├── LICENSE.md ├── README.md ├── SECURITY.md ├── analytics ├── ccFraudScore.R └── fraudModel.rData ├── build.gradle ├── di-config.json ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main ├── java └── com │ └── revo │ └── deployr │ └── rbroker │ └── example │ ├── FraudEngine.java │ ├── config │ └── WebSocketConfig.java │ ├── controller │ └── FraudController.java │ ├── model │ ├── ClientAlert.java │ ├── ClientMessage.java │ ├── ClientWarn.java │ ├── FraudScore.java │ └── RuntimeStats.java │ ├── service │ └── FraudService.java │ └── util │ └── RBrokerStatsHelper.java ├── resources ├── application.properties └── log4j.properties └── webapp ├── index.html └── js └── controllers.js /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010-2014 by Revolution Analytics Inc. 2 | 3 | This program is licensed to you under the terms of Version 2.0 of the 4 | Apache License. This program is distributed WITHOUT 5 | ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 6 | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 7 | Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more 8 | details. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | java-example-fraud-score 2 | ======================== 3 | 4 | Example use of DeployR as a real-time, R analytics scoring engine. 5 | 6 | ## About 7 | 8 | This example demonstrates the use of 9 | [DeployR](https://msdn.microsoft.com/en-us/microsoft-r/deployr-about) as a 10 | real-time, Ranalytics scoring engine. 11 | 12 | The example scenario mimics a real world application where employees 13 | at a fictitious bank can request _fraud scores_ for one or more bank 14 | account records to help detect fraudulent account activity. 15 | 16 | This example is built using the _DeployR_ [RBroker 17 | Framework](https://msdn.microsoft.com/en-us/microsoft-r/deployr-rbroker-framework), 18 | the simplest way to integrate R analytics inside any Java, JavaScript or .NET 19 | application. 20 | 21 | This example consists of three distinct parts: 22 | 23 | 1. Example R Analytics 24 | 2. Example Server Application 25 | 3. Example Client Application 26 | 27 | The final section of this document provides additional details regarding the 28 | _DeployR integration_ implemented for this example. 29 | 30 | ## Example R Analytics 31 | 32 | ``` 33 | Source: analytics/* 34 | ``` 35 | 36 | This example uses an R model built to score fictitious bank account data 37 | to help uncover fraudulent account activity. The model used is found 38 | here: 39 | 40 | ``` 41 | analytics/fraudModel.rData 42 | ``` 43 | 44 | The model uses three variables associated with individual bank accounts: 45 | 46 | 1. The number of transactions on the account 47 | 2. The account balance 48 | 3. The credit line on the account 49 | 50 | This example makes use of a scoring function that uses the model to help 51 | determine the likelihood of _fraud_ on a given account based on these 52 | data inputs. The scoring function is found here: 53 | 54 | ``` 55 | analytics/ccFraudScore.R 56 | ``` 57 | 58 | The R scripts and data models used by this example application are 59 | bundled by default within the DeployR 7.3 repository, inside the 60 | example-fraud-score directory owned by testuser. 61 | 62 | However, if for any reason your DeployR repository does not contain 63 | these files you can add them using the DeployR Repository Manager as 64 | follows: 65 | 66 | 1. Log in as testuser into the Repository Manager 67 | 2. Create a new repository directory called example-fraud-score 68 | 3. Upload analytics/fraudModel.rData to the example-fraud-score 69 | directory 70 | 4. Upload analytics/ccFraudScore.R to the example-fraud-score directory 71 | 72 | 73 | ## Example Server Application 74 | 75 | 76 | ``` 77 | Source: src/main/java/* 78 | ``` 79 | 80 | The example server application represents a real world application, 81 | capable of processing client requests for _fraud scores_ on one or more bank account records. 82 | 83 | The example server application is implemented as a simple [Spring Boot](http://projects.spring.io/spring-boot) Java Web application. 84 | 85 | The example server application exposes a simple REST API through which 86 | client applications can submit _fraud scoring_ requests: 87 | 88 | ``` 89 | /fraud/score/{num_of_records} 90 | ``` 91 | 92 | The example server application handles client requests internally using the 93 | [RBroker Framework](https://msdn.microsoft.com/en-us/microsoft-r/deployr-rbroker-framework) 94 | to run the required R analytics that _scores_ each requested bank account record. 95 | 96 | The _score_, generated by the R analytics and returned to the server via 97 | the _RBroker Framework_, is then pushed by the server application, using 98 | [STOMP-over-WebSocket](http://docs.spring.io/autorepo/docs/spring-framework/current/spring-framework-reference/html/websocket.html), to client applications that 99 | have subscribed as listeners on: 100 | 101 | ``` 102 | /fraudengine/topic/fraud 103 | ``` 104 | 105 | ## Example Client Application 106 | 107 | 108 | ``` 109 | Source: src/main/webapp/* 110 | ``` 111 | 112 | The example client application simulates a computer system made 113 | available to employees at a fictitious bank. 114 | 115 | The example client application is implemented as a simple, single page 116 | [AngularJS](https://angularjs.org) application. The single page is divided into 117 | two distinct sections: 118 | 119 | 1. RBroker Runtime Window 120 | 121 | This window gives the user a live view of all activity that 122 | is taking place through the _RBroker Framework_ on behalf of the client 123 | application. The runtime data provided indicates among other things the 124 | live throughput performance being delivered by _DeployR_ behaving as a 125 | real-time R analytics scoring engine. 126 | 127 | Note: The details presented in the RBroker Runtime Window 128 | would not typically appear in a real-world client application. These data are presented 129 | here simply to aid developers understand by observation how an _RBroker Framework_ 130 | integration works. 131 | 132 | 2. Bank Account Fraud Score Result Window 133 | 134 | This window displays the _fraud score_ results generated by the 135 | real-time R analytics scoring engine powered by _DeployR_. The end user 136 | can also use the _Execute_ button in this window to launch one or more 137 | _fraud scoring_ requests. 138 | 139 | The data for example bank account records is randomly generated by the 140 | application. Requests are submitted by the client application through 141 | the server application REST API. 142 | 143 | The _score_ generated per request is returned to the client application 144 | within a STOMP message delivered over a STOMP-WebSocket channel. 145 | 146 | ## Running the Example 147 | 148 | A Gradle build script is provided to run the example: 149 | 150 | ``` 151 | build.gradle 152 | ``` 153 | 154 | By default, the build configuration assumes an instance of the DeployR server 155 | is running on `localhost`. If your instance of DeployR is running at some 156 | other IP address then please udpate the `endpoint` property in the 157 | configuration file as appropriate. 158 | 159 | You do not need to install Gradle before running these commands. To run 160 | this example application on a Unix based OS, run the following shell 161 | script: 162 | 163 | ``` 164 | gradlew run 165 | ``` 166 | 167 | 168 | To run this example application on a Windows based OS, run the following 169 | batch file: 170 | 171 | ``` 172 | gradlew.bat run 173 | ``` 174 | 175 | Observe the console output in your terminal window to determine if the 176 | server application has started successfully. Once started, open 177 | the client application in your Web browser: 178 | 179 | ``` 180 | http://localhost:9080 181 | ``` 182 | 183 | ## Multiple Users Running the Example 184 | 185 | By default, the example build configuration defaults to using *testuser* 186 | account credentials when authenticating with the DeployR server. If two 187 | or more users intend running this example application at the same time 188 | against the same DeployR server instance then: 189 | 190 | 1. Each user must update the `username` and `password` properties in their 191 | build.gradle configuration file, each indicating the *username* and 192 | *password* for their own user account. 193 | 194 | 2. The _Access Control_ setting for each of the example R analytics file 195 | depencencies in the DeployR repository must be changed from _Private_ access 196 | to _Shared_ access. 197 | 198 | 199 | ## DeployR Integration Details 200 | 201 | #### R Analytics Dependencies 202 | 203 | DeployR-powered applications typically depend on repository-managed R analtyics 204 | scripts, models and/or data files. See the _DeployR_ [Repository Manager](http://deployr.revolutionanalytics.com/documents/help/repo-man/) for details on how best to manage your own R analytics dependencies. 205 | 206 | This example depends on two repository-managed files: 207 | 208 | 1. /testuser/example-fraud-score/fraudModel.rData 209 | 2. /testuser/example-fraud-score/ccFraudScore.R 210 | 211 | Both files, an R model and scoring function respectively, are owned by _testuser_ and can be found in the _example-fraud-score_ repository-managed directory owned by _testuser_. 212 | 213 | These example file dependencies ship, pre-deployed in the _DeployR_ repository so there is no further action for you to take in order for this example to use them. 214 | 215 | #### RBroker Framework - Pooled Task Runtime 216 | 217 | This examples uses the [RBroker Framework](https://msdn.microsoft.com/en-us/microsoft-r/deployr-rbroker-framework) 218 | to integrate _DeployR_ real-time scoring capabilities inside the example server 219 | application. 220 | 221 | Specifically, this example uses the [Pooled Task Runtime](https://msdn.microsoft.com/en-us/microsoft-r/deployr-rbroker-framework#pooled-task-runtime) 222 | provided by the _RBroker Framework_. 223 | 224 | #### RBroker Framework - Throughput 225 | 226 | The _Resize_ button in the _RBroker Runtime Window_ in the example client application lets the end user experiment with the size of the pool of R sessions associated with the _Pooled Task Runtime_. 227 | 228 | We recommend experimenting with the size of the pool and observing the effect 229 | this has on throughput. See the following sections of the _RBroker Framework_ 230 | tutorial for related details: 231 | 232 | - [Client Application Simulations](http://deployr.revolutionanalytics.com/documents/dev/rbroker/#simulation) 233 | - [Client Application Profiling](http://deployr.revolutionanalytics.com/documents/dev/rbroker/#profiling) 234 | - [Grid Resource Management](http://deployr.revolutionanalytics.com/documents/dev/rbroker/#gridprimer) 235 | 236 | ## License ## 237 | 238 | Copyright (C) 2010-2016, Microsoft Corporation 239 | 240 | This program is licensed to you under the terms of Version 2.0 of the 241 | Apache License. This program is distributed WITHOUT 242 | ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 243 | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 244 | Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more 245 | details. 246 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /analytics/ccFraudScore.R: -------------------------------------------------------------------------------- 1 | 2 | ### SCORING THE MODEL 3 | require(RevoScriptTools) 4 | revoInput('{"name": "bal", "render":"integer", "default": 5000, "min" : 0, "max": 25000 }') 5 | revoInput('{"name": "trans", "render":"integer", "default": 12, "min" : 0, "max": 100 }') 6 | revoInput('{"name": "credit", "render":"integer", "default": 8, "min" : 0, "max": 75 }') 7 | 8 | if(!exists('fraudModel')){load('fraudModel.rData')} 9 | score<-data.frame(balance=bal,numTrans=trans,creditLine=credit) 10 | x<-predict(fraudModel, score) 11 | -------------------------------------------------------------------------------- /analytics/fraudModel.rData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-example-fraud-score/92e0ba4fa8e5330285b39549675e5cd4a5fabe07/analytics/fraudModel.rData -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | dependencies { 6 | classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.5.RELEASE") 7 | } 8 | } 9 | 10 | apply plugin: 'java' 11 | apply plugin: "spring-boot" 12 | 13 | group = "com.revo.deployr.java.rbroker.example" 14 | 15 | sourceCompatibility = 1.6 16 | targetCompatibility = 1.6 17 | 18 | applicationDefaultJvmArgs = [ "-Dendpoint=http://localhost:8050/deployr", 19 | "-Dserver.port=9080", 20 | "-Dusername=testuser", 21 | "-Dpassword=TESTUSER_PASSWORD", 22 | "-Drepository-model=fraudModel.rData", 23 | "-Drepository-script=ccFraudScore.R", 24 | "-Drepository-directory=example-fraud-score", 25 | "-Dpoolsize=1", 26 | "-Dallow.SelfSignedSSLCert=true"] 27 | 28 | task argsOverride << { 29 | 30 | /* 31 | * Usage: gradlew run -Pendpoint=http://dserver:dport/deployr 32 | */ 33 | 34 | if(project.hasProperty('endpoint')) { 35 | applicationDefaultJvmArgs[0] = "-Dendpoint=${endpoint}" 36 | println "Project property (DeployR endpoint) override: " + 37 | "${applicationDefaultJvmArgs[0]}" 38 | } else { 39 | println "Project property (DeployR endpoint) default: " + 40 | "${applicationDefaultJvmArgs[0]}" 41 | } 42 | 43 | if(project.hasProperty('username')) { 44 | applicationDefaultJvmArgs[2] = "-Dusername=${username}" 45 | println "Project property (DeployR username) override: " + 46 | "${applicationDefaultJvmArgs[2]}" 47 | } else { 48 | println "Project property (DeployR username) default: " + 49 | "${applicationDefaultJvmArgs[2]}" 50 | } 51 | 52 | if(project.hasProperty('password')) { 53 | applicationDefaultJvmArgs[3] = "-Dpassword=${password}" 54 | println "Project property (DeployR password) override: [HIDDEN]" 55 | } else { 56 | println "Project property (DeployR password) default: [HIDDEN]" 57 | } 58 | 59 | } 60 | 61 | tasks.run.dependsOn argsOverride 62 | 63 | repositories { 64 | mavenCentral() 65 | } 66 | 67 | dependencies { 68 | //compile "com.revolutionanalytics.deployr:jRBroker:7.4.7" 69 | compile "com.microsoft.deployr:jRBroker:8.0.5" 70 | compile "org.springframework.boot:spring-boot-starter-web:1.0.1.RELEASE" 71 | compile("org.springframework.boot:spring-boot-starter-websocket") 72 | compile("org.springframework:spring-messaging") 73 | compile 'org.projectlombok:lombok:1.14.4' 74 | } 75 | 76 | task wrapper(type: Wrapper) { 77 | gradleVersion = '2.0' 78 | } 79 | -------------------------------------------------------------------------------- /di-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "app-install": { 3 | "repository": [{ 4 | "file": { 5 | "filename": "ccFraudScore.R", 6 | "directory": "example-fraud-score", 7 | "descr": "Uploaded from DeployR CLI." 8 | }, 9 | "permissions": { 10 | "restricted": null, 11 | "shared": true, 12 | "published": false 13 | } 14 | }, { 15 | "file": { 16 | "filename": "fraudModel.rData", 17 | "directory": "example-fraud-score", 18 | "descr": "Uploaded from DeployR CLI." 19 | }, 20 | "permissions": { 21 | "restricted": null, 22 | "shared": true, 23 | "published": false 24 | } 25 | }] 26 | }, 27 | 28 | "app-run": { 29 | "requireAuthentication": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-example-fraud-score/92e0ba4fa8e5330285b39549675e5cd4a5fabe07/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 07 12:08:57 ICT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/java/com/revo/deployr/rbroker/example/FraudEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * FraudEngine.java 3 | * 4 | * Copyright (C) 2010-2014 by Revolution Analytics Inc. 5 | * 6 | * This program is licensed to you under the terms of Version 2.0 of the 7 | * Apache License. This program is distributed WITHOUT 8 | * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 9 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 10 | * Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more details. 11 | * 12 | */ 13 | /* 14 | * Java Fraud Detection Example Application 15 | * 16 | * Spring Boot application (context) initialization. 17 | */ 18 | package com.revo.deployr.rbroker.example; 19 | 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 22 | import org.springframework.context.annotation.ComponentScan; 23 | 24 | import org.apache.log4j.Logger; 25 | 26 | @ComponentScan 27 | @EnableAutoConfiguration 28 | public class FraudEngine { 29 | 30 | private static Logger log = Logger.getLogger(FraudEngine.class); 31 | 32 | public static void main(String[] args) { 33 | SpringApplication app = new SpringApplication(FraudEngine.class); 34 | // Ensures @PreDestroy called on kill -1 <>. 35 | app.setRegisterShutdownHook(true); 36 | app.setShowBanner(false); 37 | app.run(args); 38 | log.info("Fraud Score application server has started."); 39 | log.info("Start the Fraud Score client application in your Web browser:\n"); 40 | log.info("http://localhost:9080/\n"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/revo/deployr/rbroker/example/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketConfig.java 3 | * 4 | * Copyright (C) 2010-2014 by Revolution Analytics Inc. 5 | * 6 | * This program is licensed to you under the terms of Version 2.0 of the 7 | * Apache License. This program is distributed WITHOUT 8 | * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 9 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 10 | * Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more details. 11 | * 12 | */ 13 | /* 14 | * Java Fraud Detection Example Application 15 | * 16 | * Spring SimpleBroker STOMP messaging-over-Web-Socket initialization. 17 | * 18 | * Endpoint: /fraudengine 19 | * Topic: /topic 20 | */ 21 | package com.revo.deployr.rbroker.example.config; 22 | 23 | import org.springframework.context.annotation.Configuration; 24 | import org.springframework.messaging.simp.config.MessageBrokerRegistry; 25 | import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; 26 | import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; 27 | import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 28 | 29 | @Configuration 30 | @EnableWebSocketMessageBroker 31 | public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { 32 | 33 | @Override 34 | public void configureMessageBroker(MessageBrokerRegistry config) { 35 | config.enableSimpleBroker("/topic"); 36 | config.setApplicationDestinationPrefixes("/app"); 37 | } 38 | 39 | @Override 40 | public void registerStompEndpoints(StompEndpointRegistry registry) { 41 | registry.addEndpoint("/fraudengine").withSockJS(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/revo/deployr/rbroker/example/controller/FraudController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * FraudController.java 3 | * 4 | * Copyright (C) 2010-2014 by Revolution Analytics Inc. 5 | * 6 | * This program is licensed to you under the terms of Version 2.0 of the 7 | * Apache License. This program is distributed WITHOUT 8 | * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 9 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 10 | * Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more details. 11 | * 12 | */ 13 | /* 14 | * Java Fraud Detection Example Application 15 | * 16 | * Spring REST Controller 17 | * 18 | * Mapping: /pool/init/{size} supports (re)building RBroker runtime. 19 | * 20 | * Mapping: /fraud/score/{tasks} supports RTask execution on RBroker runtime. 21 | */ 22 | package com.revo.deployr.rbroker.example.controller; 23 | 24 | import com.revo.deployr.rbroker.example.service.FraudService; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.web.bind.annotation.*; 27 | 28 | import org.apache.log4j.Logger; 29 | 30 | @RestController 31 | @RequestMapping("/fraud") 32 | public class FraudController { 33 | 34 | private static Logger log = Logger.getLogger(FraudController.class); 35 | private final FraudService fraudService; 36 | 37 | @Autowired 38 | public FraudController(FraudService fraudService) { 39 | this.fraudService = fraudService; 40 | } 41 | 42 | @RequestMapping(value = "/pool/init/{size}", method = RequestMethod.POST) 43 | public void buildPool(@PathVariable("size") int size) { 44 | 45 | try { 46 | 47 | size = (size == 0) ? 1 : size; 48 | log.info("REST:/pool/init/" + size + " called."); 49 | 50 | /* 51 | * Create a new pool or resize an existing pool. 52 | */ 53 | fraudService.buildPool(size); 54 | 55 | } catch(Exception ex) { 56 | log.warn("FraudController: buildPool ex=" + ex); 57 | String cause = ex.getMessage(); 58 | String msg = "RBroker runtime pool initialization failed: " + cause; 59 | fraudService.alertClient(msg, cause, true); 60 | } 61 | } 62 | 63 | /* 64 | * Score one or more demo account(s) with randomly generated data 65 | * for fraud. 66 | * 67 | * A call to /fraud/score/N will result in N RTasks, representing 68 | * N demo tasks with randomly generated data, being scored. 69 | */ 70 | @RequestMapping(value = "/score/{tasks}", method = RequestMethod.GET) 71 | public void score(@PathVariable("tasks") int tasks) { 72 | 73 | tasks = (tasks == 0) ? 1 : tasks; 74 | log.info("REST:/score/" + tasks + " called."); 75 | 76 | for(int i=0; i rinputs = 297 | ((PooledTaskOptions)((PooledTask)rTask).options).rinputs; 298 | 299 | fraudScore.balance = 300 | (int) ((RNumeric)rinputs.get(0)).getValue(); 301 | fraudScore.transactions = 302 | (int) ((RNumeric)rinputs.get(1)).getValue(); 303 | fraudScore.credit = 304 | (int) ((RNumeric)rinputs.get(2)).getValue(); 305 | 306 | if(rTaskResult != null) { 307 | List rObjects = rTaskResult.getGeneratedObjects(); 308 | fraudScore.score = ((RNumeric)rObjects.get(0)).getValue(); 309 | } 310 | } 311 | 312 | } catch(Exception ex) { 313 | log.warn("buildFraudScore: ex=" + ex); 314 | } 315 | 316 | return fraudScore; 317 | } 318 | 319 | /* 320 | * Private helper methods. 321 | */ 322 | 323 | private RuntimeStats populateRuntimeStats(RuntimeStats runtimeStats, 324 | RBrokerRuntimeStats stats) { 325 | 326 | runtimeStats.requestedPoolSize = brokerConfig.maxConcurrentTaskLimit; 327 | runtimeStats.allocatedPoolSize = lastAllocatedPoolSize; 328 | runtimeStats.maxConcurrency = rBroker.maxConcurrency(); 329 | 330 | runtimeStats.endpoint = brokerConfig.deployrEndpoint; 331 | if(brokerConfig.userCredentials != null) { 332 | runtimeStats.username = 333 | ((RBasicAuthentication) brokerConfig.userCredentials).getUsername(); 334 | } 335 | 336 | if(stats != null) { 337 | 338 | runtimeStats.submittedTasks = stats.totalTasksRun; 339 | runtimeStats.successfulTasks = stats.totalTasksRunToSuccess; 340 | runtimeStats.failedTasks = stats.totalTasksRunToFailure; 341 | 342 | runtimeStats.averageCodeExecution = 0L; 343 | runtimeStats.averageServerOverhead = 0L; 344 | runtimeStats.averageNetworkLatency = 0L; 345 | 346 | if(stats.totalTasksRunToSuccess > 0) { 347 | runtimeStats.averageCodeExecution = 348 | stats.totalTimeTasksOnCode/stats.totalTasksRunToSuccess; 349 | long avgTimeOnServer = 350 | stats.totalTimeTasksOnServer/stats.totalTasksRunToSuccess; 351 | runtimeStats.averageServerOverhead = 352 | avgTimeOnServer - runtimeStats.averageCodeExecution; 353 | long avgTimeOnCall = 354 | stats.totalTimeTasksOnCall/stats.totalTasksRunToSuccess; 355 | runtimeStats.averageNetworkLatency = 356 | avgTimeOnCall - avgTimeOnServer; 357 | } 358 | } 359 | 360 | return runtimeStats; 361 | } 362 | 363 | public void alertClient(String msg, String cause, boolean warning) { 364 | 365 | try { 366 | 367 | ClientMessage clientMsg = 368 | warning ? new ClientWarn() : new ClientAlert(); 369 | clientMsg.msg = msg; 370 | clientMsg.cause = cause; 371 | // Push ClientMessage over STOMP Web Socket to clients. 372 | simpMessagingTemplate.convertAndSend(FRAUDMSGTOPIC, clientMsg); 373 | 374 | } catch(Exception cex) {} 375 | 376 | } 377 | 378 | /* 379 | * Spring Lifecycle Event Handler 380 | * 381 | * Service: destroy 382 | */ 383 | @PreDestroy 384 | public void destroy() throws Exception { 385 | if(rBroker != null) { 386 | rBroker.shutdown(); 387 | } 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /src/main/java/com/revo/deployr/rbroker/example/util/RBrokerStatsHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * RBrokerStatsHelper.java 3 | * 4 | * Copyright (C) 2010-2014 by Revolution Analytics Inc. 5 | * 6 | * This program is licensed to you under the terms of Version 2.0 of the 7 | * Apache License. This program is distributed WITHOUT 8 | * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 9 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 10 | * Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more details. 11 | * 12 | */ 13 | /* 14 | * Java Fraud Detection Example Application 15 | * 16 | * RBroker runtime summary statistics (print) helper class. 17 | */ 18 | package com.revo.deployr.rbroker.example.util; 19 | 20 | import com.revo.deployr.client.broker.RTask; 21 | import com.revo.deployr.client.broker.RTaskType; 22 | import com.revo.deployr.client.broker.RTaskResult; 23 | import com.revo.deployr.client.broker.RBrokerRuntimeStats; 24 | 25 | import org.apache.log4j.Logger; 26 | 27 | public class RBrokerStatsHelper { 28 | 29 | private static Logger log = Logger.getLogger(RBrokerStatsHelper.class); 30 | 31 | /** 32 | * Prints {@link com.revo.deployr.client.broker.RBrokerRuntimeStats} 33 | * to console output. 34 | */ 35 | public static void printRBrokerStats(RBrokerRuntimeStats stats, 36 | int maxConcurrency) { 37 | 38 | log.info("RBroker Activity Summary"); 39 | log.info("RBroker: Max Concurrency [ " + 40 | maxConcurrency + " ]"); 41 | log.info("RBroker: Total Tasks Run [ " + 42 | stats.totalTasksRun + " ]"); 43 | 44 | log.info("RBroker: Tasks Ok [ " + 45 | stats.totalTasksRunToSuccess + " ] Fail [ " + 46 | stats.totalTasksRunToFailure + " ]"); 47 | 48 | long displayAvgTimeOnCode = 0L; 49 | long displayAvgTimeOnServer = 0L; 50 | long displayAvgTimeOnCall = 0L; 51 | 52 | if(stats.totalTasksRunToSuccess > 0) { 53 | displayAvgTimeOnCode = 54 | stats.totalTimeTasksOnCode/stats.totalTasksRunToSuccess; 55 | displayAvgTimeOnServer = 56 | stats.totalTimeTasksOnServer/stats.totalTasksRunToSuccess; 57 | displayAvgTimeOnCall = 58 | stats.totalTimeTasksOnCall/stats.totalTasksRunToSuccess; 59 | } 60 | 61 | log.info("RBroker: Task Average Time On Code [ " + 62 | displayAvgTimeOnCode + " ]"); 63 | log.info("RBroker: Task Average Time On Server [ " + 64 | displayAvgTimeOnServer + " ]"); 65 | log.info("RBroker: Task Average Time On Call [ " + 66 | displayAvgTimeOnCall + " ]\n"); 67 | } 68 | 69 | /** 70 | * Prints {@link com.revo.deployr.client.broker.RTaskResult} 71 | * to console output. 72 | */ 73 | public static void printRTaskResult(RTask task, 74 | RTaskResult result, 75 | Throwable throwable) { 76 | 77 | log.info("Task: " + task); 78 | 79 | if(throwable != null) { 80 | 81 | log.warn("Status[fail]: cause=" + throwable); 82 | 83 | } else { 84 | 85 | switch(result.getType()) { 86 | 87 | case DISCRETE: 88 | if(result.isSuccess()) { 89 | log.info("Status[ok]: [ code : " + 90 | result.getTimeOnCode() + " , server : " + 91 | result.getTimeOnServer() + " , call : " + 92 | result.getTimeOnCall() + " ]"); 93 | } else { 94 | log.warn("Status[fail]: cause=" + 95 | result.getFailure()); 96 | } 97 | break; 98 | 99 | case POOLED: 100 | if(result.isSuccess()) { 101 | log.info("Status[ok]: [ code : " + 102 | result.getTimeOnCode() + " , server : " + 103 | result.getTimeOnServer() + " , call : " + 104 | result.getTimeOnCall() + " ]"); 105 | } else { 106 | log.warn("Status[fail]: cause=" + 107 | result.getFailure()); 108 | } 109 | break; 110 | 111 | case BACKGROUND: 112 | if(result.isSuccess()) { 113 | log.info("Status[ok]: [ server : " + 114 | result.getTimeOnServer() + " , call : " + 115 | result.getTimeOnCall() + " ]"); 116 | } else { 117 | log.warn("Status[fail]: cause=" + 118 | result.getFailure()); 119 | } 120 | break; 121 | 122 | } 123 | } 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework: ERROR 2 | logging.level.org.apache: ERROR 3 | logging.level.com.revo.deployr: ERROR 4 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | log4j.rootLogger=INFO, stdout 3 | 4 | # DeployR RBroker Framework and Client Library 5 | log4j.category.com.revo.deployr.client=INFO 6 | 7 | # Fraud Score test application 8 | log4j.category.com.revo.deployr.rbroker.example=INFO 9 | 10 | # System packages 11 | log4j.category.org.springframework=ERROR 12 | log4j.category.org.apache=ERROR 13 | log4j.category.org.hibernate=ERROR 14 | 15 | # Direct log messages to stdout 16 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 17 | log4j.appender.stdout.Target=System.out 18 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 19 | log4j.appender.stdout.layout.ConversionPattern=%p %C{1}: - %m%n 20 | -------------------------------------------------------------------------------- /src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 33 | 34 | 35 | 36 | 37 | 44 | 45 |
46 |
47 |
48 |
49 | 51 | RBroker Runtime 52 | 53 |
54 | 55 | {{ runtimeStats.username }} @ {{ runtimeStats.endpoint }} 56 | 57 |
58 | Pool Size: 59 | 62 | Resize 67 | 68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Pool 76 |
77 |
78 |
79 |
80 | 82 | Requested Size: 83 | 84 | {{runtimeStats.requestedPoolSize}}

85 |
86 | 88 | Allocated Size: 89 | 90 | {{runtimeStats.allocatedPoolSize}}
91 |
92 | 94 | Max Concurrency: 95 | 96 | {{runtimeStats.maxConcurrency}}
97 |
98 |
99 |
100 |
101 |
102 |
Tasks
103 |
104 |
105 |
106 | 108 | Submitted Tasks: 109 | 110 | {{runtimeStats.submittedTasks}}

111 |
112 | 114 | Successful Tasks: 115 | 116 | {{runtimeStats.successfulTasks}}
117 |
118 | 120 | Failed Tasks: 121 | 122 | {{runtimeStats.failedTasks}}
123 |
124 |
125 |
126 |
127 |
128 |
Fraud Task Throughput
129 |
130 |
131 |
132 | 134 | Executed Tasks: 135 | 136 | {{currentTaskThroughput}}
137 |
138 | 140 | Tasks Per Second: 141 | 142 | {{secondTaskThroughput}}

143 |
144 | 146 | Tasks Per Minute: 147 | 148 | {{minuteTaskThroughput}}
149 |
150 | 151 |
152 |
153 |
154 |
155 |
{{alertInfoMessage}}
156 |
157 |
158 |
{{alertWarnMessage}}
159 |
160 |
161 |
162 | 163 |
164 |
165 |
166 |
167 | 169 | Fraud Analysis 170 | 171 |
172 |
173 | Task Count: 174 | 177 | Execute 182 | 183 |
184 |
185 |
186 |
187 |
188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 |
Account BalanceTransactionsCreditFraud Score
{{fraudScoreResult.balance}}{{fraudScoreResult.transactions}}{{fraudScoreResult.credit}}{{fraudScoreResult.score}}
205 |
206 |
207 | 208 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /src/main/webapp/js/controllers.js: -------------------------------------------------------------------------------- 1 | /* 2 | * controllers.js 3 | * 4 | * Copyright (C) 2010-2014 by Revolution Analytics Inc. 5 | * 6 | * This program is licensed to you under the terms of Version 2.0 of the 7 | * Apache License. This program is distributed WITHOUT 8 | * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 9 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 10 | * Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more details. 11 | * 12 | */ 13 | /* 14 | * Java Fraud Detection Example Application 15 | * 16 | * AngularJS ng-controller 17 | * 18 | * Initialization: 19 | * 20 | * Establishes STOMP connection on /fraudengine, subscribes on /topic/fraud. 21 | * 22 | * STOMP message events: 23 | * 24 | * FRAUDSCORE - RTask result message. 25 | * RUNTIMESTATS - RBroker runtime statistics message. 26 | * CLIENTALERT - RBroker runtime (error) notification message. 27 | * 28 | * User driven (index.html) events: 29 | * 30 | * Resize click -> $scope.resizePool() -> POST:/fraud/pool/init/{size} 31 | * 32 | * Execute click -> $scope.executeTasks() -> GET:/fraud/score/{tasks} 33 | * 34 | */ 35 | 36 | function fraudController($scope, $http) { 37 | 38 | // 39 | // ng-controller model on $scope. 40 | // 41 | $scope.brokerInitialized = false; 42 | $scope.alertInfoMessage = null; 43 | $scope.alertWarnMessage = null; 44 | 45 | $scope.fraudScoreResults = [ ]; 46 | $scope.poolSize = 1; 47 | $scope.taskCount = 1; 48 | 49 | $scope.runtimeStats = { 50 | requestedPoolSize: 1, 51 | allocatedPoolSize: 1, 52 | maxConcurrency: 1, 53 | submittedTasks: 0, 54 | successfulTasks: 0, 55 | failedTasks: 0, 56 | averageCodeExecution: 0, 57 | averageServerOverhead: 0, 58 | averageNetworkLatency: 0 59 | } 60 | 61 | $scope.targetTaskThroughput = 0; 62 | $scope.currentTaskThroughput = 0; 63 | $scope.startTaskThroughput = 0; 64 | $scope.secondTaskThroughput = 0; 65 | $scope.minuteTaskThroughput = 0; 66 | 67 | if($scope.socketInitialized == undefined) { 68 | 69 | // Create SockJS socket and STOMP it. 70 | var socket = new SockJS('/fraudengine'); 71 | stompClient = Stomp.over(socket); 72 | 73 | // Subscribe for events on /topic/fraud. 74 | stompClient.connect({}, function(frame) { 75 | 76 | stompClient.subscribe('/topic/fraud', function(msg){ 77 | var msgObj = JSON.parse(msg.body); 78 | 79 | if(msgObj.msgType == "FRAUDSCORE") { 80 | 81 | var elapsedTime = Date.now() - $scope.startTaskThroughput; 82 | 83 | // $apply to propogate change to model. 84 | $scope.$apply(function () { 85 | 86 | $scope.currentTaskThroughput += 1; 87 | var throughput = 88 | (1000 / elapsedTime) * $scope.currentTaskThroughput; 89 | $scope.secondTaskThroughput = (throughput - (throughput % .01)); 90 | $scope.minuteTaskThroughput = 91 | Math.round($scope.secondTaskThroughput * 60); 92 | 93 | // Discard older fraudScore from fraudScoreResults 94 | // list to prevent browser rendering exhaustion. 95 | if($scope.fraudScoreResults.length > 300) { 96 | $scope.fraudScoreResults.length = 150; 97 | } 98 | $scope.fraudScoreResults.unshift(msgObj); 99 | }); 100 | } else 101 | if(msgObj.msgType == "RUNTIMESTATS") { 102 | // $apply to propogate change to model. 103 | $scope.$apply(function () { 104 | $scope.alertInfoMessage = null; 105 | $scope.runtimeStats = msgObj; 106 | }); 107 | } else 108 | if(msgObj.msgType == "CLIENTALERT") { 109 | // $apply to propogate change to model. 110 | $scope.$apply(function () { 111 | $scope.alertInfoMessage = msgObj.msg; 112 | }); 113 | } else 114 | if(msgObj.msgType == "CLIENTWARN") { 115 | // $apply to propogate change to model. 116 | $scope.$apply(function () { 117 | $scope.alertWarnMessage = msgObj.msg; 118 | }); 119 | } 120 | }); 121 | 122 | // 123 | // Now that the STOMP connection has been established, 124 | // initialize initial RBroker pool on application startup. 125 | // 126 | $scope.resizePool(); 127 | }); 128 | 129 | $scope.socketInitialized = true; 130 | 131 | } // if $scope.socketInitialized 132 | 133 | // 134 | // Resize Button Handler: 135 | // 136 | $scope.resizePool = function() { 137 | $scope.alertWarnMessage = null; 138 | $scope.alertInfoMessage = null; 139 | $scope.brokerInitialized = false; 140 | $http.post('/fraud/pool/init/' + $scope.poolSize).success(function (data, status, headers, config) { 141 | console.log("Attempt to resize pool succeeded, new size=" + $scope.poolSize); 142 | }).error(function (data, status, headers, config) { 143 | $scope.alertWarnMessage = "Attempt to resize pool failed, error=" + data; 144 | }).finally(function () { 145 | $scope.fraudScoreResults = []; 146 | $scope.brokerInitialized = true; 147 | $scope.currentTaskThroughput = 0; 148 | $scope.secondTaskThroughput = 0; 149 | $scope.minuteTaskThroughput = 0; 150 | }); 151 | 152 | } 153 | 154 | // 155 | // Execute Button Handler: 156 | // 157 | $scope.executeTasks = function() { 158 | 159 | $scope.alertWarnMessage = null; 160 | $scope.currentTaskThroughput = 0; 161 | $scope.secondTaskThroughput = 0; 162 | $scope.minuteTaskThroughput = 0; 163 | $scope.targetTaskThroughput = $scope.taskCount; 164 | $scope.startTaskThroughput = Date.now(); 165 | 166 | $http.get('/fraud/score/' + $scope.taskCount).success(function (data, status, headers, config) { 167 | console.log("Attempt to execute tasks succeeded, taskCount=" + $scope.taskCount); 168 | }).error(function (data, status, headers, config) { 169 | $scope.alertWarnMessage = "Can't retrieve scores list!"; 170 | $scope.alertWarnMessage = "Attempt to execute tasks failed, error=" + data; 171 | }); 172 | 173 | } 174 | 175 | } 176 | --------------------------------------------------------------------------------