├── .gitignore ├── Dockerfile ├── README.md ├── build.gradle ├── deployent.yml ├── docker-compose.yml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── nginx ├── Dockerfile └── nginx.conf ├── settings.gradle └── src ├── main ├── java │ └── com │ │ └── appcoder │ │ └── springreadyapp │ │ ├── SpringReadyAppApplication.java │ │ ├── config │ │ ├── RedisConfig.java │ │ └── SwaggerConfig.java │ │ ├── controller │ │ ├── AsyncApiController.java │ │ ├── CustomerController.java │ │ ├── DesignPatternController.java │ │ ├── MainController.java │ │ ├── MongoUserController.java │ │ ├── RedisTestController.java │ │ └── SecureUserController.java │ │ ├── domain │ │ ├── Customer.java │ │ ├── ICustomer.java │ │ ├── MongoUser.java │ │ ├── Role.java │ │ └── User.java │ │ ├── exception │ │ ├── CustomerNotFoundException.java │ │ └── MyCustomException.java │ │ ├── factoryPattern │ │ ├── Admin.java │ │ ├── BaseUser.java │ │ ├── Customer.java │ │ ├── Merchant.java │ │ ├── UserCreationRequest.java │ │ ├── UserEntity.java │ │ └── UserFactory.java │ │ ├── repository │ │ ├── CustomerRepository.java │ │ ├── MongoUserRepository.java │ │ ├── RedisCacheRepository.java │ │ ├── RedisCacheRepositoryImpl.java │ │ └── SecureUserRepository.java │ │ ├── request │ │ ├── BasicRequest.java │ │ ├── RedisCreateRequest.java │ │ ├── TransactionRequest.java │ │ └── springSecurity │ │ │ ├── LoginRequest.java │ │ │ └── SignUpRequest.java │ │ ├── response │ │ ├── BasicResponse.java │ │ ├── ResponseObject.java │ │ └── springSecurity │ │ │ ├── LoginResponse.java │ │ │ └── UserResponse.java │ │ ├── security │ │ ├── IJwtTokenProviderService.java │ │ ├── JwtTokenFilter.java │ │ ├── JwtTokenFilterConfigurer.java │ │ ├── JwtTokenProviderService.java │ │ ├── MyUserDetailsService.java │ │ └── WebSecurityConfig.java │ │ └── services │ │ ├── AsyncProgrammingService.java │ │ ├── CustomerService.java │ │ ├── CustomerServiceImpl.java │ │ ├── IAsyncProgrammingService.java │ │ ├── IMongoUserService.java │ │ ├── ISecureUserService.java │ │ ├── MongoUserServiceImpl.java │ │ ├── RedisTestService.java │ │ ├── RedisTestServiceImpl.java │ │ └── SecureUserService.java └── resources │ ├── application-main.properties │ ├── application-mongo.properties │ └── application.properties └── test └── java └── com └── appcoder └── springreadyapp ├── CustomerControllerLayerTest.java ├── CustomerRepositoryTest.java ├── CustomerServiceLayerTest.java └── SpringReadyAppApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | ARG JAR_FILE=build/libs/*.jar 3 | COPY ${JAR_FILE} springreadyapp.jar 4 | 5 | ENTRYPOINT ["java","-jar","/springreadyapp.jar"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring application for various articles 2 | 3 | After build just view http://IP/domaninName:PORT/springreadyapp/ 4 | 5 | Response will be: 6 | 7 | { 8 | "serverName": "Server 1", 9 | "ipInfo": "Your current IP address : SKM-RND-0288/192.168.3.93\nYour current Hostname : SKM-RND-0288", 10 | "dateTime": "Wed Oct 16 14:50:35 BDT 2019" 11 | } 12 | 13 | #Swagger Home: 14 | Replace Your host/IP and port 15 | http://localhost:8081/springreadyapp/swagger-ui.html#/ 16 | 17 | # Tutorial List 18 | Bellow tutorials are prepared from this codebase. You can check them out 19 | * [Deep dive on spring boot and data JPA implementation: A to Z](https://mesukcse08.medium.com/spring-data-jpa-a-to-z-6c957ed17a66) 20 | 21 | * [Locking in a distributed system using Redis JAVA](https://mesukcse08.medium.com/locking-in-a-distributed-system-using-redis-java-6d1007251d61) 22 | 23 | * [Dockerizing spring app & automating docker with Gradle]( 24 | https://medium.com/dev-genius/dockerizing-spring-app-with-gradle-3b6fbd650bf7) 25 | 26 | * [Securing Spring boot REST API with spring security, JWT, and JPA]( 27 | https://medium.com/dev-genius/securing-spring-boot-rest-api-with-spring-security-jwt-and-jpa-64ec45fb25e0) 28 | 29 | * [Spring boot, deep dive on unit testing]( 30 | https://medium.com/dev-genius/spring-boot-deep-dive-on-unit-testing-92bbdf549594) 31 | 32 | * [Scaling spring app with NGINX server and docker-compose]( 33 | https://mesukcse08.medium.com/scaling-spring-app-with-nginx-server-and-docker-compose-3fcad6257a36) 34 | 35 | * [Details implementation of java asynchronous programming using completable future]( 36 | https://medium.com/dev-genius/details-implementation-of-java-asynchronous-programming-using-completable-future-949826bac6f3) 37 | 38 | * [The Factory Method Pattern and Its Implementation in JAVA]( 39 | https://medium.com/dev-genius/the-factory-method-pattern-and-its-implementation-in-java-b51d307b8dd8) 40 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.9.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | id "com.palantir.docker" version "0.22.1" 6 | id "com.palantir.docker-run" version "0.22.1" 7 | } 8 | 9 | version '0.8' 10 | 11 | group = 'com.appcoder' 12 | sourceCompatibility = '1.8' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | 19 | docker { 20 | name "${project.name}:${project.version}" 21 | // dockerfile file('src/docker/Dockerfile') 22 | dockerfile file('Dockerfile') 23 | copySpec.from(jar).rename(".*", "springreadyapp.jar") 24 | buildArgs(['JAR_FILE': "springreadyapp.jar"]) 25 | files 'springreadyapp.jar' 26 | tag 'DockerHub', "mesuk08/springreadyapp:${project.version}" 27 | } 28 | 29 | dockerRun { 30 | name "${project.name}" 31 | image "${project.name}:${project.version}" 32 | ports '8081:8081' 33 | clean true 34 | } 35 | 36 | dependencies { 37 | implementation 'org.springframework.boot:spring-boot-starter-web' 38 | 39 | implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' 40 | implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' 41 | 42 | // Dependencies for redis 43 | compile('org.springframework.boot:spring-boot-starter-data-redis') { 44 | exclude group: 'io.lettuce', module: 'lettuce-core' 45 | } 46 | compile 'redis.clients:jedis:2.9.3' 47 | 48 | // Dependencies for JPA 49 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 50 | runtimeOnly 'com.h2database:h2' 51 | 52 | // Spring security 53 | compile 'org.springframework.boot:spring-boot-starter-security' 54 | compile 'org.springframework.security:spring-security-test' 55 | compile 'io.jsonwebtoken:jjwt:0.9.1' 56 | 57 | // testing dependencies 58 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 59 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' 60 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' 61 | testCompile('org.mockito:mockito-junit-jupiter:2.23.0') 62 | testCompile 'org.assertj:assertj-core:3.11.1' 63 | 64 | compile 'org.springframework.boot:spring-boot-starter-data-mongodb' 65 | 66 | } 67 | test { 68 | useJUnitPlatform() 69 | } 70 | -------------------------------------------------------------------------------- /deployent.yml: -------------------------------------------------------------------------------- 1 | kind: Deployment 2 | apiVersion: apps/v1 3 | metadata: 4 | name: springreadyapp 5 | spec: 6 | replicas: 2 7 | selector: 8 | matchLabels: 9 | app: springreadyapp 10 | template: 11 | metadata: 12 | labels: 13 | app: springreadyapp 14 | spec: 15 | containers: 16 | - name: springreadyapp 17 | image: mesuk08/springreadyapp:0.7 18 | imagePullPolicy: Always 19 | ports: 20 | - containerPort: 8080 21 | # readinessProbe: 22 | # httpGet: 23 | # path: /actuator/health 24 | # port: 8080 25 | # initialDelaySeconds: 5 26 | # livenessProbe: 27 | # httpGet: 28 | # path: /actuator/health 29 | # port: 8080 30 | # initialDelaySeconds: 5 31 | restartPolicy: Always 32 | --- 33 | kind: Service 34 | apiVersion: v1 35 | metadata: 36 | name: springreadyapp 37 | spec: 38 | type: NodePort 39 | ports: 40 | - port: 8080 41 | targetPort: 8080 42 | protocol: TCP 43 | nodePort: 31000 44 | selector: 45 | app: springreadyapp -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | lb: 4 | build: 5 | context: ./nginx 6 | dockerfile: Dockerfile 7 | ports: 8 | - "8081:8081" 9 | depends_on: 10 | - service1 11 | - service2 12 | - service3 13 | service1: 14 | build: 15 | context: . 16 | dockerfile: Dockerfile 17 | ports: 18 | - "8181:8080" 19 | service2: 20 | build: 21 | context: . 22 | dockerfile: Dockerfile 23 | ports: 24 | - "8182:8080" 25 | service3: 26 | build: 27 | context: . 28 | dockerfile: Dockerfile 29 | ports: 30 | - "8183:8080" -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajedul-karim/SpringReadyApp/02b0e0e1b22fa3c73aab655e85d82e4966bff8d8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jan 30 23:13:15 BDT 2021 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a baseUser-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx 2 | RUN rm /etc/nginx/conf.d/default.conf 3 | COPY nginx.conf /etc/nginx/conf.d/default.conf -------------------------------------------------------------------------------- /nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | upstream servers { 2 | # Defauld load balancing algorithm is round-robin 3 | # least_conn; : A request is sent to the server with the least number of active connections, again with server weights taken into consideration 4 | # ip_hash; : The server to which a request is sent is determined from the client IP address. In this case, either the first three octets of the IPv4 address or the whole IPv6 address are used to calculate the hash value. The method guarantees that requests from the same address get to the same server unless it is not available. 5 | 6 | server service1:8080 fail_timeout=50s max_fails=5; 7 | server service2:8080 fail_timeout=50s max_fails=5; 8 | server service3:8080 fail_timeout=50s max_fails=5; 9 | } 10 | server { 11 | listen 8081; 12 | location / { 13 | proxy_pass http://servers; 14 | } 15 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'springreadyapp' 2 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/SpringReadyAppApplication.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | 8 | @SpringBootApplication 9 | @Configuration 10 | public class SpringReadyAppApplication { 11 | 12 | public static void main(String... args) { 13 | SpringApplication.run(SpringReadyAppApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | 8 | @Configuration 9 | public class RedisConfig { 10 | 11 | @Bean 12 | JedisConnectionFactory jedisConnectionFactory() { 13 | JedisConnectionFactory jedisConFactory 14 | = new JedisConnectionFactory(); 15 | jedisConFactory.setHostName("localhost"); 16 | jedisConFactory.setPort(6379); 17 | return jedisConFactory; 18 | } 19 | 20 | @Bean 21 | public RedisTemplate redisTemplate() { 22 | RedisTemplate template = new RedisTemplate<>(); 23 | template.setConnectionFactory(jedisConnectionFactory()); 24 | return template; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; 7 | import springfox.documentation.builders.ApiInfoBuilder; 8 | import springfox.documentation.builders.PathSelectors; 9 | import springfox.documentation.builders.RequestHandlerSelectors; 10 | import springfox.documentation.service.ApiInfo; 11 | import springfox.documentation.service.ApiKey; 12 | import springfox.documentation.service.AuthorizationScope; 13 | import springfox.documentation.service.SecurityReference; 14 | import springfox.documentation.spi.DocumentationType; 15 | import springfox.documentation.spi.service.contexts.SecurityContext; 16 | import springfox.documentation.spring.web.plugins.Docket; 17 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 18 | 19 | import java.util.Arrays; 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | @Configuration 24 | @EnableSwagger2 25 | public class SwaggerConfig extends WebMvcConfigurationSupport { 26 | 27 | @Bean 28 | public Docket apiMonitoramento() { 29 | return new Docket(DocumentationType.SWAGGER_2) 30 | .select() 31 | .apis(RequestHandlerSelectors.any()) 32 | .paths(PathSelectors.any()) 33 | .build() 34 | .apiInfo(apiInfo()) 35 | .useDefaultResponseMessages(false) 36 | .securitySchemes(Collections.singletonList(apiKey())) 37 | .securityContexts(Collections.singletonList(securityContext())); 38 | } 39 | 40 | private ApiInfo apiInfo() { 41 | return new ApiInfoBuilder() 42 | .title("REST API") 43 | .description("My open source services") 44 | .build(); 45 | } 46 | 47 | @Override 48 | protected void addResourceHandlers(ResourceHandlerRegistry registry) { 49 | registry.addResourceHandler("swagger-ui.html") 50 | .addResourceLocations("classpath:/META-INF/resources/"); 51 | registry.addResourceHandler("/webjars/**") 52 | .addResourceLocations("classpath:/META-INF/resources/webjars/"); 53 | } 54 | 55 | private ApiKey apiKey() { 56 | return new ApiKey("Authorization", "Authorization", "header"); 57 | } 58 | 59 | private SecurityContext securityContext() { 60 | return SecurityContext.builder() 61 | .securityReferences(defaultAuth()) 62 | .forPaths(PathSelectors.any()) 63 | .build(); 64 | } 65 | 66 | private List defaultAuth() { 67 | AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); 68 | AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; 69 | authorizationScopes[0] = authorizationScope; 70 | return Arrays.asList(new SecurityReference("Authorization", authorizationScopes)); 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/controller/AsyncApiController.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.controller; 2 | 3 | 4 | import com.appcoder.springreadyapp.services.IAsyncProgrammingService; 5 | import io.swagger.annotations.Api; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import java.util.concurrent.ExecutionException; 13 | 14 | @RestController 15 | @RequestMapping("/asyncApi") 16 | @Api(tags = {"AsyncApiController"}) 17 | public class AsyncApiController { 18 | private IAsyncProgrammingService asyncProgrammingService; 19 | 20 | public AsyncApiController(IAsyncProgrammingService asyncProgrammingService) { 21 | this.asyncProgrammingService = asyncProgrammingService; 22 | } 23 | 24 | @GetMapping(value = "/placeOrder") 25 | public ResponseEntity placeOrder() throws RuntimeException, ExecutionException, InterruptedException { 26 | return new ResponseEntity<>(asyncProgrammingService.placeOrder(1L, 2L), HttpStatus.OK); 27 | } 28 | 29 | @GetMapping(value = "/getUserFeeds") 30 | public ResponseEntity getUserFeeds() throws RuntimeException, ExecutionException, InterruptedException { 31 | return new ResponseEntity<>(asyncProgrammingService.getUserFeeds("someemail@email.com"), HttpStatus.OK); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.controller; 2 | 3 | import com.appcoder.springreadyapp.domain.Customer; 4 | import com.appcoder.springreadyapp.domain.ICustomer; 5 | import com.appcoder.springreadyapp.exception.CustomerNotFoundException; 6 | import com.appcoder.springreadyapp.services.CustomerService; 7 | import io.swagger.annotations.Api; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.util.List; 15 | 16 | @RestController 17 | @RequestMapping("/customer") 18 | @Api(tags = {"CustomerController"}) 19 | public class CustomerController { 20 | 21 | private CustomerService customerService; 22 | 23 | public CustomerController(CustomerService customerService) { 24 | this.customerService = customerService; 25 | } 26 | 27 | @PostMapping(value = "/saveCustomer") 28 | public ResponseEntity saveCustomer(HttpServletRequest requestHeader, @RequestBody Customer request) throws RuntimeException { 29 | 30 | if (customerService.saveUpdateCustomer(request)) { 31 | return new ResponseEntity<>("Customer Save/update Done", HttpStatus.OK); 32 | 33 | } else { 34 | return new ResponseEntity<>("Customer Save/update failed", HttpStatus.OK); 35 | } 36 | } 37 | 38 | @GetMapping(value = "/fetchAllCustomer") 39 | public ResponseEntity> fetchAllCustomer() throws RuntimeException { 40 | return new ResponseEntity<>(customerService.fetchAllCustomer(), HttpStatus.OK); 41 | } 42 | 43 | @GetMapping(value = "/fetchCustomerByMobileNumber") 44 | public ResponseEntity> fetchCustomerByMobileNumber(@RequestParam String mobileNumber) throws RuntimeException { 45 | return new ResponseEntity<>(customerService.findCustomerByMobileNumber(mobileNumber), HttpStatus.OK); 46 | } 47 | 48 | @GetMapping(value = "/fetchCustomerByMobileNumberException") 49 | public ResponseEntity> fetchCustomerByMobileNumberException(@RequestParam String mobileNumber) throws CustomerNotFoundException { 50 | 51 | try{ 52 | return new ResponseEntity<>(customerService.findCustomerByMobileNumberException(mobileNumber), HttpStatus.OK); 53 | }catch (Exception e){ 54 | return new ResponseEntity<>(null, HttpStatus.NOT_FOUND); 55 | } 56 | } 57 | 58 | @GetMapping(value = "/fetchCustomerByFirstNameProjection") 59 | public ResponseEntity> fetchCustomerByFirstNameProjection(@RequestParam String firstName) throws RuntimeException { 60 | return new ResponseEntity<>(customerService.findCustomerByFirstNameProjection(firstName), HttpStatus.OK); 61 | } 62 | 63 | 64 | @GetMapping(value = "/fetchCustomerByFirstNameCustomQuery") 65 | public ResponseEntity> fetchCustomerByFirstNameCustomQuery(@RequestParam String firstName) throws RuntimeException { 66 | return new ResponseEntity<>(customerService.findCustomerByFirstNameCustomQuery(firstName), HttpStatus.OK); 67 | } 68 | 69 | @GetMapping(value = "/fetchCustomerByLastNamePagination") 70 | public ResponseEntity> fetchCustomerByLastNamePagination(@RequestParam String lastName, int pageId, int pageSize) throws RuntimeException { 71 | return new ResponseEntity<>(customerService.findCustomerByLastNamePagination(lastName, pageId, pageSize), HttpStatus.OK); 72 | } 73 | 74 | @PostMapping(value = "/deleteCustomer") 75 | public ResponseEntity deleteCustomer(HttpServletRequest requestHeader, @RequestBody Customer request) throws RuntimeException { 76 | 77 | if (customerService.deleteCustomer(request)) { 78 | return new ResponseEntity<>("Customer delete Done", HttpStatus.OK); 79 | 80 | } else { 81 | return new ResponseEntity<>("Customer delete failed", HttpStatus.OK); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/controller/DesignPatternController.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.controller; 2 | 3 | import com.appcoder.springreadyapp.factoryPattern.BaseUser; 4 | import com.appcoder.springreadyapp.factoryPattern.UserCreationRequest; 5 | import com.appcoder.springreadyapp.factoryPattern.UserFactory; 6 | import io.swagger.annotations.Api; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | 16 | @RestController 17 | @RequestMapping("/designPattern") 18 | @Api(tags = {"DesignPattern"}) 19 | public class DesignPatternController { 20 | 21 | @PostMapping(value = "/buildUser") 22 | public ResponseEntity buildUser(HttpServletRequest requestHeader, @RequestBody UserCreationRequest request) throws RuntimeException { 23 | BaseUser baseUser = UserFactory.buildUser(request); 24 | return new ResponseEntity<>(baseUser, HttpStatus.OK); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/controller/MainController.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.controller; 2 | 3 | import com.appcoder.springreadyapp.request.BasicRequest; 4 | import com.appcoder.springreadyapp.response.BasicResponse; 5 | import com.appcoder.springreadyapp.response.ResponseObject; 6 | import io.swagger.annotations.Api; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.core.env.Environment; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import java.net.InetAddress; 14 | import java.net.UnknownHostException; 15 | import java.util.Date; 16 | 17 | @RestController 18 | @RequestMapping("/main") 19 | @Api(tags = {"MainController"}) 20 | public class MainController { 21 | 22 | @Autowired 23 | private Environment environment; 24 | 25 | @RequestMapping(method = RequestMethod.GET, value="/") 26 | public ResponseEntity hello() throws UnknownHostException { 27 | ResponseObject responseObject=new ResponseObject(); 28 | 29 | InetAddress ip = InetAddress.getLocalHost(); 30 | 31 | responseObject.setServerName(ip.getHostName()); 32 | responseObject.setIpInfo("Your current IP address : " + ip); 33 | responseObject.setDateTime(new Date().toString()); 34 | return new ResponseEntity<>( 35 | responseObject, 36 | HttpStatus.OK); 37 | } 38 | 39 | @PostMapping(value = "/basicPost") 40 | public @ResponseBody 41 | ResponseEntity login(@RequestBody BasicRequest request) { 42 | String response = "Your Name :"+request.getYourName()+" , Your Age :"+request.getYourAge(); 43 | 44 | BasicResponse baseResponseObject = new BasicResponse(response, new Date().toString()); 45 | 46 | return new ResponseEntity<>(baseResponseObject, HttpStatus.OK); 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/controller/MongoUserController.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.controller; 2 | 3 | import com.appcoder.springreadyapp.domain.MongoUser; 4 | import com.appcoder.springreadyapp.services.IMongoUserService; 5 | import io.swagger.annotations.Api; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import java.util.List; 13 | 14 | @RestController 15 | @RequestMapping("/mongoUser") 16 | @Api(tags = {"MongoUserController"}) 17 | public class MongoUserController { 18 | 19 | private IMongoUserService mongoUserService; 20 | 21 | public MongoUserController(IMongoUserService mongoUserService) { 22 | this.mongoUserService = mongoUserService; 23 | } 24 | 25 | @PostMapping(value = "/saveUpdateUser") 26 | public ResponseEntity saveUpdateUser(HttpServletRequest requestHeader, @RequestBody MongoUser request) throws RuntimeException { 27 | 28 | if (mongoUserService.saveUpdateUser(request)) { 29 | return new ResponseEntity<>("MongoUser Save/update Done", HttpStatus.OK); 30 | 31 | } else { 32 | return new ResponseEntity<>("MongoUser Save/update failed", HttpStatus.OK); 33 | } 34 | } 35 | 36 | @GetMapping(value = "/fetchAllCustomer") 37 | public ResponseEntity> fetchAllCustomer() throws RuntimeException { 38 | return new ResponseEntity<>(mongoUserService.fetchAllUser(), HttpStatus.OK); 39 | } 40 | 41 | @GetMapping(value = "/fetchCustomerByMobileNumber") 42 | public ResponseEntity> fetchCustomerByMobileNumber(@RequestParam String mobileNumber) throws RuntimeException { 43 | return new ResponseEntity<>(mongoUserService.findUserByMobileNumber(mobileNumber), HttpStatus.OK); 44 | } 45 | 46 | @GetMapping(value = "/findUserByGenderNamePagination") 47 | public ResponseEntity> findUserByGenderNamePagination(@RequestParam String lastName, int pageId, int pageSize) throws RuntimeException { 48 | return new ResponseEntity<>(mongoUserService.findUserByGenderNamePagination(lastName, pageId, pageSize), HttpStatus.OK); 49 | } 50 | 51 | @PostMapping(value = "/deleteCustomer") 52 | public ResponseEntity deleteCustomer(HttpServletRequest requestHeader, @RequestBody MongoUser request) throws RuntimeException { 53 | 54 | if (mongoUserService.deleteUser(request)) { 55 | return new ResponseEntity<>("MongoUser delete Done", HttpStatus.OK); 56 | 57 | } else { 58 | return new ResponseEntity<>("MongoUser delete failed", HttpStatus.OK); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/controller/RedisTestController.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.controller; 2 | 3 | import com.appcoder.springreadyapp.request.RedisCreateRequest; 4 | import com.appcoder.springreadyapp.repository.RedisCacheRepository; 5 | import com.appcoder.springreadyapp.request.TransactionRequest; 6 | import com.appcoder.springreadyapp.services.RedisTestService; 7 | import io.swagger.annotations.Api; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | 17 | @RestController 18 | @RequestMapping("/redisTest") 19 | @Api(tags = {"RedisTestController"}) 20 | public class RedisTestController { 21 | 22 | private RedisTestService redisTestService; 23 | private RedisCacheRepository redisCacheRepository; 24 | 25 | public RedisTestController(RedisTestService redisTestService, RedisCacheRepository redisCacheRepository) { 26 | this.redisTestService = redisTestService; 27 | this.redisCacheRepository = redisCacheRepository; 28 | } 29 | 30 | @PostMapping(value = "/createTransactionNormal") 31 | public ResponseEntity createTransactionNormal(HttpServletRequest requestHeader, @RequestBody TransactionRequest request) throws RuntimeException { 32 | 33 | if(redisTestService.doTransactionNormal(request)){ 34 | return new ResponseEntity<>("Transaction done", HttpStatus.OK); 35 | 36 | }else{ 37 | return new ResponseEntity<>("Transaction failed, possible cause key already acquired", HttpStatus.OK); 38 | } 39 | } 40 | 41 | @PostMapping(value = "/createTransactionLock") 42 | public ResponseEntity createTransactionLock(HttpServletRequest requestHeader, @RequestBody TransactionRequest request) throws RuntimeException { 43 | 44 | if(redisTestService.doTransactionLock(request)){ 45 | return new ResponseEntity<>("Transaction done", HttpStatus.OK); 46 | 47 | }else{ 48 | return new ResponseEntity<>("Transaction failed, possible cause key already acquired", HttpStatus.OK); 49 | } 50 | } 51 | 52 | @PostMapping(value = "/setKey") 53 | public ResponseEntity setKey(HttpServletRequest requestHeader, @RequestBody RedisCreateRequest request) throws Exception { 54 | 55 | if(redisCacheRepository.acquireLock(request.getKey())){ 56 | return new ResponseEntity<>("Lock acquire done", HttpStatus.OK); 57 | 58 | }else{ 59 | return new ResponseEntity<>("Lock acquire failed, possible cause key already acquired", HttpStatus.OK); 60 | } 61 | } 62 | 63 | @PostMapping(value = "/evictKey") 64 | public ResponseEntity evictKey(HttpServletRequest requestHeader, @RequestBody RedisCreateRequest request) throws Exception { 65 | 66 | if(redisCacheRepository.releaseLock(request.getKey())){ 67 | return new ResponseEntity<>("Lock release done", HttpStatus.OK); 68 | 69 | }else{ 70 | return new ResponseEntity<>("Lock release failed, possible cause key not acquired YET", HttpStatus.OK); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/controller/SecureUserController.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.controller; 2 | 3 | import com.appcoder.springreadyapp.domain.User; 4 | import com.appcoder.springreadyapp.request.springSecurity.LoginRequest; 5 | import com.appcoder.springreadyapp.request.springSecurity.SignUpRequest; 6 | import com.appcoder.springreadyapp.response.springSecurity.LoginResponse; 7 | import com.appcoder.springreadyapp.response.springSecurity.UserResponse; 8 | import com.appcoder.springreadyapp.services.ISecureUserService; 9 | import io.swagger.annotations.Api; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.security.access.prepost.PreAuthorize; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.List; 17 | 18 | 19 | @RestController 20 | @RequestMapping("/secureUsers") 21 | @Api(tags = "SecureUserController") 22 | public class SecureUserController { 23 | 24 | private ISecureUserService userService; 25 | 26 | public SecureUserController(ISecureUserService userService) { 27 | this.userService = userService; 28 | } 29 | 30 | @PostMapping(value = "/public/login") 31 | public ResponseEntity login(HttpServletRequest requestHeader, @RequestBody LoginRequest request) throws RuntimeException { 32 | 33 | LoginResponse loginResponse = userService.login(request.getUserName(), request.getPassword()); 34 | if(loginResponse == null){ 35 | throw new RuntimeException("Login failed. Possible cause : incorrect username/password"); 36 | }else{ 37 | return new ResponseEntity<>(loginResponse, HttpStatus.OK); 38 | } 39 | } 40 | 41 | @PostMapping(value = "/public/signUp") 42 | public ResponseEntity signUp(HttpServletRequest requestHeader, @RequestBody SignUpRequest request) throws RuntimeException { 43 | 44 | User user; 45 | try { 46 | user = userService.signUp(request); 47 | return new ResponseEntity<>(user, HttpStatus.OK); 48 | } catch (Exception e) { 49 | throw e; 50 | } 51 | } 52 | 53 | @DeleteMapping(value = "deleteUser") 54 | @PreAuthorize("hasRole('ROLE_ADMIN')") 55 | public ResponseEntity deleteUser(@RequestParam String userName) throws RuntimeException { 56 | try { 57 | userService.removeUser(userName); 58 | } catch (Exception e) { 59 | throw e; 60 | } 61 | return new ResponseEntity<>(userName, HttpStatus.OK); 62 | } 63 | 64 | @GetMapping(value = "getAllUser") 65 | @PreAuthorize("hasRole('ROLE_ADMIN')") 66 | public ResponseEntity> getAllUser() throws RuntimeException { 67 | try { 68 | return new ResponseEntity<>(userService.getAllUser(), HttpStatus.OK); 69 | } catch (Exception e) { 70 | throw e; 71 | } 72 | 73 | } 74 | 75 | @GetMapping(value = "searchUser") 76 | @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')") 77 | public ResponseEntity searchUser(@RequestParam String userName) throws RuntimeException { 78 | 79 | UserResponse userResponse = userService.searchUser(userName); 80 | return new ResponseEntity<>(userResponse, HttpStatus.OK); 81 | } 82 | 83 | @GetMapping("/refreshToken") 84 | @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')") 85 | public String refreshToken(HttpServletRequest req) { 86 | return userService.refreshToken(req.getRemoteUser()); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/domain/Customer.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.domain; 2 | 3 | import javax.persistence.*; 4 | import java.math.BigInteger; 5 | 6 | @Entity 7 | //@Table(name = "CUSTOMER", schema = "testdb") 8 | public class Customer { 9 | 10 | private Long id; 11 | private String firstName; 12 | private String lastName; 13 | private String mobileNumber; 14 | private String presentAddress; 15 | private String permanentAddress; 16 | private String gender; 17 | 18 | public Customer() { 19 | } 20 | 21 | public Customer(Object[] col) { 22 | this.id = (col[0] != null)? ((BigInteger) col[0]).longValue() :0; 23 | this.firstName = (String) col[1]; 24 | this.lastName = (String) col[2]; 25 | this.mobileNumber = (String) col[3]; 26 | 27 | } 28 | 29 | public Customer(String firstName, String lastName, String mobileNumber) { 30 | this.firstName = firstName; 31 | this.lastName = lastName; 32 | this.mobileNumber = mobileNumber; 33 | } 34 | 35 | @Id 36 | @Column(name = "id") 37 | @GeneratedValue(strategy = GenerationType.IDENTITY) 38 | public Long getId() { 39 | return id; 40 | } 41 | 42 | public void setId(Long id) { 43 | this.id = id; 44 | } 45 | 46 | @Basic 47 | @Column(name = "first_name") 48 | public String getFirstName() { 49 | return firstName; 50 | } 51 | 52 | public void setFirstName(String firstName) { 53 | this.firstName = firstName; 54 | } 55 | 56 | @Basic 57 | @Column(name = "last_name") 58 | public String getLastName() { 59 | return lastName; 60 | } 61 | 62 | public void setLastName(String lastName) { 63 | this.lastName = lastName; 64 | } 65 | 66 | @Basic 67 | @Column(name = "mobile_number") 68 | public String getMobileNumber() { 69 | return mobileNumber; 70 | } 71 | 72 | public void setMobileNumber(String mobileNumber) { 73 | this.mobileNumber = mobileNumber; 74 | } 75 | 76 | @Basic 77 | @Column(name = "presentAddress") 78 | public String getPermanentAddress() { 79 | return presentAddress; 80 | } 81 | 82 | public void setPermanentAddress(String presentAddress) { 83 | this.presentAddress = presentAddress; 84 | } 85 | 86 | @Basic 87 | @Column(name = "permanentAddress") 88 | public String getPresentAddress() { 89 | return permanentAddress; 90 | } 91 | 92 | public void setPresentAddress(String permanentAddress) { 93 | this.permanentAddress = permanentAddress; 94 | } 95 | @Basic 96 | @Column(name = "gender") 97 | public String getGender() { 98 | return gender; 99 | } 100 | 101 | public void setGender(String gender) { 102 | this.gender = gender; 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/domain/ICustomer.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.domain; 2 | 3 | public interface ICustomer { 4 | public Long getId(); 5 | String getFirstName(); 6 | String getLastName(); 7 | public String getMobileNumber(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/domain/MongoUser.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.domain; 2 | 3 | import org.springframework.data.mongodb.core.mapping.Document; 4 | 5 | import javax.persistence.Id; 6 | 7 | @Document 8 | public class MongoUser { 9 | @Id 10 | private String id; 11 | private String userName; 12 | private String fullName; 13 | private String gender; 14 | private String mobileNumber; 15 | 16 | 17 | public MongoUser() { 18 | } 19 | 20 | public MongoUser(String id, String userName, String fullName, String gender, String mobileNumber) { 21 | this.id = id; 22 | this.userName = userName; 23 | this.fullName = fullName; 24 | this.gender = gender; 25 | this.mobileNumber = mobileNumber; 26 | } 27 | 28 | public MongoUser(String userName, String fullName, String gender, String mobileNumber) { 29 | this.userName = userName; 30 | this.fullName = fullName; 31 | this.gender = gender; 32 | this.mobileNumber = mobileNumber; 33 | } 34 | 35 | public String getId() { 36 | return id; 37 | } 38 | 39 | public void setId(String id) { 40 | this.id = id; 41 | } 42 | 43 | public String getUserName() { 44 | return userName; 45 | } 46 | 47 | public void setUserName(String userName) { 48 | this.userName = userName; 49 | } 50 | 51 | public String getFullName() { 52 | return fullName; 53 | } 54 | 55 | public void setFullName(String fullName) { 56 | this.fullName = fullName; 57 | } 58 | 59 | public String getGender() { 60 | return gender; 61 | } 62 | 63 | public void setGender(String gender) { 64 | this.gender = gender; 65 | } 66 | 67 | public String getMobileNumber() { 68 | return mobileNumber; 69 | } 70 | 71 | public void setMobileNumber(String mobileNumber) { 72 | this.mobileNumber = mobileNumber; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/domain/Role.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.domain; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | 5 | public enum Role implements GrantedAuthority { 6 | ROLE_ADMIN, ROLE_CLIENT; 7 | 8 | public String getAuthority() { 9 | return name(); 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.domain; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.ElementCollection; 7 | import javax.persistence.Entity; 8 | import javax.persistence.FetchType; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.GenerationType; 11 | import javax.persistence.Id; 12 | import javax.validation.constraints.Size; 13 | 14 | @Entity 15 | public class User { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | private Integer id; 20 | 21 | @Size(min = 4, max = 255, message = "Minimum username length: 4 characters") 22 | @Column(unique = true, nullable = false) 23 | private String username; 24 | 25 | @Column(unique = true, nullable = false) 26 | private String email; 27 | 28 | @Size(min = 4, message = "Minimum password length: 4 characters") 29 | private String password; 30 | 31 | @ElementCollection(fetch = FetchType.EAGER) 32 | List roles; 33 | 34 | public Integer getId() { 35 | return id; 36 | } 37 | 38 | public void setId(Integer id) { 39 | this.id = id; 40 | } 41 | 42 | public String getUsername() { 43 | return username; 44 | } 45 | 46 | public void setUsername(String username) { 47 | this.username = username; 48 | } 49 | 50 | public String getEmail() { 51 | return email; 52 | } 53 | 54 | public void setEmail(String email) { 55 | this.email = email; 56 | } 57 | 58 | public String getPassword() { 59 | return password; 60 | } 61 | 62 | public void setPassword(String password) { 63 | this.password = password; 64 | } 65 | 66 | public List getRoles() { 67 | return roles; 68 | } 69 | 70 | public void setRoles(List roles) { 71 | this.roles = roles; 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/exception/CustomerNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.exception; 2 | 3 | public class CustomerNotFoundException extends Exception { 4 | 5 | public CustomerNotFoundException() { 6 | } 7 | 8 | public CustomerNotFoundException(String message) { 9 | super(message); 10 | } 11 | 12 | public CustomerNotFoundException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public CustomerNotFoundException(Throwable cause) { 17 | super(cause); 18 | } 19 | 20 | public CustomerNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 21 | super(message, cause, enableSuppression, writableStackTrace); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/exception/MyCustomException.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | public class MyCustomException extends RuntimeException { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | private final String message; 10 | private final HttpStatus httpStatus; 11 | 12 | public MyCustomException(String message, HttpStatus httpStatus) { 13 | this.message = message; 14 | this.httpStatus = httpStatus; 15 | } 16 | 17 | @Override 18 | public String getMessage() { 19 | return message; 20 | } 21 | 22 | public HttpStatus getHttpStatus() { 23 | return httpStatus; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/factoryPattern/Admin.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.factoryPattern; 2 | 3 | public class Admin extends BaseUser { 4 | private String email; 5 | private String password; 6 | 7 | public Admin(UserCreationRequest userCreationRequest) { 8 | System.out.println(); 9 | 10 | System.out.println("Building Admin"); 11 | 12 | if(userCreationRequest.getPassword() == null || userCreationRequest.getPassword().trim().length()<8){ 13 | System.out.println("Please provide valid Password"); 14 | throw new RuntimeException("Please provide valid Password"); 15 | } 16 | 17 | if(userCreationRequest.getEmail() == null ){ 18 | System.out.println("Please provide valid email address"); 19 | throw new RuntimeException("Please provide valid email address"); 20 | } 21 | 22 | setCommonData(userCreationRequest.getFullName(),userCreationRequest.getMobileNumber(), userCreationRequest.getGender(), userCreationRequest.getUserType()); 23 | this.password = userCreationRequest.getPassword(); 24 | this.email = userCreationRequest.getEmail(); 25 | 26 | System.out.println("Admin building done"); 27 | 28 | } 29 | 30 | public String getEmail() { 31 | return email; 32 | } 33 | 34 | public String getPassword() { 35 | return password; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/factoryPattern/BaseUser.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.factoryPattern; 2 | 3 | public abstract class BaseUser { 4 | private String fullName; 5 | private String mobileNumber; 6 | private String gender; 7 | private String userType; 8 | 9 | public BaseUser() { 10 | } 11 | 12 | public void setCommonData(String fullName, String mobileNumber, String gender, String userType){ 13 | this.fullName = fullName; 14 | this.mobileNumber = mobileNumber; 15 | this.gender = gender; 16 | this.userType = userType; 17 | 18 | } 19 | 20 | public String getFullName() { 21 | return fullName; 22 | } 23 | 24 | public String getMobileNumber() { 25 | return mobileNumber; 26 | } 27 | 28 | public String getGender() { 29 | return gender; 30 | } 31 | 32 | public String getUserType() { 33 | return userType; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/factoryPattern/Customer.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.factoryPattern; 2 | 3 | public class Customer extends BaseUser { 4 | private String pin; 5 | 6 | public Customer(UserCreationRequest userCreationRequest) { 7 | System.out.println(); 8 | 9 | System.out.println("Building customer"); 10 | if(userCreationRequest.getPin() == null || userCreationRequest.getPin().trim().length()!=4){ 11 | System.out.println("Please provide valid PIN"); 12 | throw new RuntimeException("Please provide valid PIN"); 13 | } 14 | setCommonData(userCreationRequest.getFullName(),userCreationRequest.getMobileNumber(), userCreationRequest.getGender(), userCreationRequest.getUserType()); 15 | this.pin = userCreationRequest.getPin(); 16 | System.out.println("Customer building done"); 17 | 18 | } 19 | 20 | public String getPin() { 21 | return pin; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/factoryPattern/Merchant.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.factoryPattern; 2 | 3 | public class Merchant extends BaseUser { 4 | private String password; 5 | private String bankAccountNumber; 6 | private String bankName; 7 | private String routingNumber; 8 | 9 | public Merchant(UserCreationRequest userCreationRequest) { 10 | System.out.println(); 11 | System.out.println("Building merchant"); 12 | 13 | if(userCreationRequest.getPassword() == null || userCreationRequest.getPassword().trim().length()<8){ 14 | System.out.println("Please provide valid Password"); 15 | throw new RuntimeException("Please provide valid Password"); 16 | } 17 | 18 | if(userCreationRequest.getBankAccountNumber() == null ){ 19 | System.out.println("Please provide valid bank account number"); 20 | throw new RuntimeException("Please provide valid bank account number"); 21 | } 22 | 23 | setCommonData(userCreationRequest.getFullName(),userCreationRequest.getMobileNumber(), userCreationRequest.getGender(), userCreationRequest.getUserType()); 24 | this.password = userCreationRequest.getPassword(); 25 | this.bankAccountNumber = userCreationRequest.getBankAccountNumber(); 26 | this.bankName = userCreationRequest.getBankName(); 27 | this.routingNumber = userCreationRequest.getRoutingNumber(); 28 | System.out.println("Merchant building done"); 29 | 30 | } 31 | 32 | public String getPassword() { 33 | return password; 34 | } 35 | 36 | public String getBankAccountNumber() { 37 | return bankAccountNumber; 38 | } 39 | 40 | public String getBankName() { 41 | return bankName; 42 | } 43 | 44 | public String getRoutingNumber() { 45 | return routingNumber; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/factoryPattern/UserCreationRequest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.factoryPattern; 2 | 3 | public class UserCreationRequest { 4 | private String fullName; 5 | private String mobileNumber; 6 | private String gender; 7 | private String pin; 8 | private String password; 9 | private String bankAccountNumber; 10 | private String bankName; 11 | private String routingNumber; 12 | private String email; 13 | private String userType; 14 | 15 | public String getFullName() { 16 | return fullName; 17 | } 18 | 19 | public void setFullName(String fullName) { 20 | this.fullName = fullName; 21 | } 22 | 23 | public String getMobileNumber() { 24 | return mobileNumber; 25 | } 26 | 27 | public void setMobileNumber(String mobileNumber) { 28 | this.mobileNumber = mobileNumber; 29 | } 30 | 31 | public String getGender() { 32 | return gender; 33 | } 34 | 35 | public void setGender(String gender) { 36 | this.gender = gender; 37 | } 38 | 39 | public String getPin() { 40 | return pin; 41 | } 42 | 43 | public void setPin(String pin) { 44 | this.pin = pin; 45 | } 46 | 47 | public String getPassword() { 48 | return password; 49 | } 50 | 51 | public void setPassword(String password) { 52 | this.password = password; 53 | } 54 | 55 | public String getBankAccountNumber() { 56 | return bankAccountNumber; 57 | } 58 | 59 | public void setBankAccountNumber(String bankAccountNumber) { 60 | this.bankAccountNumber = bankAccountNumber; 61 | } 62 | 63 | public String getBankName() { 64 | return bankName; 65 | } 66 | 67 | public void setBankName(String bankName) { 68 | this.bankName = bankName; 69 | } 70 | 71 | public String getRoutingNumber() { 72 | return routingNumber; 73 | } 74 | 75 | public void setRoutingNumber(String routingNumber) { 76 | this.routingNumber = routingNumber; 77 | } 78 | 79 | public String getEmail() { 80 | return email; 81 | } 82 | 83 | public void setEmail(String email) { 84 | this.email = email; 85 | } 86 | 87 | public String getUserType() { 88 | return userType; 89 | } 90 | 91 | public void setUserType(String userType) { 92 | this.userType = userType; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/factoryPattern/UserEntity.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.factoryPattern; 2 | 3 | public class UserEntity { 4 | private Long id; 5 | private String fullName; 6 | private String mobileNumber; 7 | private String gender; 8 | private String pin; 9 | private String password; 10 | private String bankAccountNumber; 11 | private String bankName; 12 | private String routingNumber; 13 | private String email; 14 | private String userType; 15 | 16 | public Long getId() { 17 | return id; 18 | } 19 | 20 | public void setId(Long id) { 21 | this.id = id; 22 | } 23 | 24 | public String getFullName() { 25 | return fullName; 26 | } 27 | 28 | public void setFullName(String fullName) { 29 | this.fullName = fullName; 30 | } 31 | 32 | public String getMobileNumber() { 33 | return mobileNumber; 34 | } 35 | 36 | public void setMobileNumber(String mobileNumber) { 37 | this.mobileNumber = mobileNumber; 38 | } 39 | 40 | public String getGender() { 41 | return gender; 42 | } 43 | 44 | public void setGender(String gender) { 45 | this.gender = gender; 46 | } 47 | 48 | public String getPin() { 49 | return pin; 50 | } 51 | 52 | public void setPin(String pin) { 53 | this.pin = pin; 54 | } 55 | 56 | public String getPassword() { 57 | return password; 58 | } 59 | 60 | public void setPassword(String password) { 61 | this.password = password; 62 | } 63 | 64 | public String getBankAccountNumber() { 65 | return bankAccountNumber; 66 | } 67 | 68 | public void setBankAccountNumber(String bankAccountNumber) { 69 | this.bankAccountNumber = bankAccountNumber; 70 | } 71 | 72 | public String getBankName() { 73 | return bankName; 74 | } 75 | 76 | public void setBankName(String bankName) { 77 | this.bankName = bankName; 78 | } 79 | 80 | public String getRoutingNumber() { 81 | return routingNumber; 82 | } 83 | 84 | public void setRoutingNumber(String routingNumber) { 85 | this.routingNumber = routingNumber; 86 | } 87 | 88 | public String getEmail() { 89 | return email; 90 | } 91 | 92 | public void setEmail(String email) { 93 | this.email = email; 94 | } 95 | 96 | public String getUserType() { 97 | return userType; 98 | } 99 | 100 | public void setUserType(String userType) { 101 | this.userType = userType; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/factoryPattern/UserFactory.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.factoryPattern; 2 | 3 | public class UserFactory { 4 | private static final String USER_TYPE_CUSTOMER = "1"; 5 | private static final String USER_TYPE_MERCHANT = "2"; 6 | private static final String USER_TYPE_ADMIN = "3"; 7 | 8 | public static BaseUser buildUser(UserCreationRequest userCreationRequest) { 9 | BaseUser baseUser; 10 | switch (userCreationRequest.getUserType()) { 11 | case USER_TYPE_CUSTOMER: 12 | baseUser = new Customer(userCreationRequest); 13 | break; 14 | case USER_TYPE_MERCHANT: 15 | baseUser = new Merchant(userCreationRequest); 16 | break; 17 | case USER_TYPE_ADMIN: 18 | baseUser = new Admin(userCreationRequest); 19 | break; 20 | default: 21 | throw new RuntimeException("Invalid user type provided"); 22 | } 23 | return baseUser; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/repository/CustomerRepository.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.repository; 2 | 3 | import com.appcoder.springreadyapp.domain.Customer; 4 | import com.appcoder.springreadyapp.domain.ICustomer; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.repository.CrudRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | 12 | @Repository 13 | public interface CustomerRepository extends CrudRepository { 14 | @Override 15 | List findAll(); 16 | 17 | List findAllByMobileNumber(String mobileNumber); 18 | List findAllByFirstName(String firstName); 19 | Page findAllByLastName(String lastName, Pageable pageable); 20 | 21 | void deleteById(Long id); 22 | long countAllByFirstName(String firstName); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/repository/MongoUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.repository; 2 | 3 | import com.appcoder.springreadyapp.domain.MongoUser; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.mongodb.repository.MongoRepository; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | @Repository 12 | public interface MongoUserRepository extends MongoRepository { 13 | 14 | Long countAllByUserName(String userName); 15 | 16 | List findAllByMobileNumber(String mobileNumber); 17 | 18 | Page findAllByMobileNumber(String mobileNumber, Pageable pageable); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/repository/RedisCacheRepository.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.repository; 2 | 3 | public interface RedisCacheRepository { 4 | public boolean isTransactionRunningForSender(String key); 5 | void makeSenderBusyForTransactionNormal(String key); 6 | void makeSenderFreeForTransactionNormal(String key); 7 | 8 | public boolean acquireLock(String key); 9 | public boolean releaseLock(String key); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/repository/RedisCacheRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.repository; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.data.redis.connection.jedis.JedisConnection; 6 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 7 | import org.springframework.stereotype.Service; 8 | import redis.clients.jedis.Jedis; 9 | 10 | import java.util.Collections; 11 | 12 | @Service 13 | public class RedisCacheRepositoryImpl implements RedisCacheRepository { 14 | 15 | private static Log log = LogFactory.getLog(RedisCacheRepositoryImpl.class); 16 | private static String SET_SUCCESS = "OK"; 17 | private static String KEY_PRE = "REDIS_LOCK_"; 18 | private Integer dbIndex = 15; 19 | 20 | private Integer lockExpireTimeSeconds = 120 * 1000; 21 | 22 | JedisConnectionFactory jedisConnectionFactory; 23 | JedisConnection jedisConnection; 24 | 25 | 26 | public RedisCacheRepositoryImpl(JedisConnectionFactory jedisConnectionFactory) { 27 | this.jedisConnectionFactory = jedisConnectionFactory; 28 | } 29 | 30 | 31 | @Override 32 | public boolean isTransactionRunningForSender(String key) { 33 | Jedis jedis = null; 34 | try { 35 | jedis = getRedis(); 36 | key = KEY_PRE + key; 37 | String value = fetchLockValue(key); 38 | if (jedis.get(key) != null) { 39 | log.info("Transaction Running for : " + key); 40 | return true; 41 | } else { 42 | log.info("Transaction not Running for : " + key); 43 | } 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } finally { 47 | if (jedis != null) { 48 | jedis.close(); 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | 55 | @Override 56 | public void makeSenderBusyForTransactionNormal(String key) { 57 | Jedis jedis = null; 58 | try { 59 | jedis = getRedis(); 60 | key = KEY_PRE + key; 61 | String value = fetchLockValue(key); 62 | if (SET_SUCCESS.equals(jedis.set(key, value))) { 63 | log.info("Sender made busy done for key : " + key + ",value : " + value); 64 | } else { 65 | log.info("Sender made busy failed for key : " + key + ",value : " + value); 66 | } 67 | } catch (Exception e) { 68 | e.printStackTrace(); 69 | } finally { 70 | if (jedis != null) { 71 | jedis.close(); 72 | } 73 | } 74 | } 75 | 76 | @Override 77 | public void makeSenderFreeForTransactionNormal(String key) { 78 | Long RELEASE_SUCCESS = 1L; 79 | Jedis jedis = null; 80 | try { 81 | jedis = getRedis(); 82 | key = KEY_PRE + key; 83 | String value = fetchLockValue(key); 84 | String command = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end"; 85 | if (RELEASE_SUCCESS.equals(jedis.eval(command, Collections.singletonList(key), Collections.singletonList(value)))) { 86 | log.info("Sender release done : " + key + ",value : " + value); 87 | } else { 88 | log.error("Sender release failed, possible cause key not acquired YET : " + key); 89 | } 90 | 91 | } catch (Exception e) { 92 | e.printStackTrace(); 93 | } finally { 94 | if (jedis != null) { 95 | jedis.close(); 96 | } 97 | } 98 | } 99 | 100 | @Override 101 | public boolean acquireLock(String key) { 102 | Jedis jedis = null; 103 | try { 104 | jedis = getRedis(); 105 | key = KEY_PRE + key; 106 | String value = fetchLockValue(key); 107 | if (SET_SUCCESS.equals(jedis.set(key, value, "NX", "EX", lockExpireTimeSeconds))) { 108 | log.info("Reids Lock acquire done key : " + key + ",value : " + value); 109 | return true; 110 | } else { 111 | log.error("Reids Lock acquire failed key, possible cause key already acquired : " + key + ",value : " + value); 112 | } 113 | } catch (Exception e) { 114 | e.printStackTrace(); 115 | } finally { 116 | if (jedis != null) { 117 | jedis.close(); 118 | } 119 | } 120 | return false; 121 | } 122 | 123 | @Override 124 | public boolean releaseLock(String key) { 125 | Long RELEASE_SUCCESS = 1L; 126 | Jedis jedis = null; 127 | try { 128 | jedis = getRedis(); 129 | key = KEY_PRE + key; 130 | String value = fetchLockValue(key); 131 | String command = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end"; 132 | if (RELEASE_SUCCESS.equals(jedis.eval(command, Collections.singletonList(key), Collections.singletonList(value)))) { 133 | log.info("Reids Lock key release done : " + key + ",value : " + value); 134 | return true; 135 | } else { 136 | log.error("Reids Lock key release failed, possible cause key not acquired YET : " + key); 137 | } 138 | 139 | } catch (Exception e) { 140 | e.printStackTrace(); 141 | } finally { 142 | if (jedis != null) { 143 | jedis.close(); 144 | } 145 | } 146 | return false; 147 | } 148 | 149 | 150 | private String fetchLockValue(String key) { 151 | return "VALUE_" + key; 152 | } 153 | 154 | private Jedis getRedis() { 155 | jedisConnection = (JedisConnection) jedisConnectionFactory.getConnection(); 156 | Jedis jedis = jedisConnection.getJedis(); 157 | jedis.select(dbIndex); 158 | return jedis; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/repository/SecureUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.repository; 2 | 3 | 4 | import javax.transaction.Transactional; 5 | 6 | import com.appcoder.springreadyapp.domain.User; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | @Repository 12 | public interface SecureUserRepository extends JpaRepository { 13 | 14 | boolean existsByUsername(String username); 15 | 16 | User findByUsername(String username); 17 | 18 | @Transactional 19 | void deleteByUsername(String username); 20 | 21 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/request/BasicRequest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.request; 2 | 3 | public class BasicRequest { 4 | private String yourName; 5 | private String yourAge; 6 | 7 | public BasicRequest() { 8 | } 9 | 10 | public String getYourName() { 11 | return yourName; 12 | } 13 | 14 | public void setYourName(String yourName) { 15 | this.yourName = yourName; 16 | } 17 | 18 | public String getYourAge() { 19 | return yourAge; 20 | } 21 | 22 | public void setYourAge(String yourAge) { 23 | this.yourAge = yourAge; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/request/RedisCreateRequest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.request; 2 | 3 | public class RedisCreateRequest { 4 | private String key; 5 | 6 | public String getKey() { 7 | return key; 8 | } 9 | 10 | public void setKey(String key) { 11 | this.key = key; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/request/TransactionRequest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.request; 2 | 3 | public class TransactionRequest { 4 | private Long senderWalletId; 5 | private Long receiverWalletId; 6 | private Double transactionAmount; 7 | 8 | public Long getSenderWalletId() { 9 | return senderWalletId; 10 | } 11 | 12 | public void setSenderWalletId(Long senderWalletId) { 13 | this.senderWalletId = senderWalletId; 14 | } 15 | 16 | public Long getReceiverWalletId() { 17 | return receiverWalletId; 18 | } 19 | 20 | public void setReceiverWalletId(Long receiverWalletId) { 21 | this.receiverWalletId = receiverWalletId; 22 | } 23 | 24 | public Double getTransactionAmount() { 25 | return transactionAmount; 26 | } 27 | 28 | public void setTransactionAmount(Double transactionAmount) { 29 | this.transactionAmount = transactionAmount; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/request/springSecurity/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.request.springSecurity; 2 | 3 | public class LoginRequest { 4 | private String userName; 5 | private String password; 6 | 7 | public String getUserName() { 8 | return userName; 9 | } 10 | 11 | public void setUserName(String userName) { 12 | this.userName = userName; 13 | } 14 | 15 | public String getPassword() { 16 | return password; 17 | } 18 | 19 | public void setPassword(String password) { 20 | this.password = password; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/request/springSecurity/SignUpRequest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.request.springSecurity; 2 | 3 | import com.appcoder.springreadyapp.domain.Role; 4 | 5 | import java.util.List; 6 | 7 | public class SignUpRequest { 8 | private String userName; 9 | private String email; 10 | private String password; 11 | private List roles; 12 | 13 | public String getUserName() { 14 | return userName; 15 | } 16 | 17 | public void setUserName(String userName) { 18 | this.userName = userName; 19 | } 20 | 21 | public String getEmail() { 22 | return email; 23 | } 24 | 25 | public void setEmail(String email) { 26 | this.email = email; 27 | } 28 | 29 | public String getPassword() { 30 | return password; 31 | } 32 | 33 | public void setPassword(String password) { 34 | this.password = password; 35 | } 36 | 37 | public List getRoles() { 38 | return roles; 39 | } 40 | 41 | public void setRoles(List roles) { 42 | this.roles = roles; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/response/BasicResponse.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.response; 2 | 3 | 4 | public class BasicResponse { 5 | private String response; 6 | private String dateTime; 7 | 8 | 9 | public BasicResponse(String response, String dateTime) { 10 | this.response = response; 11 | this.dateTime = dateTime; 12 | } 13 | 14 | public String getResponse() { 15 | return response; 16 | } 17 | 18 | public void setResponse(String response) { 19 | this.response = response; 20 | } 21 | 22 | public String getDateTime() { 23 | return dateTime; 24 | } 25 | 26 | public void setDateTime(String dateTime) { 27 | this.dateTime = dateTime; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/response/ResponseObject.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.response; 2 | 3 | public class ResponseObject { 4 | private String serverName; 5 | private String ipInfo; 6 | private String dateTime; 7 | 8 | public String getServerName() { 9 | return serverName; 10 | } 11 | 12 | public void setServerName(String serverName) { 13 | this.serverName = serverName; 14 | } 15 | 16 | public String getIpInfo() { 17 | return ipInfo; 18 | } 19 | 20 | public void setIpInfo(String ipInfo) { 21 | this.ipInfo = ipInfo; 22 | } 23 | 24 | public String getDateTime() { 25 | return dateTime; 26 | } 27 | 28 | public void setDateTime(String dateTime) { 29 | this.dateTime = dateTime; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/response/springSecurity/LoginResponse.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.response.springSecurity; 2 | 3 | public class LoginResponse { 4 | private String userName; 5 | private String email; 6 | private String accessToken; 7 | 8 | public String getUserName() { 9 | return userName; 10 | } 11 | 12 | public void setUserName(String userName) { 13 | this.userName = userName; 14 | } 15 | 16 | public String getEmail() { 17 | return email; 18 | } 19 | 20 | public void setEmail(String email) { 21 | this.email = email; 22 | } 23 | 24 | public String getAccessToken() { 25 | return accessToken; 26 | } 27 | 28 | public void setAccessToken(String accessToken) { 29 | this.accessToken = accessToken; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/response/springSecurity/UserResponse.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.response.springSecurity; 2 | 3 | public class UserResponse { 4 | private String userName; 5 | private String email; 6 | 7 | public String getUserName() { 8 | return userName; 9 | } 10 | 11 | public void setUserName(String userName) { 12 | this.userName = userName; 13 | } 14 | 15 | public String getEmail() { 16 | return email; 17 | } 18 | 19 | public void setEmail(String email) { 20 | this.email = email; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/security/IJwtTokenProviderService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.security; 2 | 3 | import com.appcoder.springreadyapp.domain.Role; 4 | import org.springframework.security.core.Authentication; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import java.util.List; 8 | 9 | public interface IJwtTokenProviderService { 10 | String createToken(String username, List roles); 11 | Authentication validateUserAndGetAuthentication(String token); 12 | String getUsername(String token); 13 | String parseToken(HttpServletRequest req); 14 | boolean validateToken(String token); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/security/JwtTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.security; 2 | 3 | 4 | import com.appcoder.springreadyapp.exception.MyCustomException; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.context.SecurityContextHolder; 7 | import org.springframework.web.filter.OncePerRequestFilter; 8 | 9 | import javax.servlet.FilterChain; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | public class JwtTokenFilter extends OncePerRequestFilter { 16 | 17 | private IJwtTokenProviderService jwtTokenProviderService; 18 | 19 | 20 | public JwtTokenFilter(IJwtTokenProviderService jwtTokenProviderService) { 21 | this.jwtTokenProviderService = jwtTokenProviderService; 22 | } 23 | 24 | @Override 25 | protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { 26 | String token = jwtTokenProviderService.parseToken(httpServletRequest); 27 | try { 28 | if (token != null && jwtTokenProviderService.validateToken(token)) { 29 | Authentication auth = jwtTokenProviderService.validateUserAndGetAuthentication(token); 30 | SecurityContextHolder.getContext().setAuthentication(auth); 31 | } 32 | } catch (MyCustomException ex) { 33 | SecurityContextHolder.clearContext(); 34 | httpServletResponse.sendError(ex.getHttpStatus().value(), ex.getMessage()); 35 | return; 36 | } 37 | 38 | filterChain.doFilter(httpServletRequest, httpServletResponse); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/security/JwtTokenFilterConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.security; 2 | 3 | 4 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter; 5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 | import org.springframework.security.web.DefaultSecurityFilterChain; 7 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 8 | 9 | public class JwtTokenFilterConfigurer extends SecurityConfigurerAdapter { 10 | 11 | private IJwtTokenProviderService jwtTokenProviderService; 12 | 13 | public JwtTokenFilterConfigurer(IJwtTokenProviderService jwtTokenProviderService) { 14 | this.jwtTokenProviderService = jwtTokenProviderService; 15 | } 16 | 17 | @Override 18 | public void configure(HttpSecurity http) throws Exception { 19 | JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProviderService); 20 | http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/security/JwtTokenProviderService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.security; 2 | 3 | import com.appcoder.springreadyapp.domain.Role; 4 | import com.appcoder.springreadyapp.exception.MyCustomException; 5 | import io.jsonwebtoken.Claims; 6 | import io.jsonwebtoken.JwtException; 7 | import io.jsonwebtoken.Jwts; 8 | import io.jsonwebtoken.SignatureAlgorithm; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 11 | import org.springframework.security.core.Authentication; 12 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.stereotype.Service; 15 | 16 | import javax.annotation.PostConstruct; 17 | import javax.servlet.http.HttpServletRequest; 18 | import java.util.Base64; 19 | import java.util.Date; 20 | import java.util.List; 21 | import java.util.Objects; 22 | import java.util.stream.Collectors; 23 | 24 | @Service 25 | public class JwtTokenProviderService implements IJwtTokenProviderService { 26 | 27 | private String secretKey = "MY_SECRET_KEY"; 28 | 29 | private long validityInMilliseconds = 3600000; // 1h 30 | 31 | private MyUserDetailsService myUserDetailsService; 32 | 33 | @PostConstruct 34 | protected void init() { 35 | secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); 36 | } 37 | 38 | public JwtTokenProviderService(MyUserDetailsService myUserDetailsService) { 39 | this.myUserDetailsService = myUserDetailsService; 40 | } 41 | 42 | @Override 43 | public String createToken(String userName, List roles) { 44 | Claims claims = Jwts.claims().setSubject(userName); 45 | claims.put("auth", roles.stream().map(s -> new SimpleGrantedAuthority(s.getAuthority())).filter(Objects::nonNull).collect(Collectors.toList())); 46 | 47 | Date now = new Date(); 48 | Date validity = new Date(now.getTime() + validityInMilliseconds); 49 | 50 | return Jwts.builder() 51 | .setClaims(claims) 52 | .setIssuedAt(now) 53 | .setExpiration(validity) 54 | .signWith(SignatureAlgorithm.HS256, secretKey) 55 | .compact(); 56 | } 57 | 58 | @Override 59 | public Authentication validateUserAndGetAuthentication(String token) { 60 | UserDetails userDetails = myUserDetailsService.loadUserByUsername(getUsername(token)); 61 | return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); 62 | } 63 | 64 | @Override 65 | public String getUsername(String token) { 66 | return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); 67 | } 68 | 69 | @Override 70 | public String parseToken(HttpServletRequest req) { 71 | String bearerToken = req.getHeader("Authorization"); 72 | if (bearerToken != null && bearerToken.startsWith("Bearer ")) { 73 | return bearerToken.substring(7); 74 | } 75 | return null; 76 | } 77 | 78 | @Override 79 | public boolean validateToken(String token) { 80 | try { 81 | Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); 82 | return true; 83 | } catch (JwtException | IllegalArgumentException e) { 84 | throw new MyCustomException("Expired or invalid JWT token", HttpStatus.INTERNAL_SERVER_ERROR); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/security/MyUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.security; 2 | 3 | import com.appcoder.springreadyapp.domain.User; 4 | import com.appcoder.springreadyapp.repository.SecureUserRepository; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.stereotype.Service; 9 | 10 | 11 | @Service 12 | public class MyUserDetailsService implements UserDetailsService { 13 | 14 | private SecureUserRepository secureUserRepository; 15 | 16 | public MyUserDetailsService(SecureUserRepository secureUserRepository) { 17 | this.secureUserRepository = secureUserRepository; 18 | } 19 | 20 | @Override 21 | public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { 22 | final User user = secureUserRepository.findByUsername(userName); 23 | 24 | if (user == null) { 25 | throw new UsernameNotFoundException("User '" + userName + "' not found"); 26 | } 27 | 28 | return org.springframework.security.core.userdetails.User 29 | .withUsername(userName) 30 | .password(user.getPassword()) 31 | .authorities(user.getRoles()) 32 | .accountExpired(false) 33 | .accountLocked(false) 34 | .credentialsExpired(false) 35 | .disabled(false) 36 | .build(); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/security/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.security; 2 | 3 | 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.authentication.AuthenticationManager; 7 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.config.http.SessionCreationPolicy; 13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 | import org.springframework.security.crypto.password.PasswordEncoder; 15 | 16 | @Configuration 17 | @EnableWebSecurity 18 | @EnableGlobalMethodSecurity(prePostEnabled = true) 19 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 20 | 21 | private IJwtTokenProviderService jwtTokenProviderService; 22 | 23 | public WebSecurityConfig(IJwtTokenProviderService jwtTokenProviderService) { 24 | this.jwtTokenProviderService = jwtTokenProviderService; 25 | } 26 | 27 | @Override 28 | protected void configure(HttpSecurity http) throws Exception { 29 | 30 | http.csrf().disable() 31 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 32 | 33 | // Entry points 34 | http.authorizeRequests() 35 | .antMatchers("/main/**/").permitAll() 36 | .antMatchers("/customer/**/").permitAll() 37 | .antMatchers("/mongoUser/**/").permitAll() 38 | .antMatchers("/designPattern/**/").permitAll() 39 | .antMatchers("/asyncApi/**/").permitAll() 40 | .antMatchers("/secureUsers/public/**/").permitAll() 41 | .antMatchers("/redisTest/**/").permitAll() 42 | .antMatchers("/h2-console/**/**").permitAll() 43 | .anyRequest().authenticated(); 44 | 45 | // If a user try to access a resource without having enough permissions 46 | http.exceptionHandling().accessDeniedPage("/accessDeniedPage"); 47 | 48 | // Apply JWT 49 | http.apply(new JwtTokenFilterConfigurer(jwtTokenProviderService)); 50 | } 51 | 52 | @Override 53 | public void configure(WebSecurity web) throws Exception { 54 | // Allow swagger to be accessed without authentication 55 | web.ignoring().antMatchers("/v2/api-docs")// 56 | .antMatchers("/swagger-resources/**")// 57 | .antMatchers("/swagger-ui.html")// 58 | .antMatchers("/configuration/**")// 59 | .antMatchers("/webjars/**")// 60 | .antMatchers("/public") 61 | 62 | // Un-secure H2 Database (for testing purposes, H2 console shouldn't be unprotected in production) 63 | .and() 64 | .ignoring() 65 | .antMatchers("/h2-console/**/**");; 66 | } 67 | 68 | @Bean 69 | public PasswordEncoder passwordEncoder() { 70 | return new BCryptPasswordEncoder(12); 71 | } 72 | 73 | @Override 74 | @Bean 75 | public AuthenticationManager authenticationManagerBean() throws Exception { 76 | return authenticationManager(); 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/AsyncProgrammingService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.stereotype.Service; 6 | 7 | import java.util.concurrent.*; 8 | 9 | @Service 10 | public class AsyncProgrammingService implements IAsyncProgrammingService { 11 | private static Log log = LogFactory.getLog(AsyncProgrammingService.class); 12 | 13 | @Override 14 | public void sendNotification(String emailId) throws ExecutionException, InterruptedException { 15 | 16 | CompletableFuture futureNotificationNormal = CompletableFuture.runAsync(new Runnable() { 17 | @Override 18 | public void run() { 19 | System.out.println("We are sending notification via notification service: runnable implementation"); 20 | sendNotification(emailId, "hello"); 21 | } 22 | }); 23 | futureNotificationNormal.get(); 24 | 25 | Executor executor = Executors.newFixedThreadPool(10); 26 | CompletableFuture futureNotificationExecutor = CompletableFuture.runAsync(new Runnable() { 27 | @Override 28 | public void run() { 29 | // Simulating a long-running Job 30 | sendNotification(emailId, "hello"); 31 | System.out.println("We are sending notification via notification service: executor implementation"); 32 | } 33 | }, executor); 34 | futureNotificationExecutor.get(); 35 | } 36 | 37 | @Override 38 | public String customerWalletBalance(String emailId) throws ExecutionException, InterruptedException { 39 | 40 | CompletableFuture> balanceFuture = fetchWalletId(emailId) 41 | .thenApply(walletId -> loadWalletBalance(walletId)); 42 | 43 | return "Wallet Balance : " + balanceFuture.get(); 44 | } 45 | 46 | 47 | private CompletableFuture fetchWalletId(String emailId) { 48 | return CompletableFuture.supplyAsync(() -> { 49 | // Load wallet id using email id 50 | return 10001L; 51 | }); 52 | } 53 | 54 | private CompletableFuture loadWalletBalance(Long walletId) { 55 | return CompletableFuture.supplyAsync(() -> { 56 | // Load wallet balance from database 57 | return 500.00; 58 | }); 59 | } 60 | 61 | @Override 62 | public boolean placeOrder(Long customerId, Long productId) throws ExecutionException, InterruptedException { 63 | 64 | log.info("Request coming to placeOrder() method."); 65 | log.info("Thread Name :"+Thread.currentThread().getName()); 66 | 67 | CompletableFuture combinedFuture = loadCustomer(customerId) 68 | .thenCombine(loadProduct(productId), (customer, product) -> { 69 | boolean isOrderPlaced = saveOrder(customer, product); 70 | return isOrderPlaced; 71 | }); 72 | 73 | 74 | return combinedFuture.get(); 75 | } 76 | 77 | @Override 78 | public String getUserFeeds(String emailId) throws ExecutionException, InterruptedException { 79 | 80 | log.info("In method getUserFeeds() : START"); 81 | log.info("Thread Name :"+Thread.currentThread().getName()); 82 | 83 | 84 | CompletableFuture loadUsersFacebookFeedsFuture = loadUsersFacebookFeeds(emailId); 85 | CompletableFuture loadUsersGitHubFeedsFuture = loadUsersGitHubFeeds(emailId); 86 | CompletableFuture loadUsersMediumFeedsFuture = loadUsersMediumFeeds(emailId); 87 | 88 | CompletableFuture allFutures = CompletableFuture.allOf( 89 | loadUsersFacebookFeedsFuture, 90 | loadUsersGitHubFeedsFuture, 91 | loadUsersMediumFeedsFuture 92 | ); 93 | log.info("CALL allFutures.get() : START"); 94 | 95 | allFutures.get(); 96 | log.info("CALL allFutures.get() : END"); 97 | 98 | String result = ""; 99 | if (allFutures.isDone ()) { 100 | result = "User feed : "+loadUsersFacebookFeedsFuture.get()+". "+loadUsersGitHubFeedsFuture.get()+". "+loadUsersMediumFeedsFuture.get(); 101 | } else { 102 | result = "Futures are not ready YET"; 103 | } 104 | 105 | log.info("Result : "+result); 106 | 107 | return result; 108 | } 109 | 110 | CompletableFuture loadUsersFacebookFeeds(String emailId) { 111 | return CompletableFuture.supplyAsync(() -> { 112 | try { 113 | log.info("loadUsersFacebookFeeds() : START"); 114 | log.info("Thread Name :"+Thread.currentThread().getName()); 115 | TimeUnit.SECONDS.sleep(5); 116 | log.info("loadUsersFacebookFeeds() : END"); 117 | } catch (InterruptedException e) { 118 | e.printStackTrace(); 119 | } 120 | 121 | return "This is users github details"; 122 | }); 123 | } 124 | 125 | CompletableFuture loadUsersGitHubFeeds(String emailId) { 126 | return CompletableFuture.supplyAsync(() -> { 127 | try { 128 | log.info("loadUsersGitHubFeeds() : START"); 129 | log.info("Thread Name :"+Thread.currentThread().getName()); 130 | TimeUnit.SECONDS.sleep(5); 131 | log.info("loadUsersGitHubFeeds() : END"); 132 | } catch (InterruptedException e) { 133 | e.printStackTrace(); 134 | } 135 | 136 | return "This is users github details"; 137 | }); 138 | } 139 | 140 | CompletableFuture loadUsersMediumFeeds(String emailId) { 141 | return CompletableFuture.supplyAsync(() -> { 142 | try { 143 | log.info("loadUsersMediumFeeds() : START"); 144 | log.info("Thread Name :"+Thread.currentThread().getName()); 145 | TimeUnit.SECONDS.sleep(5); 146 | log.info("loadUsersMediumFeeds() : END"); 147 | } catch (InterruptedException e) { 148 | e.printStackTrace(); 149 | } 150 | return "This is users medium details"; 151 | }); 152 | } 153 | 154 | private CompletableFuture loadCustomer(Long customerId) { 155 | 156 | return CompletableFuture.supplyAsync(() -> { 157 | // Load wallet id using email id 158 | try { 159 | log.info("loadCustomer() : START"); 160 | TimeUnit.SECONDS.sleep(5); 161 | log.info("loadCustomer() : END"); 162 | } catch (InterruptedException e) { 163 | e.printStackTrace(); 164 | } 165 | Customer customer = null; 166 | return customer; 167 | }); 168 | } 169 | 170 | private CompletableFuture loadProduct(Long productId) { 171 | return CompletableFuture.supplyAsync(() -> { 172 | // Load wallet balance from database 173 | try { 174 | log.info("Task loadProduct() : START"); 175 | TimeUnit.SECONDS.sleep(5); 176 | log.info("Task loadProduct() : END"); 177 | } catch (InterruptedException e) { 178 | e.printStackTrace(); 179 | } 180 | Product product = null; 181 | return product; 182 | }); 183 | } 184 | 185 | private boolean saveOrder(Customer customer, Product product) { 186 | // save data on database 187 | try { 188 | log.info("saveOrder() : START"); 189 | TimeUnit.SECONDS.sleep(5); 190 | log.info("saveOrder() : END"); 191 | } catch (InterruptedException e) { 192 | e.printStackTrace(); 193 | } 194 | return true; 195 | } 196 | 197 | 198 | public void sendNotification(String to, String message) { 199 | try { 200 | log.info("Sending notification. To : " + to + " Message :" + message); 201 | TimeUnit.SECONDS.sleep(5); 202 | log.info("Notification sending done"); 203 | } catch (InterruptedException e) { 204 | e.printStackTrace(); 205 | } 206 | 207 | } 208 | 209 | public class Product { 210 | Long id; 211 | String productName; 212 | Double price; 213 | } 214 | 215 | public class Customer { 216 | Long id; 217 | String name; 218 | Double age; 219 | } 220 | 221 | } 222 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/CustomerService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.domain.Customer; 4 | import com.appcoder.springreadyapp.domain.ICustomer; 5 | import com.appcoder.springreadyapp.exception.CustomerNotFoundException; 6 | import org.springframework.data.domain.Page; 7 | 8 | import java.util.List; 9 | 10 | public interface CustomerService { 11 | public boolean saveUpdateCustomer(Customer request); 12 | 13 | public boolean deleteCustomer(Customer request); 14 | 15 | public List fetchAllCustomer(); 16 | 17 | public List findCustomerByMobileNumber(String mobileNumber); 18 | public List findCustomerByMobileNumberException(String mobileNumber) throws CustomerNotFoundException; 19 | public List findCustomerByFirstNameProjection(String firstName); 20 | public List findCustomerByFirstNameCustomQuery(String firstName); 21 | public Page findCustomerByLastNamePagination(String lastName, int pageId, int pageSize); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/CustomerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.domain.Customer; 4 | import com.appcoder.springreadyapp.domain.ICustomer; 5 | import com.appcoder.springreadyapp.exception.CustomerNotFoundException; 6 | import com.appcoder.springreadyapp.repository.CustomerRepository; 7 | import org.apache.commons.logging.Log; 8 | import org.apache.commons.logging.LogFactory; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.data.domain.PageRequest; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.stereotype.Service; 13 | 14 | import javax.persistence.EntityManager; 15 | import javax.persistence.PersistenceContext; 16 | import javax.persistence.Query; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | @Service 21 | public class CustomerServiceImpl implements CustomerService { 22 | 23 | private static Log log = LogFactory.getLog(CustomerServiceImpl.class); 24 | 25 | private CustomerRepository customerRepository; 26 | 27 | @PersistenceContext 28 | private EntityManager entityManager; 29 | 30 | public CustomerServiceImpl(CustomerRepository customerRepository) { 31 | this.customerRepository = customerRepository; 32 | } 33 | 34 | @Override 35 | public boolean saveUpdateCustomer(Customer request) { 36 | Customer customer; 37 | 38 | if(customerRepository.countAllByFirstName(request.getFirstName())>0){ 39 | log.error("First name already exists"); 40 | return false; 41 | } 42 | 43 | if (request.getId() == null || request.getId() == 0) { 44 | customer = new Customer(); 45 | customer.setFirstName(request.getFirstName()); 46 | customer.setLastName(request.getLastName()); 47 | customer.setMobileNumber(request.getMobileNumber()); 48 | customer.setGender(request.getGender()); 49 | customer.setPermanentAddress(request.getPermanentAddress()); 50 | customer.setPresentAddress(request.getPresentAddress()); 51 | } else { 52 | customer = request; 53 | } 54 | customerRepository.save(customer); 55 | return true; 56 | } 57 | 58 | @Override 59 | public boolean deleteCustomer(Customer request) { 60 | if (request.getId() == null || request.getId() == 0) { 61 | log.error("Invalid request"); 62 | return false; 63 | } 64 | if (!customerRepository.existsById(request.getId())) { 65 | log.error("Customer not found based on provided data"); 66 | return false; 67 | } 68 | customerRepository.deleteById(request.getId()); 69 | return true; 70 | } 71 | 72 | @Override 73 | public List fetchAllCustomer() { 74 | return customerRepository.findAll(); 75 | } 76 | 77 | @Override 78 | public List findCustomerByMobileNumber(String mobileNumber) { 79 | return customerRepository.findAllByMobileNumber(mobileNumber); 80 | } 81 | 82 | @Override 83 | public List findCustomerByMobileNumberException(String mobileNumber) throws CustomerNotFoundException { 84 | List customers = customerRepository.findAllByMobileNumber(mobileNumber); 85 | if(customers == null || customers.size()==0 ){ 86 | throw new CustomerNotFoundException("No customers found"); 87 | } 88 | 89 | return customers; 90 | } 91 | 92 | @Override 93 | public List findCustomerByFirstNameProjection(String firstName) { 94 | return customerRepository.findAllByFirstName(firstName); 95 | } 96 | 97 | @Override 98 | public List findCustomerByFirstNameCustomQuery(String firstName) { 99 | String queryStr = "select id,first_name, last_name, mobile_number from customer where first_name = ?1"; 100 | try { 101 | Query query = entityManager.createNativeQuery(queryStr); 102 | query.setParameter(1, firstName); 103 | 104 | List objectList = query.getResultList(); 105 | 106 | List result = new ArrayList<>(); 107 | for (Object[] row : objectList) { 108 | result.add(new Customer(row)); 109 | } 110 | return result; 111 | 112 | } catch (Exception e) { 113 | e.printStackTrace(); 114 | throw e; 115 | } 116 | } 117 | 118 | @Override 119 | public Page findCustomerByLastNamePagination(String lastName, int pageId, int pageSize) { 120 | Pageable pageable = PageRequest.of(pageId, pageSize); 121 | return customerRepository.findAllByLastName(lastName,pageable); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/IAsyncProgrammingService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | 5 | public interface IAsyncProgrammingService { 6 | void sendNotification(String emailId) throws ExecutionException, InterruptedException; 7 | String customerWalletBalance(String emailId) throws ExecutionException, InterruptedException; 8 | boolean placeOrder(Long customerId, Long productId) throws ExecutionException, InterruptedException; 9 | String getUserFeeds(String emailId) throws ExecutionException, InterruptedException; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/IMongoUserService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.domain.MongoUser; 4 | import org.springframework.data.domain.Page; 5 | 6 | import java.util.List; 7 | 8 | public interface IMongoUserService { 9 | public boolean saveUpdateUser(MongoUser request); 10 | 11 | public boolean deleteUser(MongoUser request); 12 | 13 | public List fetchAllUser(); 14 | 15 | public List findUserByMobileNumber(String mobileNumber); 16 | public Page findUserByGenderNamePagination(String lastName, int pageId, int pageSize); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/ISecureUserService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.domain.User; 4 | import com.appcoder.springreadyapp.request.springSecurity.SignUpRequest; 5 | import com.appcoder.springreadyapp.response.springSecurity.LoginResponse; 6 | import com.appcoder.springreadyapp.response.springSecurity.UserResponse; 7 | 8 | import java.util.List; 9 | 10 | public interface ISecureUserService { 11 | LoginResponse login(String username, String password); 12 | 13 | User signUp(SignUpRequest request); 14 | 15 | void removeUser(String username); 16 | 17 | UserResponse searchUser(String userName); 18 | List getAllUser(); 19 | 20 | String refreshToken(String userName); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/MongoUserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.domain.MongoUser; 4 | import com.appcoder.springreadyapp.repository.MongoUserRepository; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.PageRequest; 9 | import org.springframework.data.domain.Pageable; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.List; 13 | 14 | @Service 15 | public class MongoUserServiceImpl implements IMongoUserService { 16 | private static Log log = LogFactory.getLog(MongoUserServiceImpl.class); 17 | 18 | private MongoUserRepository mongoUserRepository; 19 | 20 | public MongoUserServiceImpl(MongoUserRepository mongoUserRepository) { 21 | this.mongoUserRepository = mongoUserRepository; 22 | } 23 | 24 | @Override 25 | public boolean saveUpdateUser(MongoUser request) { 26 | MongoUser mongoUser; 27 | 28 | if (request.getId() == null || request.getId().trim().length() == 0) { 29 | if(mongoUserRepository.countAllByUserName(request.getUserName())>0){ 30 | log.error("UserName already exists"); 31 | return false; 32 | } 33 | 34 | mongoUser = new MongoUser(request.getUserName(),request.getFullName(),request.getGender(), request.getMobileNumber()); 35 | } else { 36 | mongoUser = request; 37 | } 38 | mongoUserRepository.save(mongoUser); 39 | return true; 40 | } 41 | 42 | @Override 43 | public boolean deleteUser(MongoUser request) { 44 | if (request.getId() == null || request.getId().trim().length() == 0) { 45 | log.error("Invalid request"); 46 | return false; 47 | } 48 | if (!mongoUserRepository.existsById(request.getId())) { 49 | log.error("Customer not found based on provided data"); 50 | return false; 51 | } 52 | mongoUserRepository.deleteById(request.getId()); 53 | return true; 54 | } 55 | 56 | @Override 57 | public List fetchAllUser() { 58 | return mongoUserRepository.findAll(); 59 | } 60 | 61 | @Override 62 | public List findUserByMobileNumber(String mobileNumber) { 63 | return mongoUserRepository.findAllByMobileNumber(mobileNumber); 64 | } 65 | 66 | 67 | @Override 68 | public Page findUserByGenderNamePagination(String mobineNumber, int pageId, int pageSize) { 69 | Pageable pageable = PageRequest.of(pageId, pageSize); 70 | return mongoUserRepository.findAllByMobileNumber(mobineNumber,pageable); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/RedisTestService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.request.TransactionRequest; 4 | 5 | public interface RedisTestService { 6 | boolean doTransactionNormal(TransactionRequest transactionRequest) throws RuntimeException; 7 | boolean doTransactionLock(TransactionRequest transactionRequest) throws RuntimeException; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/RedisTestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.repository.RedisCacheRepository; 4 | import com.appcoder.springreadyapp.request.TransactionRequest; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | import org.springframework.stereotype.Service; 8 | 9 | @Service 10 | public class RedisTestServiceImpl implements RedisTestService { 11 | private static Log log = LogFactory.getLog(RedisTestService.class); 12 | private RedisCacheRepository cacheRepository; 13 | 14 | public RedisTestServiceImpl(RedisCacheRepository cacheRepository) { 15 | this.cacheRepository = cacheRepository; 16 | } 17 | 18 | @Override 19 | public boolean doTransactionNormal(TransactionRequest transactionRequest) throws RuntimeException { 20 | 21 | String key = "TRANSACTION-" + transactionRequest.getSenderWalletId().toString(); 22 | 23 | if (cacheRepository.isTransactionRunningForSender(key)) { 24 | log.error("Transaction Failed, Transaction is going on for sender : " + transactionRequest.getSenderWalletId()); 25 | throw new RuntimeException("Transaction Failed, Transaction is going on for sender : " + transactionRequest.getSenderWalletId()); 26 | } 27 | 28 | fetchSomeValueFromDb(); 29 | 30 | cacheRepository.makeSenderBusyForTransactionNormal(key); 31 | 32 | saveSomeDataIntoDb(); 33 | log.info("Transaction Done"); 34 | cacheRepository.makeSenderFreeForTransactionNormal(key); 35 | return true; 36 | 37 | } 38 | 39 | @Override 40 | public boolean doTransactionLock(TransactionRequest transactionRequest) throws RuntimeException { 41 | 42 | String key = "TRANSACTION-" + transactionRequest.getSenderWalletId().toString(); 43 | 44 | if (cacheRepository.acquireLock(key)) { 45 | fetchSomeValueFromDb(); 46 | saveSomeDataIntoDb(); 47 | log.info("Transaction Done"); 48 | cacheRepository.releaseLock(key); 49 | return true; 50 | } else { 51 | log.error("Transaction Failed, Transaction is going on for sender : " + transactionRequest.getSenderWalletId()); 52 | throw new RuntimeException("Transaction Failed, Transaction is going on for sender : " + transactionRequest.getSenderWalletId()); 53 | } 54 | } 55 | 56 | public void fetchSomeValueFromDb() { 57 | log.info("Fetching some data from database."); 58 | try { 59 | Thread.sleep(5000); 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | log.info("Data fetch done from database."); 64 | } 65 | 66 | public void saveSomeDataIntoDb() { 67 | log.info("Saving data into database."); 68 | 69 | try { 70 | Thread.sleep(5000); 71 | } catch (Exception e) { 72 | e.printStackTrace(); 73 | } 74 | log.info("Saving data into database done."); 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/appcoder/springreadyapp/services/SecureUserService.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp.services; 2 | 3 | import com.appcoder.springreadyapp.domain.User; 4 | import com.appcoder.springreadyapp.exception.MyCustomException; 5 | import com.appcoder.springreadyapp.repository.SecureUserRepository; 6 | import com.appcoder.springreadyapp.request.springSecurity.SignUpRequest; 7 | import com.appcoder.springreadyapp.response.springSecurity.LoginResponse; 8 | import com.appcoder.springreadyapp.response.springSecurity.UserResponse; 9 | import com.appcoder.springreadyapp.security.IJwtTokenProviderService; 10 | import org.apache.commons.logging.Log; 11 | import org.apache.commons.logging.LogFactory; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.security.authentication.AuthenticationManager; 14 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 15 | import org.springframework.security.core.AuthenticationException; 16 | import org.springframework.security.crypto.password.PasswordEncoder; 17 | import org.springframework.stereotype.Service; 18 | 19 | import java.util.List; 20 | 21 | 22 | @Service 23 | public class SecureUserService implements ISecureUserService { 24 | private static Log log = LogFactory.getLog(SecureUserService.class); 25 | 26 | private SecureUserRepository secureUserRepository; 27 | 28 | private PasswordEncoder passwordEncoder; 29 | 30 | private IJwtTokenProviderService jwtTokenProviderService; 31 | private AuthenticationManager authenticationManager; 32 | 33 | 34 | public SecureUserService(SecureUserRepository secureUserRepository, PasswordEncoder passwordEncoder, IJwtTokenProviderService jwtTokenProviderService, AuthenticationManager authenticationManager) { 35 | this.secureUserRepository = secureUserRepository; 36 | this.passwordEncoder = passwordEncoder; 37 | this.jwtTokenProviderService = jwtTokenProviderService; 38 | this.authenticationManager = authenticationManager; 39 | } 40 | 41 | @Override 42 | public LoginResponse login(String userName, String password) { 43 | try { 44 | authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, password)); 45 | 46 | User user = secureUserRepository.findByUsername(userName); 47 | 48 | LoginResponse loginResponse = new LoginResponse(); 49 | loginResponse.setEmail(user.getEmail()); 50 | loginResponse.setUserName(user.getUsername()); 51 | loginResponse.setAccessToken(jwtTokenProviderService.createToken(userName, user.getRoles())); 52 | 53 | log.info("Login successfully"); 54 | 55 | return loginResponse; 56 | } catch (AuthenticationException e) { 57 | throw new MyCustomException("Invalid username/password supplied", HttpStatus.UNPROCESSABLE_ENTITY); 58 | } 59 | } 60 | 61 | @Override 62 | public User signUp(SignUpRequest request) { 63 | if(secureUserRepository.existsByUsername(request.getUserName())){ 64 | throw new MyCustomException("User already exists in system", HttpStatus.UNPROCESSABLE_ENTITY); 65 | } 66 | 67 | User user = new User(); 68 | user.setUsername(request.getUserName()); 69 | user.setPassword(passwordEncoder.encode(request.getPassword())); 70 | user.setEmail(request.getEmail()); 71 | user.setRoles(request.getRoles()); 72 | request.setPassword(user.getPassword()); 73 | 74 | secureUserRepository.save(user); 75 | log.info("Register successfully"); 76 | 77 | 78 | return user; 79 | } 80 | 81 | @Override 82 | public void removeUser(String userName) { 83 | if(!secureUserRepository.existsByUsername(userName)){ 84 | throw new RuntimeException("User doesn't exists"); 85 | } 86 | secureUserRepository.deleteByUsername(userName); 87 | log.info("User remove successfully"); 88 | 89 | } 90 | 91 | @Override 92 | public UserResponse searchUser(String userName) { 93 | User user = secureUserRepository.findByUsername(userName); 94 | if (user == null) { 95 | throw new MyCustomException("Provided user doesn't exist", HttpStatus.NOT_FOUND); 96 | } 97 | 98 | UserResponse userResponse = new UserResponse(); 99 | userResponse.setEmail(user.getEmail()); 100 | userResponse.setUserName(user.getUsername()); 101 | 102 | return userResponse; 103 | } 104 | 105 | @Override 106 | public List getAllUser() { 107 | return secureUserRepository.findAll(); 108 | } 109 | 110 | @Override 111 | public String refreshToken(String userName) { 112 | return jwtTokenProviderService.createToken(userName, secureUserRepository.findByUsername(userName).getRoles()); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/resources/application-main.properties: -------------------------------------------------------------------------------- 1 | server.servlet.context-path=/springreadyapp 2 | server.port = 8080 3 | 4 | spring.datasource.url=jdbc:h2:mem:testdb 5 | spring.datasource.driverClassName=org.h2.Driver 6 | spring.datasource.username=sa 7 | spring.datasource.password=password 8 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 9 | spring.jpa.hibernate.ddl-auto=create 10 | 11 | #For logging SQL 12 | spring.jpa.show-sql=true 13 | spring.jpa.properties.hibernate.format_sql=true 14 | 15 | management.security.enabled=false -------------------------------------------------------------------------------- /src/main/resources/application-mongo.properties: -------------------------------------------------------------------------------- 1 | server.servlet.context-path=/springreadyapp 2 | server.port = 8080 3 | 4 | spring.data.mongodb.host=localhost 5 | spring.data.mongodb.port=27017 6 | spring.data.mongodb.database=myMongoDB 7 | 8 | #For logging SQL 9 | spring.jpa.show-sql=true 10 | spring.jpa.properties.hibernate.format_sql=true 11 | 12 | management.security.enabled=false -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active: main 2 | #spring.profiles.active: mongo -------------------------------------------------------------------------------- /src/test/java/com/appcoder/springreadyapp/CustomerControllerLayerTest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp; 2 | 3 | 4 | import com.appcoder.springreadyapp.controller.CustomerController; 5 | import com.appcoder.springreadyapp.domain.Customer; 6 | import com.appcoder.springreadyapp.security.JwtTokenProviderService; 7 | import com.appcoder.springreadyapp.services.CustomerService; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 13 | import org.springframework.boot.test.mock.mockito.MockBean; 14 | import org.springframework.http.MediaType; 15 | import org.springframework.security.test.context.support.WithMockUser; 16 | import org.springframework.test.context.junit4.SpringRunner; 17 | import org.springframework.test.web.servlet.MockMvc; 18 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 19 | 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | import static org.mockito.ArgumentMatchers.any; 24 | import static org.mockito.Mockito.when; 25 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 27 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 28 | 29 | @RunWith(SpringRunner.class) 30 | @WebMvcTest({CustomerController.class}) 31 | public class CustomerControllerLayerTest { 32 | 33 | @Autowired 34 | private MockMvc mockMvc; 35 | 36 | @MockBean 37 | JwtTokenProviderService jwtTokenProviderService; 38 | 39 | @MockBean 40 | CustomerService customerService; 41 | 42 | 43 | @Test 44 | @WithMockUser(username = "user1", password = "pwd", roles = "USER") 45 | public void save_customer_success() throws Exception { 46 | 47 | Customer customer = new Customer("sajedul", "karim", "01737186095"); 48 | 49 | when(customerService.saveUpdateCustomer(any())).thenReturn(Boolean.TRUE); 50 | 51 | mockMvc.perform( 52 | MockMvcRequestBuilders.post("/customer/saveCustomer") 53 | .content(asJsonString(customer)) 54 | .contentType(MediaType.APPLICATION_JSON) 55 | .accept(MediaType.APPLICATION_JSON) 56 | ) 57 | .andExpect(status().isOk()) 58 | .andExpect(content().string("Customer Save/update Done")); 59 | } 60 | 61 | @Test 62 | @WithMockUser(username = "user1", password = "pwd", roles = "USER") 63 | public void save_customer_failed() throws Exception { 64 | 65 | Customer customer = new Customer("sajedul", "karim", "01737186095"); 66 | 67 | when(customerService.saveUpdateCustomer(any())).thenReturn(Boolean.FALSE); 68 | 69 | mockMvc.perform( 70 | MockMvcRequestBuilders.post("/customer/saveCustomer") 71 | .content(asJsonString(customer)) 72 | .contentType(MediaType.APPLICATION_JSON) 73 | .accept(MediaType.APPLICATION_JSON) 74 | ) 75 | .andExpect(status().isOk()) 76 | .andExpect(content().string("Customer Save/update failed")); 77 | } 78 | 79 | @Test 80 | @WithMockUser(username = "user1", password = "pwd", roles = "USER") 81 | public void customer_fetch_in_db_success() throws Exception { 82 | 83 | List customerList = Arrays.asList( 84 | new Customer("sajedul", "karim", "01737186095"), 85 | new Customer("shawon", "nirob", "01737186096"), 86 | new Customer("aayan", "karim", "01737186097") 87 | ); 88 | 89 | when(customerService.fetchAllCustomer()).thenReturn(customerList); 90 | 91 | mockMvc.perform( 92 | MockMvcRequestBuilders.get("/customer/fetchAllCustomer")) 93 | .andExpect(status().isOk()) 94 | .andExpect(content().json("[{}, {}, {}]")); 95 | } 96 | 97 | @Test 98 | @WithMockUser(username = "user1", password = "pwd", roles = "USER") 99 | public void customer_fetch_customer_by_mobileNo_exception_success() throws Exception { 100 | 101 | String searchedMobileNo = "01737186095"; 102 | 103 | when(customerService.findCustomerByMobileNumberException(searchedMobileNo)).thenThrow(new RuntimeException("No data found")); 104 | 105 | mockMvc.perform( 106 | MockMvcRequestBuilders.get("/customer/fetchCustomerByMobileNumberException?mobileNumber=" + searchedMobileNo)) 107 | .andDo(print()) 108 | .andExpect(status().is(404)) 109 | .andReturn(); 110 | } 111 | 112 | 113 | public static String asJsonString(final Object obj) { 114 | try { 115 | return new ObjectMapper().writeValueAsString(obj); 116 | } catch (Exception e) { 117 | throw new RuntimeException(e); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/test/java/com/appcoder/springreadyapp/CustomerRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp; 2 | 3 | 4 | import com.appcoder.springreadyapp.domain.Customer; 5 | import com.appcoder.springreadyapp.domain.ICustomer; 6 | import com.appcoder.springreadyapp.repository.CustomerRepository; 7 | import org.junit.jupiter.api.AfterEach; 8 | import org.junit.jupiter.api.BeforeEach; 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.ExtendWith; 11 | import org.mockito.junit.jupiter.MockitoExtension; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 14 | 15 | import java.util.Arrays; 16 | import java.util.List; 17 | import java.util.concurrent.atomic.AtomicInteger; 18 | 19 | import static org.assertj.core.api.Java6Assertions.assertThat; 20 | 21 | @ExtendWith(MockitoExtension.class) 22 | @DataJpaTest 23 | public class CustomerRepositoryTest { 24 | @Autowired 25 | private CustomerRepository customerRepository; 26 | 27 | @BeforeEach 28 | void initUseCase() { 29 | List customers = Arrays.asList( 30 | new Customer("default", "user", "01737186090") 31 | ); 32 | customerRepository.saveAll(customers); 33 | } 34 | 35 | @AfterEach 36 | public void destroyAll(){ 37 | customerRepository.deleteAll(); 38 | } 39 | 40 | @Test 41 | void saveAll_success() { 42 | List customers = Arrays.asList( 43 | new Customer("sajedul", "karim", "01737186095"), 44 | new Customer("nafis", "khan", "01737186096"), 45 | new Customer("aayan", "karim", "01737186097") 46 | ); 47 | Iterable allCustomer = customerRepository.saveAll(customers); 48 | 49 | AtomicInteger validIdFound = new AtomicInteger(); 50 | allCustomer.forEach(customer -> { 51 | if(customer.getId()>0){ 52 | validIdFound.getAndIncrement(); 53 | } 54 | }); 55 | 56 | assertThat(validIdFound.intValue()).isEqualTo(3); 57 | } 58 | 59 | @Test 60 | void findAll_success() { 61 | List allCustomer = customerRepository.findAll(); 62 | assertThat(allCustomer.size()).isGreaterThanOrEqualTo(1); 63 | } 64 | 65 | @Test 66 | void findAllByFirstName_success() { 67 | List allCustomer = customerRepository.findAllByFirstName("default"); 68 | assertThat(allCustomer.size()).isGreaterThanOrEqualTo(1); 69 | } 70 | 71 | @Test 72 | void findAllByFirstName_failed() { 73 | List allCustomer = customerRepository.findAllByFirstName("obama"); 74 | assertThat(allCustomer.size()).isEqualTo(0); 75 | } 76 | 77 | @Test 78 | void findAllByMobile_success() { 79 | List allCustomer = customerRepository.findAllByMobileNumber("01737186090"); 80 | assertThat(allCustomer.size()).isEqualTo(1); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/com/appcoder/springreadyapp/CustomerServiceLayerTest.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp; 2 | 3 | 4 | import com.appcoder.springreadyapp.domain.Customer; 5 | import com.appcoder.springreadyapp.exception.CustomerNotFoundException; 6 | import com.appcoder.springreadyapp.repository.CustomerRepository; 7 | import com.appcoder.springreadyapp.services.CustomerService; 8 | import com.appcoder.springreadyapp.services.CustomerServiceImpl; 9 | import org.junit.jupiter.api.Assertions; 10 | import org.junit.jupiter.api.BeforeEach; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | import org.mockito.Mock; 14 | import org.mockito.junit.jupiter.MockitoExtension; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | import static org.assertj.core.api.Java6Assertions.assertThat; 20 | import static org.mockito.ArgumentMatchers.any; 21 | import static org.mockito.Mockito.when; 22 | 23 | @ExtendWith(MockitoExtension.class) 24 | public class CustomerServiceLayerTest { 25 | @Mock 26 | private CustomerRepository customerRepository; 27 | 28 | CustomerService customerService; 29 | 30 | @BeforeEach 31 | void initUseCase() { 32 | customerService = new CustomerServiceImpl(customerRepository); 33 | } 34 | 35 | @Test 36 | public void savedCustomer_Success() { 37 | Customer customer = new Customer(); 38 | customer.setFirstName("sajedul"); 39 | customer.setLastName("karim"); 40 | customer.setMobileNumber("01737186095"); 41 | 42 | // providing knowledge 43 | when(customerRepository.save(any(Customer.class))).thenReturn(customer); 44 | 45 | Customer savedCustomer = customerRepository.save(customer); 46 | assertThat(savedCustomer.getFirstName()).isNotNull(); 47 | } 48 | 49 | @Test 50 | public void savedCustomer_FirstName_exists_Failed() { 51 | Customer customer = new Customer(); 52 | customer.setFirstName("sajedul"); 53 | customer.setLastName("karim"); 54 | customer.setMobileNumber("01737186095"); 55 | 56 | // providing knowledge 57 | when(customerRepository.countAllByFirstName(customer.getFirstName())).thenReturn(1L); 58 | 59 | Boolean isSaveSuccess = customerService.saveUpdateCustomer(customer); 60 | assertThat(isSaveSuccess).isEqualTo(false); 61 | } 62 | 63 | @Test 64 | public void customer_exists_in_db_success() { 65 | Customer customer = new Customer(); 66 | customer.setFirstName("sajedul"); 67 | customer.setLastName("karim"); 68 | customer.setMobileNumber("01737186095"); 69 | List customerList = new ArrayList<>(); 70 | customerList.add(customer); 71 | 72 | // providing knowledge 73 | when(customerRepository.findAll()).thenReturn(customerList); 74 | 75 | List fetchedCustomers = customerService.fetchAllCustomer(); 76 | assertThat(fetchedCustomers.size()).isGreaterThan(0); 77 | } 78 | 79 | @Test 80 | public void customer_search_found_success() { 81 | Customer customer = new Customer(); 82 | customer.setFirstName("sajedul"); 83 | customer.setLastName("karim"); 84 | customer.setMobileNumber("01737186095"); 85 | List customerList = new ArrayList<>(); 86 | customerList.add(customer); 87 | 88 | // providing knowledge 89 | when(customerRepository.findAllByMobileNumber(customer.getMobileNumber())).thenReturn(customerList); 90 | 91 | List fetchedCustomers = customerService.findCustomerByMobileNumber(customer.getMobileNumber()); 92 | assertThat(fetchedCustomers.size()).isGreaterThan(0); 93 | } 94 | 95 | @Test 96 | public void customer_search_not_found_failed() { 97 | Customer customer = new Customer(); 98 | customer.setFirstName("sajedul"); 99 | customer.setLastName("karim"); 100 | customer.setMobileNumber("01737186095"); 101 | List customerList = new ArrayList<>(); 102 | customerList.add(customer); 103 | 104 | List fetchedCustomers = customerService.findCustomerByMobileNumber(customer.getMobileNumber()); 105 | assertThat(fetchedCustomers.size()).isEqualTo(0); 106 | } 107 | 108 | @Test 109 | public void customer_search_not_found_exception_handle_failed() { 110 | 111 | Assertions.assertThrows(CustomerNotFoundException.class, () -> { 112 | List fetchedCustomers = customerService.findCustomerByMobileNumberException("018277272772"); 113 | assertThat(fetchedCustomers.size()).isGreaterThan(0); 114 | }); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/test/java/com/appcoder/springreadyapp/SpringReadyAppApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.appcoder.springreadyapp; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringReadyAppApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------