├── .gitignore ├── README.md ├── build.gradle ├── deploy ├── deploy.py ├── requirements.txt └── tox.ini ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── license └── license_header.txt ├── pack.sh └── src ├── cloudfoundry └── manifest.yml └── main ├── java └── org │ └── trustedanalytics │ └── examples │ └── hbase │ ├── Main.java │ ├── api │ ├── ApiController.java │ └── ExceptionHandlerAdvice.java │ ├── configs │ ├── HBaseConfig.java │ ├── HBaseConnectionFactory.java │ └── SwaggerConfig.java │ ├── model │ ├── ColumnFamilyValue.java │ ├── ColumnValue.java │ ├── RowValue.java │ └── TableDescription.java │ └── services │ ├── ConversionsService.java │ └── HBaseService.java └── resources ├── application-cloud.properties └── application.properties /.gitignore: -------------------------------------------------------------------------------- 1 | ### Java template 2 | *.class 3 | 4 | # Package Files # 5 | *.jar 6 | *.war 7 | *.ear 8 | 9 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 10 | hs_err_pid* 11 | 12 | ### JetBrains template 13 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 14 | 15 | *.iml 16 | 17 | ## Directory-based project format: 18 | .idea/ 19 | # if you remove the above rule, at least ignore the following: 20 | 21 | # User-specific stuff: 22 | # .idea/workspace.xml 23 | # .idea/tasks.xml 24 | # .idea/dictionaries 25 | 26 | # Sensitive or high-churn files: 27 | # .idea/dataSources.ids 28 | # .idea/dataSources.xml 29 | # .idea/sqlDataSources.xml 30 | # .idea/dynamic.xml 31 | # .idea/uiDesigner.xml 32 | 33 | # Gradle: 34 | # .idea/gradle.xml 35 | # .idea/libraries 36 | 37 | # Mongo Explorer plugin: 38 | # .idea/mongoSettings.xml 39 | 40 | ## File-based project format: 41 | *.ipr 42 | *.iws 43 | 44 | ## Plugin-specific files: 45 | 46 | # IntelliJ 47 | /out/ 48 | 49 | # mpeltonen/sbt-idea plugin 50 | .idea_modules/ 51 | 52 | # JIRA plugin 53 | atlassian-ide-plugin.xml 54 | 55 | # Crashlytics plugin (for Android Studio and IntelliJ) 56 | com_crashlytics_export_strings.xml 57 | crashlytics.properties 58 | crashlytics-build.properties 59 | 60 | ### Eclipse template 61 | *.pydevproject 62 | .metadata 63 | bin/ 64 | tmp/ 65 | *.tmp 66 | *.bak 67 | *.swp 68 | *~.nib 69 | local.properties 70 | .settings/ 71 | .loadpath 72 | 73 | # Eclipse Core 74 | .project 75 | 76 | # External tool builders 77 | .externalToolBuilders/ 78 | 79 | # Locally stored "Eclipse launch configurations" 80 | *.launch 81 | 82 | # CDT-specific 83 | .cproject 84 | 85 | # JDT-specific (Eclipse Java Development Tools) 86 | .classpath 87 | 88 | # Java annotation processor (APT) 89 | .factorypath 90 | 91 | # PDT-specific 92 | .buildpath 93 | 94 | # sbteclipse plugin 95 | .target 96 | 97 | # TeXlipse plugin 98 | .texlipse 99 | 100 | ### Gradle template 101 | .gradle 102 | build/ 103 | 104 | # Ignore Gradle GUI config 105 | gradle-app.setting 106 | 107 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 108 | !gradle-wrapper.jar 109 | 110 | 111 | # python related 112 | 113 | /deploy/.tox 114 | /manifest.yml 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hbase-java-api-example 2 | This is a simple example usage of HBase on Trusted Analytics Platform. 3 | 4 | This application utilizes HBase service broker (from TAP) and HBase Client API to connect to HBase. 5 | It performs basic operations, like: 6 | 7 | * list tables 8 | * show table description (column families) 9 | * get _n_ last rows from given table 10 | * get _n_ first rows from given table 11 | * create a table 12 | 13 | After being deployed to TAP it provides these functionalities through the following endpoints: 14 | 15 | |URL |method |operation | 16 | |--- |--- |--- | 17 | |/api/tables |GET |list the tables | 18 | |/api/tables |POST |create new table | 19 | |/api/tables/{name} |GET |describe details of given table | 20 | |/api/tables/{name}/head|GET |get first rows of given table | 21 | |/api/tables/{name}/tail|GET |get last rows of given table | 22 | |/api/tables/{name}/row |POST |add new value for given row| 23 | |/api/tables/{name}/row/{rowKey}|GET |get row by given row key | 24 | 25 | 26 | You can use Swagger API to work with the service: 27 | 28 | http://hbase-reader.{domain.com}/swagger-ui.html 29 | 30 | 31 | ## Under the hood 32 | This is a simple spring boot application. Key point of interest here are: 33 | 34 | * extracting HBase configuration information (required for connection; provided by hbase-broker and kerberos-broker) 35 | * connect to HBase and authenticate in kerberos 36 | * using HBase client to perform some admin operations (in our case: getting information on tables) 37 | * using HBase client to perform some operations on tables (in our case: reading data) 38 | 39 | 40 | The following sections will present information on the broker and client API role. 41 | 42 | ### HBase broker 43 | HBase broker of TAP provisions a namespace for the user. 44 | After binding to an app, it also provides some configuration information. 45 | 46 | ``` 47 | { 48 | "VCAP_SERVICES": { 49 | "hbase": [ 50 | { 51 | "credentials": { 52 | "HADOOP_CONFIG_KEY": { 53 | ... 54 | "hbase.zookeeper.property.clientPort": "2181", 55 | "hbase.zookeeper.quorum": "cdh-master-0.node.server.com,cdh-master-1.node.server.com,cdh-master-2.node.server.com", 56 | ... 57 | }, 58 | "hbase.namespace": "2bd6c4db32236dd4a33d19f8ef76257b4a69ff1b", 59 | ... 60 | }, 61 | "label": "hbase", 62 | "name": "hbase1", 63 | "plan": "bare", 64 | "tags": [] 65 | } 66 | ] 67 | ... 68 | ``` 69 | 70 | Essential fragments here are: 71 | 72 | * _name_ key - service instance name 73 | * _credential_ section - crucial configuration information, including: 74 | * zookeeper settings (required to connect to HBase) 75 | * hbase.namespace key - the namespace created for the user 76 | 77 | ### Kerberos broker 78 | In TAP Kerberos credentials can be obtained from kerberos-broker. After creating service instance and binding it to an application, the following information are available: 79 | 80 | ``` 81 | "kerberos": [ 82 | { 83 | "credentials": { 84 | "enabled": true, 85 | "kcacert": "...", 86 | "kdc": "...", 87 | "kpassword": "...", 88 | "krealm": "...", 89 | "kuser": "..." 90 | }, 91 | "label": "kerberos", 92 | "name": "kerberos-instance", 93 | "plan": "shared", 94 | "tags": [ 95 | "kerberos" 96 | ] 97 | } 98 | ] 99 | ``` 100 | 101 | ### Connecting to HBase 102 | TAP platform provides [hadoop-utils library](https://github.com/trustedanalytics/hadoop-utils "hadoop-utils"). It contains many usefull utils. 103 | For example, connecting to HBase boils down to: 104 | ```Java 105 | Hbase.newInstance().createConnection().connect(); 106 | ``` 107 | 108 | hadoop-utils takes care of the configuration and authentication (reads data from HBase and Kerberos service binding). 109 | 110 | ### HBase Java API (1.1.2) 111 | HBase project provides Java client API. 112 | 113 | If you want to use the API in your Maven project, the corresponding dependency is: 114 | 115 | ``` 116 | 117 | org.apache.hbase 118 | hbase-client 119 | 1.1.2 120 | 121 | ``` 122 | 123 | ("org.apache.hbase:hbase-client:1.1.2" for Gradle). 124 | 125 | In our case, we depend on hadoop-utils instead which bring all required dependencies: 126 | 127 | ``` 128 | 129 | org.trustedanalytics 130 | hadoop-utils 131 | 0.6.5 132 | 133 | ``` 134 | 135 | ("org.trustedanalytics:hadoop-utils:0.6.5" for Gradle) 136 | 137 | 138 | You'll find javadocs here: [https://hbase.apache.org/apidocs/index.html/](https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/package-summary.html) 139 | 140 | The API allows for interaction with HBase for DDL (administrative tasks like tables creation/deletion) and DML (data importing, querying). 141 | 142 | This sample application shows some examples of these operations. 143 | 144 | #### Row get 145 | ```Java 146 | Result r = null; 147 | try (Connection connection = hBaseConnectionFactory.connect()) { 148 | Table table = connection.getTable(TableName.valueOf(name)); 149 | Get get = new Get(Bytes.toBytes(rowKey)); 150 | r = table.get(get); 151 | } catch (org.apache.hadoop.hbase.TableNotFoundException e) { 152 | throw new TableNotFoundException(name); 153 | } catch (IOException e) { 154 | LOG.error("Error while talking to HBase.", e); 155 | } 156 | ``` 157 | 158 | #### Table scan 159 | Get first 10 rows of given table (by _name_): 160 | 161 | ```Java 162 | List result = new ArrayList<>(); 163 | try (Connection connection = hBaseConnectionFactory.connect()) { 164 | Table table = connection.getTable(TableName.valueOf(name)); 165 | 166 | Scan scan = new Scan(); 167 | scan.setFilter(new PageFilter(10)); 168 | 169 | try (ResultScanner rs = table.getScanner(scan)) { 170 | for (Result r = rs.next(); r != null; r = rs.next()) { 171 | //conversionsService.constructRowValue is a helper method (defined in the app) 172 | result.add(conversionsService.constructRowValue(r)); 173 | } 174 | } 175 | } 176 | ``` 177 | 178 | #### Admin API usage 179 | Fetch list of tables: 180 | 181 | ```Java 182 | List result = null; 183 | try (Connection connection = hBaseConnectionFactory.connect(); 184 | Admin admin = connection.getAdmin()) { 185 | HTableDescriptor[] tables = admin.listTables(); 186 | 187 | Stream tableDescriptorsStream = Arrays.stream(tables); 188 | 189 | //ConversionService.constructTableDecription is a helper method (defined in the app) 190 | result = tableDescriptorsStream.map(conversionsService::constructTableDescription) 191 | .collect(Collectors.toList()); 192 | } catch (IOException e) { 193 | LOG.error("Error while talking to HBase.", e); 194 | } 195 | ``` 196 | 197 | Of course, obtaining the connection for every operation is costly (connect to ZooKeeper, connect to HBase takes time). 198 | In real life, you'd probably strive to reuse HBase connections. 199 | 200 | ## Compiling and deploying the example 201 | ### Manual deployment 202 | App deployment is described in details on the Platform Wiki: [Getting started Guilde](https://github.com/trustedanalytics/platform-wiki/wiki/Getting%20Started%20Guide). 203 | 204 | The procedure boils down to following steps. 205 | After cloning the repository you will be able to compile the project with: 206 | 207 | ``` 208 | ./gradlew clean check assemble 209 | ``` 210 | 211 | (optional) to update headers use 212 | 213 | ``` 214 | ./gradlew licenseFormatMain 215 | ``` 216 | 217 | Before deploying, which can be done with `cf push`, make sure there is an HBase instance available for you. 218 | 219 | Also take notice that after you build the project with `gradlew assemble` 220 | the application manifest file has been auto-generated from the template **src/cloudfoundry/manifest.yml** 221 | and copied into the project root folder. 222 | 223 | 224 | If it is not already done, create an instance of HBase service: 225 | 226 | ``` 227 | cf create-service hbase bare hbase1 228 | ``` 229 | 230 | To use this instance either add it to manifest.yml or bind it to the app through CLI. 231 | 232 | 233 | If it is not already done, create an instance of Kerberos service: 234 | ``` 235 | cf create-service kerberos shared kerberos-instance 236 | ``` 237 | 238 | 239 | You can define the bindings in _services_ section of app's manifest file: 240 | 241 | ``` 242 | --- 243 | applications: 244 | - name: hbase-reader 245 | memory: 1G 246 | instances: 1 247 | host: hbase-reader 248 | path: build/libs/hbase-rest-0.0.2.jar 249 | services: 250 | - hbase1 251 | - kerberos-instance 252 | ``` 253 | 254 | > Sample manifest is provided in this project for your convenience. Please modify it for your needs (application name, service name, etc.) 255 | > For example, src/main/resources/application-cloud.properties uses HBase service name for some keys. Adjust properties file accordingly to your needs. 256 | 257 | 258 | After this you are ready to push your application to the platform: 259 | ``` 260 | cf push 261 | ``` 262 | 263 | 264 | If you plan to *bind an instance of HBase to applications that is already running*, you could do this with following commands: 265 | 266 | ``` 267 | cf bind-service hbase-reader hbase1 268 | 269 | cf bind-service hbase-reader kerberos-instance 270 | 271 | 272 | cf restage hbase-reader 273 | ``` 274 | 275 | ### Automated deployment 276 | * Switch to `deploy` directory: `cd deploy` 277 | * Install tox: `sudo -E pip install --upgrade tox` 278 | * Run: `tox` 279 | * Activate virtualenv with installed dependencies: `. .tox/py27/bin/activate` 280 | * Run deployment script: `python deploy.py` providing required parameters when running script (`python deploy.py -h` to check script parameters with their descriptions). 281 | 282 | # TO DO 283 | * update info about namespace and service name in applciation.properties. How namespace is read/used. 284 | 285 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | version = '0.1.1' 18 | 19 | buildscript { 20 | ext { 21 | springBootVersion = '1.3.3.RELEASE' 22 | } 23 | repositories { 24 | mavenCentral() 25 | maven { 26 | url 'http://repo.spring.io/release' 27 | url 'https://plugins.gradle.org/m2/' 28 | } 29 | } 30 | dependencies { 31 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 32 | classpath("io.spring.gradle:dependency-management-plugin:0.5.6.RELEASE") 33 | classpath 'gradle.plugin.nl.javadude.gradle.plugins:license-gradle-plugin:0.12.1' 34 | } 35 | } 36 | 37 | apply plugin: 'java' 38 | apply plugin: 'eclipse' 39 | apply plugin: 'idea' 40 | apply plugin: 'spring-boot' 41 | apply plugin: 'io.spring.dependency-management' 42 | apply plugin: 'application' 43 | apply plugin: 'com.github.hierynomus.license' 44 | 45 | jar { 46 | baseName = 'hbase-rest' 47 | version = project.version 48 | } 49 | 50 | sourceCompatibility = 1.8 51 | targetCompatibility = 1.8 52 | 53 | repositories { 54 | mavenLocal() 55 | mavenCentral() 56 | maven { 57 | url 'http://repo.spring.io/release' 58 | } 59 | maven { 60 | url 'http://repo.spring.io/libs-release' 61 | } 62 | } 63 | 64 | configurations { 65 | all*.exclude group: '', module: 'servlet-api' 66 | all*.exclude group: 'org.slf4j', module: 'log4j-over-slf4j' 67 | all*.exclude group: 'org.slf4j', module: 'slf4j-log4j12' 68 | } 69 | 70 | dependencies { 71 | compile("org.springframework.boot:spring-boot-starter-web") 72 | compile("org.springframework.boot:spring-boot-devtools") 73 | 74 | compile("org.trustedanalytics:hadoop-utils:0.6.11") 75 | 76 | compile("io.springfox:springfox-swagger-ui:2.4.0") { 77 | exclude group: 'com.google.guava', module: 'guava' 78 | } 79 | compile("io.springfox:springfox-swagger2:2.4.0") { 80 | exclude group: 'com.google.guava', module: 'guava' 81 | } 82 | 83 | testCompile("org.springframework.boot:spring-boot-starter-test") 84 | } 85 | 86 | eclipse { 87 | classpath { 88 | containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') 89 | containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8' 90 | } 91 | } 92 | 93 | task wrapper(type: Wrapper) { 94 | gradleVersion = '2.8' 95 | } 96 | 97 | task('info') << { 98 | println jar.baseName 99 | println jar.version 100 | } 101 | 102 | springBoot { 103 | mainClass = "org.trustedanalytics.examples.hbase.Main" 104 | } 105 | 106 | license { 107 | header rootProject.file('license/license_header.txt') 108 | ext.year = Calendar.getInstance().get(Calendar.YEAR) 109 | strictCheck true 110 | } 111 | 112 | task copyApplicationManifest(type: Copy) { 113 | from "src/cloudfoundry" 114 | include "**/*.yml" 115 | into "." 116 | 117 | filter org.apache.tools.ant.filters.ReplaceTokens, tokens: [ 118 | version: project.version 119 | ] 120 | } 121 | 122 | assemble.dependsOn copyApplicationManifest 123 | -------------------------------------------------------------------------------- /deploy/deploy.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2016 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the 'License'); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an 'AS IS' BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | """ 18 | This scripts automates deployment of hbase-reader application 19 | (creates required service instances, pushes to TAP instance). 20 | """ 21 | 22 | from app_deployment_helpers import cf_cli 23 | from app_deployment_helpers import cf_helpers 24 | 25 | APP_NAME = "hbase-reader" 26 | 27 | PARSER = cf_helpers.get_parser(APP_NAME) 28 | 29 | ARGS = PARSER.parse_args() 30 | 31 | CF_INFO = cf_helpers.get_info(ARGS) 32 | cf_cli.login(CF_INFO) 33 | 34 | cf_cli.create_service('hbase', 'bare', 'hbase1') 35 | cf_cli.create_service('kerberos', 'shared', 'kerberos-instance') 36 | 37 | PROJECT_DIR = ARGS.project_dir if ARGS.project_dir else \ 38 | cf_helpers.get_project_dir() 39 | 40 | #running script to prepare deployable jar 41 | cf_cli.run_command(['./gradlew', 'clean', 'check', 'assemble'], work_dir=PROJECT_DIR) 42 | 43 | cf_helpers.push(work_dir=PROJECT_DIR, options=ARGS.app_name) -------------------------------------------------------------------------------- /deploy/requirements.txt: -------------------------------------------------------------------------------- 1 | -e git+git@github.com:trustedanalytics/python-app-deployment-helpers.git@b1517c0f26d6079098bd473e759546550b0e5dc3#egg=app_deployment_helpers 2 | -------------------------------------------------------------------------------- /deploy/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27 3 | skipsdist = true 4 | 5 | [testenv] 6 | deps = 7 | -rrequirements.txt 8 | 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustedanalytics/hbase-java-api-example/b9309962a42f9f588a968fdaaa5a467bb2a72b1e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 19 10:55:27 CET 2015 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.8-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 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /license/license_header.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) ${year} Intel Corporation 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /pack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | OUTPUT=$(./gradlew info) 5 | declare -a lines=() 6 | IFS=$'\r\n' mapfile -t lines <<< "$OUTPUT" 7 | 8 | 9 | VERSION=${lines[2]} 10 | PROJECT_NAME=${lines[1]} 11 | PACKAGE_CATALOG=${PROJECT_NAME}-${VERSION} 12 | JAR_NAME="${PACKAGE_CATALOG}.jar" 13 | 14 | 15 | # build project 16 | ./gradlew clean assemble 17 | 18 | # create tmp catalog 19 | mkdir ${PACKAGE_CATALOG} 20 | 21 | # files to package 22 | cp manifest.yml ${PACKAGE_CATALOG} 23 | cp --parents build/libs/${JAR_NAME} ${PACKAGE_CATALOG} 24 | 25 | # prepare build manifest 26 | echo "commit_sha=$(git rev-parse HEAD)" > ${PACKAGE_CATALOG}/build_info.ini 27 | 28 | # create zip package 29 | cd ${PACKAGE_CATALOG} 30 | zip -r ../${PROJECT_NAME}-${VERSION}.zip * 31 | cd .. 32 | 33 | # remove tmp catalog 34 | rm -r ${PACKAGE_CATALOG} 35 | 36 | echo "Zip package for $PROJECT_NAME project in version $VERSION has been prepared." -------------------------------------------------------------------------------- /src/cloudfoundry/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | applications: 3 | - name: hbase-reader 4 | memory: 1G 5 | instances: 1 6 | host: hbase-reader 7 | path: build/libs/hbase-rest-@version@.jar 8 | services: 9 | - hbase1 10 | - kerberos-instance 11 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase; 17 | 18 | import org.springframework.boot.SpringApplication; 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | 21 | @SpringBootApplication 22 | public class Main { 23 | 24 | public static void main(String[] args) { 25 | SpringApplication.run(Main.class, args); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/api/ApiController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.api; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.http.HttpStatus; 22 | import org.springframework.stereotype.Controller; 23 | import org.springframework.web.bind.annotation.PathVariable; 24 | import org.springframework.web.bind.annotation.RequestBody; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | import org.springframework.web.bind.annotation.RequestMethod; 27 | import org.springframework.web.bind.annotation.ResponseBody; 28 | import org.springframework.web.bind.annotation.ResponseStatus; 29 | import org.trustedanalytics.examples.hbase.model.RowValue; 30 | import org.trustedanalytics.examples.hbase.model.TableDescription; 31 | import org.trustedanalytics.examples.hbase.services.HBaseService; 32 | 33 | import javax.security.auth.login.LoginException; 34 | import java.io.IOException; 35 | import java.util.List; 36 | 37 | @Controller 38 | @RequestMapping(value = "/api") 39 | public class ApiController { 40 | 41 | private static final Logger LOG = LoggerFactory.getLogger(ApiController.class); 42 | 43 | @Autowired HBaseService hbaseService; 44 | 45 | @RequestMapping(method = RequestMethod.GET, value = "/tables") 46 | @ResponseBody 47 | public List listTables() throws IOException, LoginException { 48 | LOG.info("listTables invoked."); 49 | return hbaseService.listTables(); 50 | } 51 | 52 | @RequestMapping(method = RequestMethod.GET, value = "/tables/{name}") 53 | @ResponseBody 54 | public TableDescription getSingleTable(@PathVariable(value = "name") String name) throws IOException, LoginException { 55 | LOG.info("getSingleTable for {}.", name); 56 | return hbaseService.getTableInfo(name); 57 | } 58 | 59 | @RequestMapping(method = RequestMethod.GET, value = "/tables/{name}/tail") 60 | @ResponseBody 61 | public List tail(@PathVariable(value = "name") String name) throws IOException, LoginException { 62 | LOG.info("tail for {}.", name); 63 | return hbaseService.head(name, true); 64 | } 65 | 66 | @RequestMapping(method = RequestMethod.GET, value = "/tables/{name}/head") 67 | @ResponseBody 68 | public List head(@PathVariable(value = "name") String name) throws IOException, LoginException { 69 | LOG.info("head for {}.", name); 70 | return hbaseService.head(name, false); 71 | } 72 | 73 | @RequestMapping(method = RequestMethod.POST, value = "/tables", consumes = "application/json") 74 | @ResponseStatus(HttpStatus.CREATED) 75 | public void createTable(@RequestBody TableDescription tableDescription) throws LoginException, IOException { 76 | LOG.info("tail for {}.", tableDescription.toString()); 77 | hbaseService.createTable(tableDescription); 78 | } 79 | 80 | @RequestMapping(method = RequestMethod.POST, value = "/tables/{name}/row", consumes = "application/json") 81 | @ResponseStatus(HttpStatus.CREATED) 82 | public void putRow(@PathVariable(value = "name") String name, @RequestBody RowValue rowValue) throws IOException, LoginException { 83 | LOG.info("put for {}, {}.", name, rowValue); 84 | hbaseService.putRow(name, rowValue); 85 | } 86 | 87 | @RequestMapping(method = RequestMethod.GET, value = "/tables/{name}/row/{rowKey}") 88 | @ResponseBody 89 | public RowValue getRow(@PathVariable(value = "name") String name, @PathVariable(value = "rowKey") String rowKey) throws IOException, LoginException { 90 | LOG.info("get for {}, {}.", name, rowKey); 91 | return hbaseService.getRow(name, rowKey); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/api/ExceptionHandlerAdvice.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.trustedanalytics.examples.hbase.api; 18 | 19 | import org.apache.hadoop.hbase.TableExistsException; 20 | import org.apache.hadoop.hbase.TableNotFoundException; 21 | import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.springframework.http.HttpStatus; 25 | import org.springframework.http.ResponseEntity; 26 | import org.springframework.http.converter.HttpMessageConversionException; 27 | import org.springframework.web.bind.annotation.ControllerAdvice; 28 | import org.springframework.web.bind.annotation.ExceptionHandler; 29 | import org.springframework.web.bind.annotation.ResponseBody; 30 | import org.springframework.web.bind.annotation.ResponseStatus; 31 | 32 | import javax.security.auth.login.LoginException; 33 | import java.io.IOException; 34 | 35 | import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation; 36 | 37 | @ControllerAdvice 38 | public class ExceptionHandlerAdvice { 39 | 40 | private static final Logger LOG = LoggerFactory.getLogger(ExceptionHandlerAdvice.class); 41 | 42 | @ExceptionHandler(HttpMessageConversionException.class) 43 | @ResponseStatus(HttpStatus.BAD_REQUEST) 44 | @ResponseBody 45 | public String handleBadRequest(Exception ex) { 46 | LOG.error("Handling request malformed exception", ex); 47 | return "Request message malformed"; 48 | } 49 | 50 | @ExceptionHandler 51 | @ResponseStatus(HttpStatus.FORBIDDEN) 52 | @ResponseBody 53 | public String handleLoginException(LoginException ex) { 54 | LOG.error("Error logging in", ex); 55 | return ex.getMessage(); 56 | } 57 | 58 | 59 | @ExceptionHandler 60 | @ResponseStatus(HttpStatus.NOT_FOUND) 61 | @ResponseBody 62 | public String handleTableNotFound(TableNotFoundException ex) { 63 | LOG.error("Table not found", ex); 64 | return ex.getMessage(); 65 | } 66 | 67 | @ExceptionHandler({TableExistsException.class, NoSuchColumnFamilyException.class}) 68 | @ResponseStatus(HttpStatus.CONFLICT) 69 | @ResponseBody 70 | public String handleConflict(Exception ex) { 71 | LOG.error("Resource already exists", ex); 72 | return ex.getMessage(); 73 | } 74 | 75 | @ExceptionHandler 76 | @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) 77 | @ResponseBody 78 | public String handleIOException(IOException ex) { 79 | LOG.error("Error while talking to HBase", ex); 80 | return "Error while talking to HBase"; 81 | } 82 | 83 | @ExceptionHandler 84 | public ResponseEntity handleGeneric(Exception ex) { 85 | LOG.error("Handling generic exception", ex); 86 | HttpStatus responseStatus = resolveAnnotatedResponseStatus(ex); 87 | if (responseStatus == null) { 88 | return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); 89 | } 90 | return new ResponseEntity<>(ex.getMessage(), responseStatus); 91 | } 92 | 93 | private HttpStatus resolveAnnotatedResponseStatus(Throwable ex) { 94 | ResponseStatus responseStatus = findMergedAnnotation(ex.getClass(), ResponseStatus.class); 95 | if (responseStatus != null) { 96 | return responseStatus.code(); 97 | } 98 | else if (ex.getCause() instanceof Exception) { 99 | return resolveAnnotatedResponseStatus(ex.getCause()); 100 | } 101 | return null; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/configs/HBaseConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.configs; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.trustedanalytics.hadoop.config.client.helper.Hbase; 21 | 22 | import java.io.IOException; 23 | 24 | @Configuration 25 | public class HBaseConfig { 26 | 27 | @Bean 28 | public HBaseConnectionFactory hBaseFactory() { 29 | return () -> Hbase.newInstance().createConnection(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/configs/HBaseConnectionFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.configs; 17 | 18 | import org.apache.hadoop.hbase.client.Connection; 19 | 20 | import javax.security.auth.login.LoginException; 21 | import java.io.IOException; 22 | 23 | @FunctionalInterface 24 | public interface HBaseConnectionFactory { 25 | Connection connect() throws IOException, LoginException; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/configs/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.trustedanalytics.examples.hbase.configs; 18 | 19 | import com.google.common.base.Predicates; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | import springfox.documentation.builders.ApiInfoBuilder; 23 | import springfox.documentation.builders.PathSelectors; 24 | import springfox.documentation.builders.RequestHandlerSelectors; 25 | import springfox.documentation.service.ApiInfo; 26 | import springfox.documentation.service.Contact; 27 | import springfox.documentation.spi.DocumentationType; 28 | import springfox.documentation.spring.web.plugins.Docket; 29 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 30 | 31 | @Configuration 32 | @EnableSwagger2 33 | public class SwaggerConfig { 34 | @Bean 35 | public Docket api() { 36 | return new Docket(DocumentationType.SWAGGER_2) 37 | .select() 38 | .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot"))) 39 | .paths(PathSelectors.any()) 40 | .build().apiInfo(apiInfo()); 41 | } 42 | 43 | private ApiInfo apiInfo() { 44 | return new ApiInfoBuilder() 45 | .title("HBase REST API") 46 | .description("HBase REST API SwaggerUI") 47 | .contact(new Contact("TAP.Ganymede", "", "")) 48 | .version("0.1.0") 49 | .build(); 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/model/ColumnFamilyValue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.model; 17 | 18 | import java.util.List; 19 | 20 | public class ColumnFamilyValue { 21 | private final String familyName; 22 | private final List columnValues; 23 | 24 | public ColumnFamilyValue() { 25 | this.familyName = null; 26 | this.columnValues = null; 27 | } 28 | 29 | public ColumnFamilyValue(String familyName, List columnValues) { 30 | this.familyName = familyName; 31 | this.columnValues = columnValues; 32 | } 33 | 34 | public String getFamilyName() { 35 | return familyName; 36 | } 37 | 38 | public List getColumnValues() { 39 | return columnValues; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "ColumnFamilyValue{" + 45 | "familyName='" + familyName + '\'' + 46 | ", columnValues=" + columnValues + 47 | '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/model/ColumnValue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.model; 17 | 18 | public class ColumnValue { 19 | private final String column; 20 | private final String value; 21 | 22 | public ColumnValue() { 23 | this.column = null; 24 | this.value = null; 25 | } 26 | 27 | public ColumnValue(String column, String value) { 28 | this.column = column; 29 | this.value = value; 30 | } 31 | 32 | public String getValue() { 33 | return value; 34 | } 35 | 36 | public String getColumn() { 37 | return column; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "ColumnValue{" + 43 | "column='" + column + '\'' + 44 | ", value='" + value + '\'' + 45 | '}'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/model/RowValue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.model; 17 | 18 | import java.util.List; 19 | 20 | public class RowValue { 21 | 22 | private final String rowKey; 23 | private final List columnFamilies; 24 | 25 | public RowValue() { 26 | this.rowKey = null; 27 | this.columnFamilies = null; 28 | } 29 | 30 | public RowValue(String rowKey, List columnFamilies) { 31 | this.rowKey = rowKey; 32 | this.columnFamilies = columnFamilies; 33 | } 34 | 35 | public String getRowKey() { 36 | return rowKey; 37 | } 38 | 39 | public List getColumnFamilies() { 40 | return columnFamilies; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/model/TableDescription.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.model; 17 | 18 | import java.util.List; 19 | 20 | public class TableDescription { 21 | 22 | private final String tableName; 23 | private final List columnFamilies; 24 | 25 | public TableDescription() { 26 | this.tableName = null; 27 | this.columnFamilies = null; 28 | } 29 | 30 | public TableDescription(String tableName) { 31 | this.tableName = tableName; 32 | this.columnFamilies = null; 33 | 34 | } 35 | 36 | public TableDescription(String tableName, List columnFamilies) { 37 | this.tableName = tableName; 38 | this.columnFamilies = columnFamilies; 39 | } 40 | 41 | public String getTableName() { 42 | return tableName; 43 | } 44 | 45 | public List getColumnFamilies() { 46 | return columnFamilies; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "TableDescription{" + 52 | "tableName='" + tableName + '\'' + 53 | ", columnFamilies=" + columnFamilies + 54 | '}'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/services/ConversionsService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.services; 17 | 18 | import org.apache.hadoop.hbase.HColumnDescriptor; 19 | import org.apache.hadoop.hbase.HTableDescriptor; 20 | import org.apache.hadoop.hbase.client.Result; 21 | import org.springframework.stereotype.Service; 22 | import org.trustedanalytics.examples.hbase.model.ColumnFamilyValue; 23 | import org.trustedanalytics.examples.hbase.model.ColumnValue; 24 | import org.trustedanalytics.examples.hbase.model.RowValue; 25 | import org.trustedanalytics.examples.hbase.model.TableDescription; 26 | 27 | import java.util.Collection; 28 | import java.util.List; 29 | import java.util.NavigableMap; 30 | import java.util.stream.Collectors; 31 | 32 | @Service 33 | public class ConversionsService { 34 | 35 | public TableDescription constructTableDescription(HTableDescriptor htd) { 36 | TableDescription result = null; 37 | 38 | if (htd != null) { 39 | String name = htd.getNameAsString(); 40 | Collection families = htd.getFamilies(); 41 | 42 | List familiesNames = families.stream() 43 | .map(HColumnDescriptor::getNameAsString) 44 | .collect(Collectors.toList()); 45 | 46 | result = new TableDescription(name, familiesNames); 47 | } 48 | 49 | return result; 50 | } 51 | 52 | public RowValue constructRowValue(Result r) { 53 | RowValue result = null; 54 | 55 | if (r != null && !r.isEmpty()) { 56 | String rowKey = new String(r.getRow()); 57 | 58 | // Map> 59 | NavigableMap> valueMap = r.getNoVersionMap(); 60 | 61 | List families = valueMap.entrySet().stream() 62 | .map(b -> new ColumnFamilyValue(new String(b.getKey()), constructColumnValues(b.getValue()))) 63 | .collect(Collectors.toList()); 64 | 65 | result = new RowValue(rowKey, families); 66 | } 67 | 68 | return result; 69 | } 70 | 71 | private List constructColumnValues(NavigableMap map) { 72 | List result = null; 73 | result = map.entrySet().stream() 74 | .map(i -> new ColumnValue(new String(i.getKey()), new String(i.getValue()))) 75 | .collect(Collectors.toList()); 76 | return result; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/org/trustedanalytics/examples/hbase/services/HBaseService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.trustedanalytics.examples.hbase.services; 17 | 18 | import org.apache.hadoop.conf.Configuration; 19 | import org.apache.hadoop.hbase.HColumnDescriptor; 20 | import org.apache.hadoop.hbase.HTableDescriptor; 21 | import org.apache.hadoop.hbase.TableName; 22 | import org.apache.hadoop.hbase.client.*; 23 | import org.apache.hadoop.hbase.filter.PageFilter; 24 | import org.apache.hadoop.hbase.util.Bytes; 25 | import org.apache.hadoop.hbase.util.Strings; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | import org.springframework.beans.factory.annotation.Value; 29 | import org.springframework.stereotype.Service; 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | import org.trustedanalytics.examples.hbase.configs.HBaseConnectionFactory; 32 | import org.trustedanalytics.examples.hbase.model.ColumnFamilyValue; 33 | import org.trustedanalytics.examples.hbase.model.ColumnValue; 34 | import org.trustedanalytics.examples.hbase.model.RowValue; 35 | import org.trustedanalytics.examples.hbase.model.TableDescription; 36 | 37 | import javax.security.auth.login.LoginException; 38 | import java.io.IOException; 39 | import java.util.ArrayList; 40 | import java.util.Arrays; 41 | import java.util.List; 42 | import java.util.stream.Collectors; 43 | import java.util.stream.Stream; 44 | 45 | @Service 46 | public class HBaseService { 47 | 48 | private static final Logger LOG = LoggerFactory.getLogger(HBaseService.class); 49 | 50 | @Autowired 51 | ConversionsService conversionsService; 52 | 53 | @Autowired 54 | HBaseConnectionFactory hBaseConnectionFactory; 55 | 56 | @Value("${hbase.namespace}") 57 | private String hbaseNamespace; 58 | 59 | @Value("${results.pageSize}") 60 | private int pageSize; 61 | 62 | /** 63 | * Get list of tables in given namespace; 64 | */ 65 | public List listTables() throws LoginException { 66 | List result = null; 67 | 68 | try (Connection connection = hBaseConnectionFactory.connect(); 69 | Admin admin = connection.getAdmin()) { 70 | HTableDescriptor[] tables = admin.listTables(); 71 | 72 | Stream tableDescriptorsStream = Arrays.stream(tables); 73 | 74 | result = tableDescriptorsStream.map(conversionsService::constructTableDescription) 75 | .collect(Collectors.toList()); 76 | } catch (IOException e) { 77 | LOG.error("Error while talking to HBase.", e); 78 | } 79 | 80 | return result; 81 | } 82 | 83 | public TableDescription getTableInfo(String name) throws IOException, LoginException { 84 | TableDescription result = null; 85 | 86 | try (Connection connection = hBaseConnectionFactory.connect(); 87 | Admin admin = connection.getAdmin()) { 88 | HTableDescriptor tableDesc = admin.getTableDescriptor(TableName.valueOf(name)); 89 | result = conversionsService.constructTableDescription(tableDesc); 90 | } 91 | 92 | return result; 93 | } 94 | 95 | public List head(String name, boolean reverse) throws IOException, LoginException { 96 | List result = new ArrayList<>(); 97 | 98 | try (Connection connection = hBaseConnectionFactory.connect()) { 99 | Table table = connection.getTable(TableName.valueOf(name)); 100 | 101 | Scan scan = new Scan(); 102 | scan.setReversed(reverse); 103 | scan.setFilter(new PageFilter(pageSize)); 104 | try (ResultScanner rs = table.getScanner(scan)) { 105 | for (Result r = rs.next(); r != null; r = rs.next()) { 106 | result.add(conversionsService.constructRowValue(r)); 107 | } 108 | } 109 | } 110 | 111 | return result; 112 | } 113 | 114 | 115 | public void createTable(TableDescription tableDescription) throws IOException, LoginException { 116 | try (Connection connection = hBaseConnectionFactory.connect(); 117 | Admin admin = connection.getAdmin()) { 118 | 119 | HTableDescriptor table = new HTableDescriptor(TableName.valueOf(ensureNamespace(tableDescription.getTableName()))); 120 | for (String columnFamily : tableDescription.getColumnFamilies()) { 121 | table.addFamily(new HColumnDescriptor(columnFamily)); 122 | } 123 | 124 | admin.createTable(table); 125 | } 126 | } 127 | 128 | public void putRow(String name, RowValue row) throws IOException, LoginException { 129 | try (Connection connection = hBaseConnectionFactory.connect()) { 130 | Table table = connection.getTable(TableName.valueOf(name)); 131 | 132 | Put p = new Put(Bytes.toBytes(row.getRowKey())); 133 | for (ColumnFamilyValue family : row.getColumnFamilies() ) { 134 | for (ColumnValue column : family.getColumnValues()) { 135 | p.addColumn(Bytes.toBytes(family.getFamilyName()), Bytes.toBytes(column.getColumn()),Bytes.toBytes(column.getValue())); 136 | } 137 | } 138 | table.put(p); 139 | 140 | } 141 | } 142 | 143 | public RowValue getRow(String name, String rowKey) throws IOException, LoginException { 144 | Result r = null; 145 | try (Connection connection = hBaseConnectionFactory.connect()) { 146 | Table table = connection.getTable(TableName.valueOf(name)); 147 | Get get = new Get(Bytes.toBytes(rowKey)); 148 | r = table.get(get); 149 | } 150 | 151 | return conversionsService.constructRowValue(r); 152 | } 153 | 154 | private String ensureNamespace(String tableName) { 155 | if (!tableName.contains(":") && !Strings.isEmpty(hbaseNamespace)) { 156 | tableName = String.format("%s:%s", hbaseNamespace, tableName); 157 | } 158 | 159 | return tableName; 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/main/resources/application-cloud.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2016 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | hbase.namespace=${vcap.services.hbase1.credentials.hbase.namespace:} 18 | results.pageSize=10 -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2016 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | hbase.namespace= 18 | results.pageSize=10 --------------------------------------------------------------------------------