├── .gitignore ├── .rat-excludes ├── .travis.yml ├── KEYS ├── LICENSE ├── README.md ├── client ├── .rat-excludes ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── apache │ │ └── predictionio │ │ └── sdk │ │ └── java │ │ ├── APIResponse.java │ │ ├── BaseClient.java │ │ ├── DateTimeAdapter.java │ │ ├── EngineClient.java │ │ ├── Event.java │ │ ├── EventClient.java │ │ ├── FileExporter.java │ │ ├── FutureAPIResponse.java │ │ └── package-info.java │ └── test │ └── java │ └── org │ └── apache │ └── predictionio │ └── sdk │ └── java │ └── FileExporterTest.java ├── examples ├── import │ ├── .gitignore │ ├── pom.xml │ ├── sampledata │ │ └── sample1.txt │ └── src │ │ └── main │ │ └── java │ │ └── org │ │ └── apache │ │ └── predictionio │ │ └── samples │ │ └── SampleImport.java └── quickstart_import │ ├── .gitignore │ ├── pom.xml │ └── src │ └── main │ └── java │ └── org │ └── apache │ └── predictionio │ └── samples │ └── QuickstartImport.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # IDE working files 9 | *.iws 10 | *.ipr 11 | *.iml 12 | .idea/ 13 | .settings 14 | .project 15 | .classpath 16 | 17 | .DS_Store 18 | 19 | target/ 20 | -------------------------------------------------------------------------------- /.rat-excludes: -------------------------------------------------------------------------------- 1 | .rat-excludes 2 | examples/import/sampledata/sample1.txt -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | language: java 17 | jdk: 18 | - openjdk7 19 | - openjdk8 20 | - oraclejdk8 21 | - oraclejdk9 22 | -------------------------------------------------------------------------------- /KEYS: -------------------------------------------------------------------------------- 1 | This file contains the PGP keys of various developers. 2 | Please don't use them for email unless you have to. Their main 3 | purpose is code signing. 4 | 5 | Users: pgp < KEYS 6 | gpg --import KEYS 7 | Developers: 8 | pgp -kxa and append it to this file. 9 | (pgpk -ll && pgpk -xa ) >> this file. 10 | (gpg --list-sigs 11 | && gpg --armor --export ) >> this file. 12 | 13 | -------------------------------------------------------------------------------------------- 14 | 15 | pub 4096R/8BF4ABEB 2016-08-01 16 | uid Donald Szeto (CODE SIGNING KEY) 17 | sig 3 8BF4ABEB 2016-08-01 Donald Szeto (CODE SIGNING KEY) 18 | sub 4096R/D8AB5D20 2016-08-01 19 | sig 8BF4ABEB 2016-08-01 Donald Szeto (CODE SIGNING KEY) 20 | 21 | -----BEGIN PGP PUBLIC KEY BLOCK----- 22 | Version: GnuPG v1 23 | 24 | mQINBFefie0BEAC8RvYKQJ7xOeqaBKAi+PpcRvLxvpO9G8HIXDiw/6GCO3/tBHJ8 25 | Z2NMfGtFx351R+YpAd2KsiInU4iB25YoTeUqCrwR81zBnXPuNsKs6FXqSLlOZrYq 26 | O+a9wLkBY7bh6ABRc3OI3kGTpFMSqq8tlaJyLHvQIREHtQFckjSONMOjSnR0EAfn 27 | 4DQS3xgVZNAUbpLeJUdc3B5XYAIzMnkFBPSXEQkBmA97kkDrgaoPpeUdGW4Cqsfz 28 | ekUjkjxcax9Dp/OjhLKWmLabHdiVp161Td0x6e24rBaGSVNRlpNLHXfBCBW/+iml 29 | iGEh8OGtW/Fc8b4V4HEhTXPbVLpvgt22T17OTIYKyueUGvSd+AIS0053asLlO9kQ 30 | X4Y00sH8nnCtJgeTDwwLiudCENvYmE5PvX6Kwiq3tOZJN/onFRKnOHrssXbPd87m 31 | +82yDx8/oKYKEoA23bz8f7yMPeqmiedgRr4/1b+ToVtiKSUGtnyzLiXbC2c0sxAZ 32 | /L8qFMEWQmO/iDMq5+JmMvZld+Ns4AO81gg+WiWoCaE0YB3kqo1L3yP+D0FDETke 33 | 5Ky0i2RtVlCzoM9aXz0zQkHx7vhN24h2IJdCADhGAloykmNVxIqlsbDxx02SsNgV 34 | IuZQ+jq9zwL/VR3UUm8uJ+o55XcgBDjBPALvilMTnUG+tB99ip9H/p3l2QARAQAB 35 | tDNEb25hbGQgU3pldG8gKENPREUgU0lHTklORyBLRVkpIDxkb25hbGRAYXBhY2hl 36 | Lm9yZz6JAjcEEwEKACEFAlefie0CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AA 37 | CgkQbHTsq4v0q+ub4xAArvZBq7K1FjtqiKdwuOqOXGLuQC7Eq8e7mYUvac08nNsq 38 | rkvr2RtCDN9VaPbYh9TNJ/7BdcwG6IXOmOsW24FsAnrLSueGaw3zuaAhz8Q/vn+b 39 | 7VPcJ3OQEHbNpHlVkAur2NzZobznNhWGK4M9LQnXrVxEMTTDTd5MJqdDKAPNZ/TE 40 | Aav0AiAlOd56U8ONswBHgjqlXoS/xHvsUI9UrJIFGkdz96I1ohdcjmjkDiCYFJRt 41 | 2NvSWgGEtiN8oykYSCjU1qlyPgcIkdHu5E5xy5fXvVdQEV3bc/Y0Ghf02W6Nb8RY 42 | fuq8qBtBVhbi6T0xqwnuh5iuuO4k1BAJUUC2H+c68VTUWWJ0b6Wzz1x54MClUwQV 43 | u1hrBFbMGubRTo6uuB9hKMzwXfl3WY6iBXQvb1eY+Y0Fu/NEnNSSSVFq+qyaluUq 44 | 9RQn5u0+VCULomzr0TME4Etd+UbIliiylVFg+mtalvha0z5CrE4EJOJ/c+efI/JP 45 | vN/WOSJ44JDXUocvp05cZ0GZGyBcfTEepb/gR1dpidoYBnvScWkBak7P4trkadCS 46 | vpjbMPtWOOEa7hVP+vZg1MvmelZ2o+VvuyWvGMHryimpV6tFFtbiGR03ltC3cN1t 47 | HmjYjSb9rIsXGIN2c+b1LLuR0zxaK46y8UKNMWrwI++9Iqbl4BrBN4oofD78p4W5 48 | Ag0EV5+J7QEQAKkBVsL1zSlOuh/GAeXBs3aIwfY+eQD3PIeo4DsCD1J1M8Dn5xa7 49 | SBHqM+aql7t9hw2iIdqioS8P9ScN1uyWi/MppxDVdTR526ViBR8+739EeprzWPn2 50 | k+cTGoTeisxQjgLgC/C48taCHDPcztDUh+rLnmcKxKJA+dfqswtiAK7qxCHrT+jq 51 | 5ru78lDqzbHbJU6BqsEyzP9rwtMnGzjbevNC8YLddkZ8iF8KQgSlr93EXlDj6KaU 52 | pZs1AUkPg4UEEkuHJv+pjDhqNfoRSM1vqFyilEe4dWFW+MOKt6yiexVmHB2kgXuV 53 | 7J0PjFi4V2tlgInDhimrvW/6gg2b0EPNF3hPIAo9dBUDpW5EEj1HG+CFPEvLBOHX 54 | V3LLi5NLDSnj8iL4eiJV+l0/pQToAxDjV7VwFQ3T7gLyKM1YwkOXtS8GsjtqCsJ8 55 | xIGVWsgmaZWpZSIRuEWhgSLwSPOjZjo2YvXQA3WMdslrx+5/ZF5ElFPBKCYXxpUB 56 | DkSQ/jTLRSitAXH/0rHrsdw+TZdaW8GPsx7tzdXQVK1PajEpBIx5r+Ix/uhQarwr 57 | 9T2yBQ75rMfPPCccHbAI5g4aGpAEpDNnXfjiYi2fEffB5mEiaDaftiHqjOcoMOBw 58 | OpN7Y6V+IWniaaqEfWfGMBjM+G/m6veLIgQhAv91TmWvdMksunM9sTAFABEBAAGJ 59 | Ah8EGAEKAAkFAlefie0CGwwACgkQbHTsq4v0q+v1rQ//bp0a6vBrRYJU5RKTZ5me 60 | Ux93RT5BxZqf0wX4deCz0GiaD9G8fJ9HZyv1jedygIeBiSU/dkrkemGA8j0fchca 61 | An8yt4tNamo4AAdkvmPa9c7Z4qpHQvKpKDqrVT+ztB+a6qGFjx9cw3iioji3HW9m 62 | ykOPYYk03q9H8h0dW2sa4jaVlXNq/3b2t5cWJ14GGk9XkraSfd+0ZEIT8ffT6u45 63 | B5l35FuzBdxjyNh91T9UGrREjo1e5sgB0WSss/EJVBAJq+xDbWeOgE/azXQ1MhT+ 64 | Z+BwKfMfvI35SIHG4Ngr/OSirZbQy4s+OktFBbGhBy7dlmWbS2A9SMn7pt9e/i9K 65 | Y44sFGC1xAjq2gnVhbkal0mvT0iDLwIe4/sWuMZJHG05wUGJNMqf8au9KjVj5NzT 66 | iDo8roJi4jFolm6YmH6FRFCeYmLON0pXdNFnCe+cLanrQDI59TBgHh/XPFweOjla 67 | LqMCEjGpfSLvnopusA1SJUnenwjWWecdfnChnSB8EVIkBiAah1DP1wk+Qy9YfZlj 68 | MV2jufd24oqFWQmddOCCkIPYeDOavZvcxYevdftY3LX1B4WbiZOMHqh/HDH2NkyW 69 | 6YQIPrw2fEHG2av55RCzCKVcW0PKgW05zjUWwFVo7gEaj5CHK/SeYv0Fpc6QQKls 70 | 93sbykwywNMHkdFPE0109cM= 71 | =QAQh 72 | -----END PGP PUBLIC KEY BLOCK----- 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apache PredictionIO Java SDK 2 | 3 | This bulk of this README is divided into two sections: Using the SDK and developing the SDK. 4 | Choose the one the suits you. For support please see the bottom of this README. 5 | 6 | # Using the SDK 7 | 8 | ## With Maven 9 | 10 | If you have a Maven project, simply add the dependency to your `pom.xml`. 11 | 12 | ```XML 13 | 14 | ... 15 | 16 | 17 | org.apache.predictionio 18 | predictionio-sdk-java-client 19 | 0.13.0 20 | 21 | 22 | ... 23 | ``` 24 | 25 | 26 | ## With Ivy 27 | 28 | If you use Ivy, simply add the dependency to your `ivy.xml`. 29 | 30 | ```XML 31 | 32 | ... 33 | 34 | 35 | ... 36 | 37 | ... 38 | ``` 39 | 40 | 41 | ## With sbt 42 | 43 | If you have an sbt project, add the library dependency to your build definition. 44 | 45 | ```Scala 46 | libraryDependencies += "org.apache.predictionio" % "predictionio-sdk-java-client" % "0.13.0" 47 | ``` 48 | 49 | 50 | ## Examples 51 | 52 | Please check out the examples under `examples/`. 53 | 54 | 55 | # Developing SDK - Building from Source 56 | 57 | Fork and clone from GitHub. The following assumes you are cloning to your home directory. 58 | 59 | ```sh 60 | cd ~ 61 | git clone https://github.com//predictionio-sdk-java.git 62 | ``` 63 | 64 | To build this SDK you will need Maven 3+. Run the following to publish the module to your local 65 | Maven repository. 66 | 67 | ```sh 68 | cd ~/predictionio-sdk-java 69 | mvn clean install 70 | ``` 71 | 72 | Run the following to generate API documentation. 73 | 74 | ```sh 75 | mvn javadoc:javadoc 76 | ``` 77 | 78 | 79 | # Running CLI Examples 80 | 81 | 82 | ## Building 83 | 84 | If your PredictionIO server is not at `localhost`, edit the source and replace API URLs with your 85 | redictionIO server host. 86 | 87 | To build these examples you will need Maven 3+. Run the following in each example's directory, e.g. 88 | 89 | ```sh 90 | cd ~/predictionio-sdk-java/examples/quickstart_import 91 | mvn clean compile assembly:single 92 | cd ~/predictionio-sdk-java/examples/import 93 | mvn clean compile assembly:single 94 | ``` 95 | 96 | These will create JAR files with all dependencies built in. 97 | 98 | 99 | ## Try It Now 100 | 101 | For running the quick start example (`quickstart_import`), please refer to the "Quick Start" page of 102 | the PredictionIO documentation. Most importantly, create an App with `pio new app MyApp` and take 103 | note of the `Access Key` produced, which will be `` in the following. 104 | 105 | For `quickstart_import`, 106 | 107 | ```sh 108 | cd ~/predictionio-sdk-java/examples/quickstart_import 109 | java -jar target/quickstart-import--jar-with-dependencies.jar 110 | ``` 111 | 112 | To check the data has been imported successfully, run 113 | ```sh 114 | curl -i -X GET http://localhost:7070/events.json?accessKey= 115 | ``` 116 | 117 | To import the provided small sample data for the import example using asynchronous calls: 118 | 119 | ```sh 120 | cd ~/predictionio-sdk-java/examples/import 121 | java -jar target/sample-import--jar-with-dependencies.jar sampledata/sample1.txt 122 | ``` 123 | 124 | To check the data is imported properly, run 125 | ```sh 126 | curl -i -X GET http://localhost:7070/events.json?accessKey= 127 | ``` 128 | 129 | Enjoy! 130 | 131 | 132 | # Support 133 | 134 | 135 | ## Bugs and Feature Requests 136 | 137 | Use [Apache JIRA](https://issues.apache.org/jira/browse/PIO) to report bugs or request new features. 138 | 139 | 140 | ## Community 141 | 142 | Keep track of development and community news. 143 | 144 | * Subscribe to the user mailing list 145 | and the dev mailing list 146 | * Follow [@predictionio](https://twitter.com/predictionio) on Twitter. 147 | 148 | 149 | ## Contributing 150 | 151 | Read the [Contribute Code](http://predictionio.apache.org/community/contribute-code/) page. 152 | 153 | 154 | ## License 155 | 156 | Apache PredictionIO is under [Apache 2 157 | license](http://www.apache.org/licenses/LICENSE-2.0.html). -------------------------------------------------------------------------------- /client/.rat-excludes: -------------------------------------------------------------------------------- 1 | .rat-excludes 2 | -------------------------------------------------------------------------------- /client/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 4.0.0 18 | 19 | 20 | org.apache.predictionio 21 | predictionio-sdk-java 22 | 0.13.1-SNAPSHOT 23 | 24 | 25 | predictionio-sdk-java-client 26 | jar 27 | 28 | Apache PredictionIO Java SDK: Client 29 | 30 | 31 | UTF-8 32 | 33 | 34 | 35 | 36 | com.ning 37 | async-http-client 38 | 1.9.33 39 | 40 | 41 | com.google.code.gson 42 | gson 43 | 2.2.4 44 | 45 | 46 | joda-time 47 | joda-time 48 | 2.3 49 | 50 | 51 | junit 52 | junit 53 | 4.11 54 | test 55 | 56 | 57 | com.github.tomakehurst 58 | wiremock 59 | 1.48 60 | test 61 | 62 | 63 | org.hamcrest 64 | hamcrest-all 65 | 1.3 66 | test 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-compiler-plugin 75 | 76 | UTF-8 77 | 1.7 78 | 1.7 79 | 80 | 81 | 82 | org.apache.maven.plugins 83 | maven-source-plugin 84 | 85 | 86 | attach-sources 87 | 88 | jar 89 | 90 | 91 | 92 | 93 | 94 | org.apache.maven.plugins 95 | maven-javadoc-plugin 96 | 97 | 98 | attach-javadocs 99 | 100 | jar 101 | 102 | 103 | 104 | 105 | 106 | org.codehaus.mojo 107 | emma-maven-plugin 108 | 1.0-alpha-3 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/APIResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | /** 21 | * API Response class for wrapping responses. 22 | * 23 | * @version 0.8.3 24 | * @since 0.2 25 | */ 26 | 27 | public class APIResponse { 28 | 29 | private int status; 30 | private String message; 31 | 32 | public APIResponse(int status, String message) { 33 | this.status = status; 34 | this.message = message; 35 | } 36 | 37 | public int getStatus() { 38 | return this.status; 39 | } 40 | 41 | public void setStatus(int status) { 42 | this.status = status; 43 | } 44 | 45 | public String getMessage() { 46 | return this.message; 47 | } 48 | 49 | public void setMessage(String message) { 50 | this.message = message; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/BaseClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | import com.google.gson.JsonParser; 21 | import com.ning.http.client.AsyncHandler; 22 | import com.ning.http.client.AsyncHttpClient; 23 | import com.ning.http.client.AsyncHttpClientConfig; 24 | import com.ning.http.client.HttpResponseBodyPart; 25 | import com.ning.http.client.HttpResponseHeaders; 26 | import com.ning.http.client.HttpResponseStatus; 27 | import com.ning.http.client.Response; 28 | import com.ning.http.client.extra.ThrottleRequestFilter; 29 | import com.ning.http.client.providers.netty.NettyAsyncHttpProvider; 30 | import java.io.Closeable; 31 | import java.io.IOException; 32 | import java.util.concurrent.ExecutionException; 33 | 34 | /** 35 | * BaseClient contains code common to both {@link EventClient} and {@link EngineClient}. 36 | * 37 | * @version 0.8.3 38 | * @since 0.1 39 | */ 40 | public abstract class BaseClient implements Closeable { 41 | 42 | private static final int defaultThreadLimit = 1; 43 | private static final int defaultQSize = 0; 44 | private static final int defaultTimeout = 5; 45 | 46 | // HTTP status code 47 | static final int HTTP_OK = 200; 48 | static final int HTTP_CREATED = 201; 49 | 50 | // API Url 51 | final String apiUrl; 52 | 53 | final AsyncHttpClient client; 54 | 55 | final JsonParser parser = new JsonParser(); 56 | 57 | /** 58 | * @param apiUrl the URL of the PredictionIO API 59 | */ 60 | public BaseClient(String apiUrl) { 61 | this(apiUrl, BaseClient.defaultThreadLimit); 62 | } 63 | 64 | /** 65 | * @param apiUrl the URL of the PredictionIO API 66 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 67 | */ 68 | public BaseClient(String apiUrl, int threadLimit) { 69 | this(apiUrl, threadLimit, defaultQSize); 70 | } 71 | 72 | /** 73 | * @param apiUrl the URL of the PredictionIO API 74 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 75 | * @param queueSize size of the queue 76 | */ 77 | public BaseClient(String apiUrl, int threadLimit, int queueSize) { 78 | this(apiUrl, threadLimit, queueSize, defaultTimeout); 79 | } 80 | 81 | /** 82 | * @param apiUrl the URL of the PredictionIO API 83 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 84 | * @param queueSize size of the queue 85 | * @param timeout timeout in seconds for the connections 86 | */ 87 | public BaseClient(String apiUrl, int threadLimit, int queueSize, int timeout) { 88 | this.apiUrl = apiUrl; 89 | // Async HTTP client config 90 | AsyncHttpClientConfig config = (new AsyncHttpClientConfig.Builder()) 91 | .setAllowPoolingConnections(true) 92 | .setAllowPoolingSslConnections(true) 93 | .addRequestFilter(new ThrottleRequestFilter(threadLimit)) 94 | .setMaxConnectionsPerHost(threadLimit) 95 | .setRequestTimeout(timeout * 1000) 96 | .setIOThreadMultiplier(threadLimit) 97 | .build(); 98 | this.client = new AsyncHttpClient(new NettyAsyncHttpProvider(config), config); 99 | } 100 | 101 | /** 102 | * Close all connections associated with this client. It is a good practice to always close the 103 | * client after use. 104 | */ 105 | @Override 106 | public void close() { 107 | client.close(); 108 | } 109 | 110 | AsyncHandler getHandler() { 111 | return new AsyncHandler() { 112 | private final Response.ResponseBuilder builder = new Response.ResponseBuilder(); 113 | 114 | public void onThrowable(Throwable throwable) { 115 | } 116 | 117 | public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { 118 | builder.accumulate(content); 119 | return STATE.CONTINUE; 120 | } 121 | 122 | public STATE onStatusReceived(HttpResponseStatus status) throws Exception { 123 | builder.accumulate(status); 124 | return STATE.CONTINUE; 125 | } 126 | 127 | public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { 128 | builder.accumulate(headers); 129 | return STATE.CONTINUE; 130 | } 131 | 132 | public APIResponse onCompleted() throws Exception { 133 | Response response = builder.build(); 134 | return new APIResponse(response.getStatusCode(), response.getResponseBody()); 135 | } 136 | }; 137 | } 138 | 139 | /** 140 | * Get status of the API. 141 | * 142 | * @throws ExecutionException indicates an error in the HTTP backend 143 | * @throws InterruptedException indicates an interruption during the HTTP operation 144 | * @throws IOException indicates an error from the API response 145 | */ 146 | public String getStatus() throws ExecutionException, InterruptedException, IOException { 147 | return (new FutureAPIResponse(client.prepareGet(apiUrl).execute(getHandler()))).get() 148 | .getMessage(); 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/DateTimeAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | import com.google.gson.JsonDeserializationContext; 21 | import com.google.gson.JsonDeserializer; 22 | import com.google.gson.JsonElement; 23 | import com.google.gson.JsonParseException; 24 | import com.google.gson.JsonPrimitive; 25 | import com.google.gson.JsonSerializationContext; 26 | import com.google.gson.JsonSerializer; 27 | import java.lang.reflect.Type; 28 | import org.joda.time.DateTime; 29 | 30 | /** 31 | * DateTimeAdapter turns a String in ISO 8601 format into a DateTime object, and vice versa. 32 | * 33 | * @version 0.8.3 34 | * @since 0.8.0 35 | */ 36 | public class DateTimeAdapter implements JsonSerializer, JsonDeserializer { 37 | 38 | @Override 39 | public JsonElement serialize(DateTime src, Type type, JsonSerializationContext context) { 40 | return new JsonPrimitive(src.toString()); 41 | } 42 | 43 | @Override 44 | public DateTime deserialize(final JsonElement json, final Type type, 45 | final JsonDeserializationContext context) throws JsonParseException { 46 | return new DateTime(json.getAsJsonPrimitive().getAsString()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/EngineClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | import com.google.gson.Gson; 21 | import com.google.gson.GsonBuilder; 22 | import com.google.gson.JsonObject; 23 | import com.ning.http.client.RequestBuilder; 24 | import java.io.IOException; 25 | import java.util.Map; 26 | import java.util.concurrent.ExecutionException; 27 | import org.joda.time.DateTime; 28 | 29 | /** 30 | * EngineClient contains generic methods sendQuery() and sendQueryAsFuture() for sending queries. 31 | * 32 | * @version 0.8.3 33 | * @since 0.8.0 34 | */ 35 | public class EngineClient extends BaseClient { 36 | 37 | private static final String defaultEngineUrl = "http://localhost:8000"; 38 | 39 | /** 40 | * Instantiates a PredictionIO RESTful API Engine Client using default values for API URL and 41 | * default values in BaseClient. 42 | * 43 | *

The default API URL is http://localhost:8000. 44 | */ 45 | public EngineClient() { 46 | super(defaultEngineUrl); 47 | } 48 | 49 | /** 50 | * Instantiates a PredictionIO RESTful API Engine Client using default values in BaseClient. 51 | * 52 | * @param engineUrl the URL of the PredictionIO API 53 | */ 54 | public EngineClient(String engineUrl) { 55 | super(engineUrl); 56 | } 57 | 58 | /** 59 | * Instantiates a PredictionIO RESTful API Engine Client using default values in BaseClient for 60 | * parameters that are not specified. 61 | * 62 | * @param engineUrl the URL of the PredictionIO API 63 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 64 | */ 65 | public EngineClient(String engineUrl, int threadLimit) { 66 | super(engineUrl, threadLimit); 67 | } 68 | 69 | /** 70 | * Instantiates a PredictionIO RESTful API Engine Client using default values in BaseClient for 71 | * parameters that are not specified. 72 | * 73 | * @param engineUrl the URL of the PredictionIO API 74 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 75 | * @param queueSize size of the queue 76 | */ 77 | public EngineClient(String engineUrl, int threadLimit, int queueSize) { 78 | super(engineUrl, threadLimit, queueSize); 79 | } 80 | 81 | /** 82 | * Instantiates a PredictionIO RESTful API Engine Client. 83 | * 84 | * @param engineUrl the URL of the PredictionIO API 85 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 86 | * @param queueSize size of the queue 87 | * @param timeout timeout in seconds for the connections 88 | */ 89 | public EngineClient(String engineUrl, int threadLimit, int queueSize, int timeout) { 90 | super(engineUrl, threadLimit, queueSize, timeout); 91 | } 92 | 93 | /** 94 | * Sends a query asynchronously. 95 | */ 96 | public FutureAPIResponse sendQueryAsFuture(Map query) 97 | throws ExecutionException, InterruptedException, IOException { 98 | RequestBuilder builder = new RequestBuilder("POST"); 99 | builder.setUrl(apiUrl + "/queries.json"); 100 | 101 | // handle DateTime separately 102 | GsonBuilder gsonBuilder = new GsonBuilder(); 103 | gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeAdapter()); 104 | Gson gson = gsonBuilder.create(); 105 | 106 | String requestJsonString = gson.toJson(query); 107 | builder.setBody(requestJsonString); 108 | builder.setHeader("Content-Type", "application/json"); 109 | builder.setHeader("Content-Length", "" + requestJsonString.length()); 110 | return new FutureAPIResponse(client.executeRequest(builder.build(), getHandler())); 111 | } 112 | 113 | /** 114 | * Sends a query synchronously. 115 | */ 116 | public JsonObject sendQuery(Map query) 117 | throws ExecutionException, InterruptedException, IOException { 118 | return sendQuery(sendQueryAsFuture(query)); 119 | } 120 | 121 | /** 122 | * Gets query result from a previously sent asynchronous request. 123 | */ 124 | public JsonObject sendQuery(FutureAPIResponse response) 125 | throws ExecutionException, InterruptedException, IOException { 126 | int status = response.get().getStatus(); 127 | String message = response.get().getMessage(); 128 | 129 | if (status != HTTP_OK) { 130 | throw new IOException(status + " " + message); 131 | } 132 | return ((JsonObject) parser.parse(message)); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/Event.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | import com.google.common.collect.Maps; 21 | import com.google.gson.Gson; 22 | import com.google.gson.GsonBuilder; 23 | import java.util.Map; 24 | import org.joda.time.DateTime; 25 | 26 | /** 27 | * Event class for PredictionIO Event objects. 28 | * 29 | * @version 0.8.3 30 | * @since 0.8.0 31 | */ 32 | 33 | public class Event { 34 | 35 | // mandatory fields 36 | private String event; 37 | private String entityType; 38 | private String entityId; 39 | 40 | // optional fields 41 | private String targetEntityType; 42 | private String targetEntityId; 43 | private Map properties = Maps.newHashMap(); 44 | private DateTime eventTime; 45 | 46 | /** 47 | * Instantiate an event object. 48 | */ 49 | public Event() { 50 | } 51 | 52 | /** 53 | * Returns the name of the event. 54 | */ 55 | public String getEvent() { 56 | return event; 57 | } 58 | 59 | /** 60 | * Returns the entity type. entityType-entityId forms the unique identifier of the entity. 61 | */ 62 | public String getEntityType() { 63 | return entityType; 64 | } 65 | 66 | /** 67 | * Returns the entity id. entityType-entityId forms the unique identifier of the entity. 68 | */ 69 | public String getEntityId() { 70 | return entityId; 71 | } 72 | 73 | /** 74 | * Returns the target entity type, or null if the field is not set. 75 | */ 76 | public String getTargetEntityType() { 77 | return targetEntityType; 78 | } 79 | 80 | /** 81 | * Returns the target entity id, or null if the field is not set. 82 | */ 83 | public String getTargetEntityId() { 84 | return targetEntityId; 85 | } 86 | 87 | /** 88 | * Returns the set of properties as a map. 89 | */ 90 | public Map getProperties() { 91 | return properties; 92 | } 93 | 94 | /** 95 | * Returns the event time, or null if the field is not set. 96 | */ 97 | public DateTime getEventTime() { 98 | return eventTime; 99 | } 100 | 101 | // builder methods for convenience 102 | 103 | /** 104 | * Sets the name of the event. 105 | */ 106 | public Event event(String event) { 107 | this.event = event; 108 | return this; 109 | } 110 | 111 | /** 112 | * Sets the entity type. entityType-entityId forms the unique identifier of the entity. 113 | */ 114 | public Event entityType(String entityType) { 115 | this.entityType = entityType; 116 | return this; 117 | } 118 | 119 | /** 120 | * Sets the entity id. entityType-entityId forms the unique identifier of the entity. 121 | */ 122 | public Event entityId(String entityId) { 123 | this.entityId = entityId; 124 | return this; 125 | } 126 | 127 | public Event targetEntityType(String targetEntityType) { 128 | this.targetEntityType = targetEntityType; 129 | return this; 130 | } 131 | 132 | public Event targetEntityId(String targetEntityId) { 133 | this.targetEntityId = targetEntityId; 134 | return this; 135 | } 136 | 137 | public Event property(String key, Object value) { 138 | this.properties.put(key, value); 139 | return this; 140 | } 141 | 142 | public Event properties(Map properties) { 143 | this.properties.putAll(properties); 144 | return this; 145 | } 146 | 147 | public Event eventTime(DateTime eventTime) { 148 | this.eventTime = eventTime; 149 | return this; 150 | } 151 | 152 | // toJsonString and toString methods 153 | 154 | public String toJsonString() { 155 | return toString(); 156 | } 157 | 158 | @Override 159 | public String toString() { 160 | // handle DateTime separately 161 | GsonBuilder gsonBuilder = new GsonBuilder(); 162 | gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeAdapter()); 163 | Gson gson = gsonBuilder.create(); 164 | return gson.toJson(this); // works when there are no generic types 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/EventClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | import com.google.common.collect.Maps; 21 | import com.google.gson.Gson; 22 | import com.google.gson.GsonBuilder; 23 | import com.google.gson.JsonArray; 24 | import com.google.gson.JsonElement; 25 | import com.google.gson.JsonObject; 26 | import com.ning.http.client.Request; 27 | import com.ning.http.client.RequestBuilder; 28 | import java.io.IOException; 29 | import java.util.LinkedList; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.concurrent.ExecutionException; 33 | import org.joda.time.DateTime; 34 | 35 | /** 36 | * EventClient contains the generic methods createEvent() and getEvent() for importing and accessing 37 | * events, as well as helper methods such as setUser(), unsetItem() and userActionItem() for 38 | * convenience. Methods with an "AsFuture" suffix are asynchronous. 39 | * 40 | *

Multiple simultaneous asynchronous requests is made possible by the high performance backend 41 | * provided by the Async Http 42 | * Client. 43 | * 44 | * @version 0.8.3 45 | * @since 0.8.0 46 | */ 47 | public class EventClient extends BaseClient { 48 | 49 | private static final String defaultEventUrl = "http://localhost:7070"; 50 | 51 | private final String accessKey; 52 | 53 | /** 54 | * Instantiate a PredictionIO RESTful API Event Client using default values for API URL and 55 | * default values in {@link BaseClient}. 56 | * 57 | *

The default API URL is http://localhost:7070. 58 | * 59 | * @param accessKey the access key that this client will use to communicate with the API 60 | */ 61 | public EventClient(String accessKey) { 62 | this(accessKey, defaultEventUrl); 63 | } 64 | 65 | /** 66 | * Instantiate a PredictionIO RESTful API Event Client using default values in {@link 67 | * BaseClient}. 68 | * 69 | * @param accessKey the access key that this client will use to communicate with the API 70 | * @param eventUrl the URL of the PredictionIO API 71 | */ 72 | public EventClient(String accessKey, String eventUrl) { 73 | super(eventUrl); 74 | this.accessKey = accessKey; 75 | } 76 | 77 | /** 78 | * Instantiate a PredictionIO RESTful API Event Client using default values in {@link BaseClient} 79 | * for parameters that are not specified. 80 | * 81 | * @param accessKey the access key that this client will use to communicate with the API 82 | * @param eventUrl the URL of the PredictionIO API 83 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 84 | */ 85 | public EventClient(String accessKey, String eventUrl, int threadLimit) { 86 | super(eventUrl, threadLimit); 87 | this.accessKey = accessKey; 88 | } 89 | 90 | /** 91 | * Instantiate a PredictionIO RESTful API Event Client using default values in {@link BaseClient} 92 | * for parameters that are not specified. 93 | * 94 | * @param accessKey the access key that this client will use to communicate with the API 95 | * @param eventUrl the URL of the PredictionIO API 96 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 97 | * @param queueSize size of the queue 98 | */ 99 | public EventClient(String accessKey, String eventUrl, int threadLimit, int queueSize) { 100 | super(eventUrl, threadLimit, queueSize); 101 | this.accessKey = accessKey; 102 | } 103 | 104 | /** 105 | * Instantiate a PredictionIO RESTful API Event Client. 106 | * 107 | * @param accessKey the access key that this client will use to communicate with the API 108 | * @param eventUrl the URL of the PredictionIO API 109 | * @param threadLimit maximum number of simultaneous threads (connections) to the API 110 | * @param queueSize size of the queue 111 | * @param timeout timeout in seconds for the connections 112 | */ 113 | public EventClient(String accessKey, String eventUrl, int threadLimit, int queueSize, 114 | int timeout) { 115 | super(eventUrl, threadLimit, queueSize, timeout); 116 | this.accessKey = accessKey; 117 | } 118 | 119 | /** 120 | * Sends an asynchronous create event request to the API. 121 | * 122 | * @param event an instance of {@link Event} that will be turned into a request 123 | */ 124 | public FutureAPIResponse createEventAsFuture(Event event) throws IOException { 125 | RequestBuilder builder = new RequestBuilder("POST"); 126 | builder.setUrl(apiUrl + "/events.json?accessKey=" + accessKey); 127 | String requestJsonString = event.toJsonString(); 128 | builder.setBody(requestJsonString); 129 | builder.setHeader("Content-Type", "application/json"); 130 | builder.setHeader("Content-Length", "" + requestJsonString.length()); 131 | return new FutureAPIResponse(client.executeRequest(builder.build(), getHandler())); 132 | } 133 | 134 | /** 135 | * Sends a synchronous create event request to the API. 136 | * 137 | * @param event an instance of {@link Event} that will be turned into a request 138 | * @return event ID from the server 139 | * @throws ExecutionException indicates an error in the HTTP backend 140 | * @throws InterruptedException indicates an interruption during the HTTP operation 141 | * @throws IOException indicates an error from the API response 142 | */ 143 | public String createEvent(Event event) 144 | throws ExecutionException, InterruptedException, IOException { 145 | return createEvent(createEventAsFuture(event)); 146 | } 147 | 148 | /** 149 | * Synchronize a previously sent asynchronous create event request. 150 | * 151 | * @param response an instance of {@link FutureAPIResponse} returned from {@link 152 | * #createEventAsFuture} 153 | * @return event ID from the server 154 | * @throws ExecutionException indicates an error in the HTTP backend 155 | * @throws InterruptedException indicates an interruption during the HTTP operation 156 | * @throws IOException indicates an error from the API response 157 | */ 158 | public String createEvent(FutureAPIResponse response) 159 | throws ExecutionException, InterruptedException, IOException { 160 | int status = response.get().getStatus(); 161 | String message = response.get().getMessage(); 162 | 163 | if (status != HTTP_CREATED) { 164 | throw new IOException(status + " " + message); 165 | } 166 | return ((JsonObject) parser.parse(message)).get("eventId").getAsString(); 167 | } 168 | 169 | /** 170 | * Sends an asynchronous create events (batch) request to the API. 171 | * 172 | * @param events a List of {@link Event} that will be turned into a request 173 | */ 174 | public FutureAPIResponse createEventsAsFuture(List events) throws IOException { 175 | RequestBuilder builder = new RequestBuilder("POST"); 176 | builder.setUrl(apiUrl + "/batch/events.json?accessKey=" + accessKey); 177 | 178 | GsonBuilder gsonBuilder = new GsonBuilder(); 179 | gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeAdapter()); 180 | Gson gson = gsonBuilder.create(); 181 | String requestJsonString = gson.toJson(events); 182 | 183 | builder.setBody(requestJsonString); 184 | builder.setHeader("Content-Type", "application/json"); 185 | builder.setHeader("Content-Length", "" + requestJsonString.length()); 186 | return new FutureAPIResponse(client.executeRequest(builder.build(), getHandler())); 187 | } 188 | 189 | /** 190 | * Sends a synchronous create events (batch) request to the API. 191 | * 192 | * @param events a List of {@link Event} that will be turned into a request 193 | * @return event ID from the server 194 | * @throws ExecutionException indicates an error in the HTTP backend 195 | * @throws InterruptedException indicates an interruption during the HTTP operation 196 | * @throws IOException indicates an error from the API response 197 | */ 198 | public List createEvents(List events) 199 | throws ExecutionException, InterruptedException, IOException { 200 | return createEvents(createEventsAsFuture(events)); 201 | } 202 | 203 | /** 204 | * Synchronize a previously sent asynchronous create events (batch) request. 205 | * 206 | * @param response an instance of {@link FutureAPIResponse} returned from {@link 207 | * #createEventAsFuture} 208 | * @return List of event IDs from the server 209 | * @throws ExecutionException indicates an error in the HTTP backend 210 | * @throws InterruptedException indicates an interruption during the HTTP operation 211 | * @throws IOException indicates an error from the API response 212 | */ 213 | public List createEvents(FutureAPIResponse response) 214 | throws ExecutionException, InterruptedException, IOException { 215 | int status = response.get().getStatus(); 216 | String message = response.get().getMessage(); 217 | 218 | if (status != HTTP_OK) { 219 | throw new IOException(status + " " + message); 220 | } 221 | List eventIds = new LinkedList(); 222 | 223 | for (JsonElement elem : (JsonArray) parser.parse(message)) { 224 | eventIds.add(((JsonObject) elem).get("eventId").getAsString()); 225 | } 226 | return eventIds; 227 | } 228 | 229 | /** 230 | * Sends an asynchronous get event request to the API. 231 | * 232 | * @param eid ID of the event to get 233 | */ 234 | public FutureAPIResponse getEventAsFuture(String eid) throws IOException { 235 | Request request = (new RequestBuilder("GET")) 236 | .setUrl(apiUrl + "/events/" + eid + ".json?accessKey=" + accessKey) 237 | .build(); 238 | return new FutureAPIResponse(client.executeRequest(request, getHandler())); 239 | } 240 | 241 | /** 242 | * Sends a synchronous get event request to the API. 243 | * 244 | * @param eid ID of the event to get 245 | * @throws ExecutionException indicates an error in the HTTP backend 246 | * @throws InterruptedException indicates an interruption during the HTTP operation 247 | * @throws IOException indicates an error from the API response 248 | */ 249 | public Event getEvent(String eid) 250 | throws ExecutionException, InterruptedException, IOException { 251 | return getEvent(getEventAsFuture(eid)); 252 | } 253 | 254 | /** 255 | * Synchronize a previously sent asynchronous get item request. 256 | * 257 | * @param response an instance of {@link FutureAPIResponse} returned from {@link 258 | * #getEventAsFuture} 259 | * @throws ExecutionException indicates an error in the HTTP backend 260 | * @throws InterruptedException indicates an interruption during the HTTP operation 261 | * @throws IOException indicates an error from the API response 262 | */ 263 | public Event getEvent(FutureAPIResponse response) 264 | throws ExecutionException, InterruptedException, IOException { 265 | int status = response.get().getStatus(); 266 | String message = response.get().getMessage(); 267 | 268 | if (status == HTTP_OK) { 269 | // handle DateTime separately 270 | GsonBuilder gsonBuilder = new GsonBuilder(); 271 | gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeAdapter()); 272 | Gson gson = gsonBuilder.create(); 273 | 274 | return gson.fromJson(message, Event.class); 275 | } else { 276 | throw new IOException(message); 277 | } 278 | } 279 | 280 | //////////////////////////////////// 281 | // 282 | // helper methods for convenience 283 | // 284 | //////////////////////////////////// 285 | 286 | /** 287 | * Sends a set user properties request. Implicitly creates the user if it's not already there. 288 | * Properties could be empty. 289 | * 290 | * @param uid ID of the user 291 | * @param properties a map of all the properties to be associated with the user, could be empty 292 | * @param eventTime timestamp of the event 293 | * @return ID of this event 294 | */ 295 | public FutureAPIResponse setUserAsFuture(String uid, Map properties, 296 | DateTime eventTime) throws IOException { 297 | return createEventAsFuture(new Event() 298 | .event("$set") 299 | .entityType("user") 300 | .entityId(uid) 301 | .eventTime(eventTime) 302 | .properties(properties)); 303 | } 304 | 305 | /** 306 | * Sends a set user properties request. Same as {@link #setUserAsFuture(String, Map, DateTime) 307 | * setUserAsFuture(String, Map<String, Object>, DateTime)} except event time is not 308 | * specified and recorded as the time when the function is called. 309 | */ 310 | public FutureAPIResponse setUserAsFuture(String uid, Map properties) 311 | throws IOException { 312 | return setUserAsFuture(uid, properties, new DateTime()); 313 | } 314 | 315 | /** 316 | * Sets properties of a user. Implicitly creates the user if it's not already there. Properties 317 | * could be empty. 318 | * 319 | * @param uid ID of the user 320 | * @param properties a map of all the properties to be associated with the user, could be empty 321 | * @param eventTime timestamp of the event 322 | * @return ID of this event 323 | */ 324 | public String setUser(String uid, Map properties, DateTime eventTime) 325 | throws ExecutionException, InterruptedException, IOException { 326 | return createEvent(setUserAsFuture(uid, properties, eventTime)); 327 | } 328 | 329 | /** 330 | * Sets properties of a user. Same as {@link #setUser(String, Map, DateTime)} except event time is 331 | * not specified and recorded as the time when the function is called. 332 | */ 333 | public String setUser(String uid, Map properties) 334 | throws ExecutionException, InterruptedException, IOException { 335 | return setUser(uid, properties, new DateTime()); 336 | } 337 | 338 | /** 339 | * Sends an unset user properties request. The list must not be empty. 340 | * 341 | * @param uid ID of the user 342 | * @param properties a list of all the properties to unset 343 | * @param eventTime timestamp of the event 344 | */ 345 | public FutureAPIResponse unsetUserAsFuture(String uid, List properties, 346 | DateTime eventTime) throws IOException { 347 | if (properties.isEmpty()) { 348 | throw new IllegalStateException("property list cannot be empty"); 349 | } 350 | // converts the list into a map (to empty string) before creating the event object 351 | Map propertiesMap = Maps.newHashMap(); 352 | for (String property : properties) { 353 | propertiesMap.put(property, ""); 354 | } 355 | return createEventAsFuture(new Event() 356 | .event("$unset") 357 | .entityType("user") 358 | .entityId(uid) 359 | .eventTime(eventTime) 360 | .properties(propertiesMap)); 361 | } 362 | 363 | /** 364 | * Sends an unset user properties request. Same as {@link #unsetUserAsFuture(String, List, 365 | * DateTime) unsetUserAsFuture(String, List<String>, DateTime)} except event time is not 366 | * specified and recorded as the time when the function is called. 367 | */ 368 | public FutureAPIResponse unsetUserAsFuture(String uid, List properties) 369 | throws IOException { 370 | return unsetUserAsFuture(uid, properties, new DateTime()); 371 | } 372 | 373 | /** 374 | * Unsets properties of a user. The list must not be empty. 375 | * 376 | * @param uid ID of the user 377 | * @param properties a list of all the properties to unset 378 | * @param eventTime timestamp of the event 379 | * @return ID of this event 380 | */ 381 | public String unsetUser(String uid, List properties, DateTime eventTime) 382 | throws ExecutionException, InterruptedException, IOException { 383 | return createEvent(unsetUserAsFuture(uid, properties, eventTime)); 384 | } 385 | 386 | /** 387 | * Unsets properties of a user. Same as {@link #unsetUser(String, List, DateTime) 388 | * unsetUser(String, List<String>, DateTime)} except event time is not specified and 389 | * recorded as the time when the function is called. 390 | */ 391 | public String unsetUser(String uid, List properties) 392 | throws ExecutionException, InterruptedException, IOException { 393 | return unsetUser(uid, properties, new DateTime()); 394 | } 395 | 396 | /** 397 | * Sends a delete user request. 398 | * 399 | * @param uid ID of the user 400 | * @param eventTime timestamp of the event 401 | */ 402 | public FutureAPIResponse deleteUserAsFuture(String uid, DateTime eventTime) 403 | throws IOException { 404 | return createEventAsFuture(new Event() 405 | .event("$delete") 406 | .entityType("user") 407 | .entityId(uid) 408 | .eventTime(eventTime)); 409 | } 410 | 411 | /** 412 | * Sends a delete user request. Event time is recorded as the time when the function is called. 413 | * 414 | * @param uid ID of the user 415 | */ 416 | public FutureAPIResponse deleteUserAsFuture(String uid) 417 | throws IOException { 418 | return deleteUserAsFuture(uid, new DateTime()); 419 | } 420 | 421 | /** 422 | * Deletes a user. 423 | * 424 | * @param uid ID of the user 425 | * @param eventTime timestamp of the event 426 | * @return ID of this event 427 | */ 428 | public String deleteUser(String uid, DateTime eventTime) 429 | throws ExecutionException, InterruptedException, IOException { 430 | return createEvent(deleteUserAsFuture(uid, eventTime)); 431 | } 432 | 433 | /** 434 | * Deletes a user. Event time is recorded as the time when the function is called. 435 | * 436 | * @param uid ID of the user 437 | * @return ID of this event 438 | */ 439 | public String deleteUser(String uid) 440 | throws ExecutionException, InterruptedException, IOException { 441 | return deleteUser(uid, new DateTime()); 442 | } 443 | 444 | 445 | /** 446 | * Sends a set item properties request. Implicitly creates the item if it's not already there. 447 | * Properties could be empty. 448 | * 449 | * @param iid ID of the item 450 | * @param properties a map of all the properties to be associated with the item, could be empty 451 | * @param eventTime timestamp of the event 452 | * @return ID of this event 453 | */ 454 | public FutureAPIResponse setItemAsFuture(String iid, Map properties, 455 | DateTime eventTime) throws IOException { 456 | return createEventAsFuture(new Event() 457 | .event("$set") 458 | .entityType("item") 459 | .entityId(iid) 460 | .eventTime(eventTime) 461 | .properties(properties)); 462 | } 463 | 464 | /** 465 | * Sends a set item properties request. Same as {@link #setItemAsFuture(String, Map, DateTime) 466 | * setItemAsFuture(String, Map<String, Object>, DateTime)} except event time is not 467 | * specified and recorded as the time when the function is called. 468 | */ 469 | public FutureAPIResponse setItemAsFuture(String iid, Map properties) 470 | throws IOException { 471 | return setItemAsFuture(iid, properties, new DateTime()); 472 | } 473 | 474 | /** 475 | * Sets properties of a item. Implicitly creates the item if it's not already there. Properties 476 | * could be empty. 477 | * 478 | * @param iid ID of the item 479 | * @param properties a map of all the properties to be associated with the item, could be empty 480 | * @param eventTime timestamp of the event 481 | * @return ID of this event 482 | */ 483 | public String setItem(String iid, Map properties, DateTime eventTime) 484 | throws ExecutionException, InterruptedException, IOException { 485 | return createEvent(setItemAsFuture(iid, properties, eventTime)); 486 | } 487 | 488 | /** 489 | * Sets properties of a item. Same as {@link #setItem(String, Map, DateTime) setItem(String, 490 | * Map<String, Object>, DateTime)} except event time is not specified and recorded as the 491 | * time when the function is called. 492 | */ 493 | public String setItem(String iid, Map properties) 494 | throws ExecutionException, InterruptedException, IOException { 495 | return setItem(iid, properties, new DateTime()); 496 | } 497 | 498 | /** 499 | * Sends an unset item properties request. The list must not be empty. 500 | * 501 | * @param iid ID of the item 502 | * @param properties a list of all the properties to unset 503 | * @param eventTime timestamp of the event 504 | */ 505 | public FutureAPIResponse unsetItemAsFuture(String iid, List properties, 506 | DateTime eventTime) throws IOException { 507 | if (properties.isEmpty()) { 508 | throw new IllegalStateException("property list cannot be empty"); 509 | } 510 | // converts the list into a map (to empty string) before creating the event object 511 | Map propertiesMap = Maps.newHashMap(); 512 | for (String property : properties) { 513 | propertiesMap.put(property, ""); 514 | } 515 | return createEventAsFuture(new Event() 516 | .event("$unset") 517 | .entityType("item") 518 | .entityId(iid) 519 | .eventTime(eventTime) 520 | .properties(propertiesMap)); 521 | } 522 | 523 | /** 524 | * Sends an unset item properties request. Same as {@link #unsetItemAsFuture(String, List, 525 | * DateTime) unsetItemAsFuture(String, List<String>, DateTime)} except event time is not 526 | * specified and recorded as the time when the function is called. 527 | */ 528 | public FutureAPIResponse unsetItemAsFuture(String iid, List properties) 529 | throws IOException { 530 | return unsetItemAsFuture(iid, properties, new DateTime()); 531 | } 532 | 533 | /** 534 | * Unsets properties of a item. The list must not be empty. 535 | * 536 | * @param iid ID of the item 537 | * @param properties a list of all the properties to unset 538 | * @param eventTime timestamp of the event 539 | * @return ID of this event 540 | */ 541 | public String unsetItem(String iid, List properties, DateTime eventTime) 542 | throws ExecutionException, InterruptedException, IOException { 543 | return createEvent(unsetItemAsFuture(iid, properties, eventTime)); 544 | } 545 | 546 | /** 547 | * Unsets properties of a item. Same as {@link #unsetItem(String, List, DateTime) 548 | * unsetItem(String, List<String>, DateTime)} except event time is not specified and 549 | * recorded as the time when the function is called. 550 | */ 551 | public String unsetItem(String iid, List properties) 552 | throws ExecutionException, InterruptedException, IOException { 553 | return unsetItem(iid, properties, new DateTime()); 554 | } 555 | 556 | /** 557 | * Sends a delete item request. 558 | * 559 | * @param iid ID of the item 560 | * @param eventTime timestamp of the event 561 | */ 562 | public FutureAPIResponse deleteItemAsFuture(String iid, DateTime eventTime) 563 | throws IOException { 564 | return createEventAsFuture(new Event() 565 | .event("$delete") 566 | .entityType("item") 567 | .entityId(iid) 568 | .eventTime(eventTime)); 569 | } 570 | 571 | /** 572 | * Sends a delete item request. Event time is recorded as the time when the function is called. 573 | * 574 | * @param iid ID of the item 575 | */ 576 | public FutureAPIResponse deleteItemAsFuture(String iid) 577 | throws IOException { 578 | return deleteItemAsFuture(iid, new DateTime()); 579 | } 580 | 581 | /** 582 | * Deletes a item. 583 | * 584 | * @param iid ID of the item 585 | * @param eventTime timestamp of the event 586 | * @return ID of this event 587 | */ 588 | public String deleteItem(String iid, DateTime eventTime) 589 | throws ExecutionException, InterruptedException, IOException { 590 | return createEvent(deleteItemAsFuture(iid, eventTime)); 591 | } 592 | 593 | /** 594 | * Deletes a item. Event time is recorded as the time when the function is called. 595 | * 596 | * @param iid ID of the item 597 | * @return ID of this event 598 | */ 599 | public String deleteItem(String iid) 600 | throws ExecutionException, InterruptedException, IOException { 601 | return deleteItem(iid, new DateTime()); 602 | } 603 | 604 | /** 605 | * Sends a user-action-on-item request. 606 | * 607 | * @param action name of the action performed 608 | * @param uid ID of the user 609 | * @param iid ID of the item 610 | * @param properties a map of properties associated with this action 611 | * @param eventTime timestamp of the event 612 | */ 613 | public FutureAPIResponse userActionItemAsFuture(String action, String uid, String iid, 614 | Map properties, DateTime eventTime) throws IOException { 615 | return createEventAsFuture(new Event() 616 | .event(action) 617 | .entityType("user") 618 | .entityId(uid) 619 | .targetEntityType("item") 620 | .targetEntityId(iid) 621 | .properties(properties) 622 | .eventTime(eventTime)); 623 | } 624 | 625 | /** 626 | * Sends a user-action-on-item request. Similar to {@link #userActionItemAsFuture(String, String, 627 | * String, Map, DateTime) #userActionItemAsFuture(String, String, String, Map<String, 628 | * Object\gt;, DateTime)} except event time is not specified and recorded as the time when the 629 | * function is called. 630 | */ 631 | public FutureAPIResponse userActionItemAsFuture(String action, String uid, String iid, 632 | Map properties) throws IOException { 633 | return userActionItemAsFuture(action, uid, iid, properties, new DateTime()); 634 | } 635 | 636 | /** 637 | * Records a user-action-on-item event. 638 | * 639 | * @param action name of the action performed 640 | * @param uid ID of the user 641 | * @param iid ID of the item 642 | * @param properties a map of properties associated with this action 643 | * @param eventTime timestamp of the event 644 | * @return ID of this event 645 | */ 646 | public String userActionItem(String action, String uid, String iid, 647 | Map properties, DateTime eventTime) 648 | throws ExecutionException, InterruptedException, IOException { 649 | return createEvent(userActionItemAsFuture(action, uid, iid, properties, eventTime)); 650 | } 651 | 652 | /** 653 | * Records a user-action-on-item event. Similar to {@link #userActionItem(String, String, String, 654 | * Map, DateTime) userActionItem(String, String, String, Map<String, Object>, DateTime)} 655 | * except event time is not specified and recorded as the time when the function is called. 656 | */ 657 | public String userActionItem(String action, String uid, String iid, 658 | Map properties) 659 | throws ExecutionException, InterruptedException, IOException { 660 | return userActionItem(action, uid, iid, properties, new DateTime()); 661 | } 662 | 663 | } 664 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/FileExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | 21 | import java.io.FileNotFoundException; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.util.Map; 25 | import org.joda.time.DateTime; 26 | 27 | public class FileExporter { 28 | 29 | private FileOutputStream out; 30 | 31 | public FileExporter(String pathname) throws FileNotFoundException { 32 | out = new FileOutputStream(pathname); 33 | } 34 | 35 | /** 36 | * Create and write a json-encoded event to the underlying file. 37 | * 38 | * @param eventName Name of the event. 39 | * @param entityType The entity type. 40 | * @param entityId The entity ID. 41 | * @param targetEntityType The target entity type (optional). 42 | * @param targetEntityId The target entity ID (optional). 43 | * @param properties Properties (optional). 44 | * @param eventTime The time of the event (optional). 45 | */ 46 | public void createEvent(String eventName, String entityType, String entityId, 47 | String targetEntityType, String targetEntityId, Map properties, 48 | DateTime eventTime) throws IOException { 49 | 50 | if (eventTime == null) { 51 | eventTime = new DateTime(); 52 | } 53 | 54 | Event event = new Event() 55 | .event(eventName) 56 | .entityType(entityType) 57 | .entityId(entityId) 58 | .eventTime(eventTime); 59 | 60 | if (targetEntityType != null) { 61 | event.targetEntityType(targetEntityType); 62 | } 63 | 64 | if (targetEntityId != null) { 65 | event.targetEntityId(targetEntityId); 66 | } 67 | 68 | if (properties != null) { 69 | event.properties(properties); 70 | } 71 | 72 | out.write(event.toJsonString().getBytes("UTF8")); 73 | out.write('\n'); 74 | } 75 | 76 | public void close() throws IOException { 77 | out.close(); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/FutureAPIResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | import com.google.common.util.concurrent.ListenableFuture; 21 | import com.ning.http.client.extra.ListenableFutureAdapter; 22 | import java.util.concurrent.ExecutionException; 23 | import java.util.concurrent.Executor; 24 | import java.util.concurrent.TimeUnit; 25 | import java.util.concurrent.TimeoutException; 26 | 27 | /** 28 | * APIResponse as a listenable future. 29 | * 30 | * @version 0.8.3 31 | * @since 0.2 32 | */ 33 | 34 | public class FutureAPIResponse implements ListenableFuture { 35 | 36 | private ListenableFuture apiResponse; 37 | 38 | public FutureAPIResponse(com.ning.http.client.ListenableFuture apiResponse) { 39 | this.apiResponse = ListenableFutureAdapter.asGuavaFuture(apiResponse); 40 | } 41 | 42 | // implements ListenableFuture 43 | 44 | public void addListener(Runnable listener, Executor executor) { 45 | this.apiResponse.addListener(listener, executor); 46 | } 47 | 48 | // implements Future 49 | 50 | public boolean cancel(boolean mayInterruptIfRunning) { 51 | return this.apiResponse.cancel(mayInterruptIfRunning); 52 | } 53 | 54 | public APIResponse get() throws ExecutionException, InterruptedException { 55 | return this.apiResponse.get(); 56 | } 57 | 58 | public APIResponse get(long timeout, TimeUnit unit) 59 | throws ExecutionException, InterruptedException, TimeoutException { 60 | return this.apiResponse.get(timeout, unit); 61 | } 62 | 63 | public boolean isCancelled() { 64 | return this.apiResponse.isCancelled(); 65 | } 66 | 67 | public boolean isDone() { 68 | return this.apiResponse.isDone(); 69 | } 70 | 71 | public ListenableFuture getAPIResponse() { 72 | // get the underlying APIResponse 73 | return this.apiResponse; 74 | } 75 | 76 | public int getStatus() { 77 | try { 78 | return this.apiResponse.get().getStatus(); 79 | } catch (InterruptedException | ExecutionException e) { 80 | return 0; 81 | } 82 | } 83 | 84 | public String getMessage() { 85 | try { 86 | return this.apiResponse.get().getMessage(); 87 | } catch (InterruptedException | ExecutionException e) { 88 | return e.getMessage(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /client/src/main/java/org/apache/predictionio/sdk/java/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /** 19 | * This package contains classes that provide convenient access of Apache PredictionIO RESTful API. 20 | * 21 | * To create an app and perform predictions, please download Apache PredictionIO from 22 | * http://predictionio.apache.org. 23 | * 24 | * Most functionality is provided by the {@link org.apache.predictionio.sdk.java.EventClient} and 25 | * {@link org.apache.predictionio.sdk.java.EngineClient} class. 26 | */ 27 | package org.apache.predictionio.sdk.java; 28 | -------------------------------------------------------------------------------- /client/src/test/java/org/apache/predictionio/sdk/java/FileExporterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.sdk.java; 19 | 20 | import static org.junit.Assert.assertEquals; 21 | import static org.junit.Assert.assertNull; 22 | import static org.junit.Assert.assertTrue; 23 | 24 | import com.google.gson.Gson; 25 | import com.google.gson.GsonBuilder; 26 | import java.io.BufferedReader; 27 | import java.io.File; 28 | import java.io.FileReader; 29 | import java.io.IOException; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | import org.joda.time.DateTime; 33 | import org.junit.Rule; 34 | import org.junit.Test; 35 | import org.junit.rules.TemporaryFolder; 36 | 37 | public class FileExporterTest { 38 | 39 | @Rule 40 | public TemporaryFolder folder = new TemporaryFolder(); 41 | 42 | @Test 43 | public void testIt() throws IOException { 44 | 45 | String pathname = folder.getRoot().getCanonicalPath() + "/testIt.out"; 46 | 47 | FileExporter exporter = new FileExporter(pathname); 48 | 49 | Map properties = new HashMap<>(); 50 | properties.put("birthday", new DateTime("1758-05-06T00:00:00+00:00")); 51 | 52 | DateTime then = new DateTime("1794-07-27T00:00:00+00:00"); 53 | 54 | exporter.createEvent("event-1", "entity-type-1", "entity-id-1", 55 | null, null, null, null); 56 | 57 | exporter.createEvent("event-2", "entity-type-2", "entity-id-2", 58 | "target-entity-type-2", null, null, null); 59 | 60 | exporter.createEvent("event-3", "entity-type-3", "entity-id-3", 61 | null, "target-entity-id-3", null, null); 62 | 63 | exporter.createEvent("event-4", "entity-type-4", "entity-id-4", 64 | null, null, properties, then); 65 | 66 | exporter.createEvent("event-5", "entity-type-5", "entity-id-5", 67 | "target-entity-type-5", "target-entity-id-5", properties, then); 68 | 69 | exporter.close(); 70 | 71 | File out = new File(pathname); 72 | assertTrue(pathname + " exists", out.exists()); 73 | 74 | BufferedReader reader = new BufferedReader(new FileReader(pathname)); 75 | 76 | GsonBuilder gsonBuilder = new GsonBuilder(); 77 | gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeAdapter()); 78 | Gson gson = gsonBuilder.create(); 79 | 80 | String json1 = reader.readLine(); 81 | Event event1 = gson.fromJson(json1, Event.class); 82 | assertEquals("event-1", event1.getEvent()); 83 | assertEquals("entity-type-1", event1.getEntityType()); 84 | assertEquals("entity-id-1", event1.getEntityId()); 85 | assertNull(event1.getTargetEntityType()); 86 | assertNull(event1.getTargetEntityId()); 87 | assertTrue(event1.getProperties().isEmpty()); 88 | assertEquals(new DateTime().getMillis(), event1.getEventTime().getMillis(), 1000); 89 | 90 | String json2 = reader.readLine(); 91 | Event event2 = gson.fromJson(json2, Event.class); 92 | assertEquals("event-2", event2.getEvent()); 93 | assertEquals("entity-type-2", event2.getEntityType()); 94 | assertEquals("entity-id-2", event2.getEntityId()); 95 | assertEquals("target-entity-type-2", event2.getTargetEntityType()); 96 | assertNull(event2.getTargetEntityId()); 97 | assertTrue(event2.getProperties().isEmpty()); 98 | assertEquals(new DateTime().getMillis(), event2.getEventTime().getMillis(), 1000); 99 | 100 | String json3 = reader.readLine(); 101 | Event event3 = gson.fromJson(json3, Event.class); 102 | assertEquals("event-3", event3.getEvent()); 103 | assertEquals("entity-type-3", event3.getEntityType()); 104 | assertEquals("entity-id-3", event3.getEntityId()); 105 | assertNull(event3.getTargetEntityType()); 106 | assertEquals("target-entity-id-3", event3.getTargetEntityId()); 107 | assertTrue(event3.getProperties().isEmpty()); 108 | assertEquals(new DateTime().getMillis(), event3.getEventTime().getMillis(), 1000); 109 | 110 | String json4 = reader.readLine(); 111 | Event event4 = gson.fromJson(json4, Event.class); 112 | assertEquals("event-4", event4.getEvent()); 113 | assertEquals("entity-type-4", event4.getEntityType()); 114 | assertEquals("entity-id-4", event4.getEntityId()); 115 | assertNull(event4.getTargetEntityType()); 116 | assertNull(event4.getTargetEntityId()); 117 | assertEquals(1, event4.getProperties().size()); 118 | assertEquals(properties.get("birthday"), new DateTime(event4.getProperties().get("birthday"))); 119 | assertEquals(then.getMillis(), event4.getEventTime().getMillis()); 120 | 121 | String json5 = reader.readLine(); 122 | Event event5 = gson.fromJson(json5, Event.class); 123 | assertEquals("event-5", event5.getEvent()); 124 | assertEquals("entity-type-5", event5.getEntityType()); 125 | assertEquals("entity-id-5", event5.getEntityId()); 126 | assertEquals("target-entity-type-5", event5.getTargetEntityType()); 127 | assertEquals("target-entity-id-5", event5.getTargetEntityId()); 128 | assertEquals(1, event5.getProperties().size()); 129 | assertEquals(properties.get("birthday"), new DateTime(event5.getProperties().get("birthday"))); 130 | assertEquals(then.getMillis(), event4.getEventTime().getMillis()); 131 | 132 | String empty = reader.readLine(); 133 | assertNull("no more data", empty); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /examples/import/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # IDE working files 9 | *.iws 10 | *.ipr 11 | *.iml 12 | .idea/ 13 | .settings 14 | .project 15 | .classpath 16 | 17 | .DS_Store 18 | 19 | -------------------------------------------------------------------------------- /examples/import/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 18 | 4.0.0 19 | org.apache.predictionio.samples 20 | sample-import 21 | 0.13.0 22 | jar 23 | PredictionIO Java SDK Examples: Import 24 | 25 | 26 | 27 | org.apache.predictionio 28 | predictionio-sdk-java-client 29 | 0.13.0 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-dependency-plugin 38 | 39 | 40 | copy-dependencies 41 | prepare-package 42 | 43 | copy-dependencies 44 | 45 | 46 | ${project.build.directory}/lib 47 | false 48 | false 49 | true 50 | 51 | 52 | 53 | 54 | 55 | org.apache.maven.plugins 56 | maven-compiler-plugin 57 | 3.0 58 | 59 | 1.7 60 | 1.7 61 | 62 | 63 | 64 | org.apache.maven.plugins 65 | maven-assembly-plugin 66 | 2.4 67 | 68 | 69 | 70 | org.apache.predictionio.samples.SampleImport 71 | 72 | 73 | 74 | jar-with-dependencies 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /examples/import/sampledata/sample1.txt: -------------------------------------------------------------------------------- 1 | 1 3 5 2 | 1 2 3 3 | 1 4 5 4 | 2 1 2 5 | 2 3 4 6 | 3 4 1 7 | -------------------------------------------------------------------------------- /examples/import/src/main/java/org/apache/predictionio/samples/SampleImport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.samples; 19 | 20 | import com.google.common.util.concurrent.FutureCallback; 21 | import com.google.common.util.concurrent.Futures; 22 | import com.google.common.util.concurrent.ListenableFuture; 23 | import java.io.BufferedReader; 24 | import java.io.FileReader; 25 | import java.io.IOException; 26 | import java.io.Reader; 27 | import java.util.ArrayList; 28 | import java.util.HashMap; 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.Set; 32 | import java.util.StringTokenizer; 33 | import java.util.TreeSet; 34 | import java.util.concurrent.ExecutionException; 35 | import org.apache.predictionio.sdk.java.APIResponse; 36 | import org.apache.predictionio.sdk.java.EventClient; 37 | import org.apache.predictionio.sdk.java.FutureAPIResponse; 38 | 39 | /** 40 | * Sample data import client using MovieLens data set. 41 | * 42 | * @author Cong Qin, Donald Szeto, Tom Chan 43 | */ 44 | public class SampleImport { 45 | 46 | private static final int HTTP_CREATED = 201; 47 | 48 | public static void main(String[] args) { 49 | /* set appurl to your API server */ 50 | String appurl = "http://localhost:7070"; 51 | /* Handle command line arguments */ 52 | String accessKey = null; 53 | String inputFile = null; 54 | try { 55 | accessKey = args[0]; 56 | inputFile = args[1]; 57 | } catch (ArrayIndexOutOfBoundsException e) { 58 | System.err.println("You must provide access key (1st arg) and input file name (2nd arg)"); 59 | System.exit(1); 60 | } 61 | 62 | EventClient client = null; 63 | Reader fileReader = null; 64 | 65 | /* Read input MovieLens data and send requests to API */ 66 | List listOfFutures = new ArrayList<>(); // keeping track of requests 67 | try { 68 | /* Create a client with the access key */ 69 | client = new EventClient(accessKey, appurl); 70 | 71 | /* Data structure */ 72 | Set uids = new TreeSet(); 73 | Set iids = new TreeSet(); 74 | 75 | /* Get API status */ 76 | System.out.println(client.getStatus()); 77 | 78 | /* Open data file for reading */ 79 | fileReader = new FileReader(inputFile); 80 | BufferedReader reader = new BufferedReader(fileReader); 81 | 82 | /* Some local variables */ 83 | String line; 84 | int i = 0; 85 | FutureAPIResponse future; 86 | Map userProperties = new HashMap<>(); // empty properties for user 87 | 88 | while ((line = reader.readLine()) != null) { 89 | /* Break the line up */ 90 | StringTokenizer st = new StringTokenizer(line); 91 | 92 | /* The 1st field is User ID, the 2nd field is Item ID, and the 3rd field is rating */ 93 | String uid = st.nextToken(); 94 | String iid = st.nextToken(); 95 | int rate = Integer.parseInt(st.nextToken()); 96 | 97 | /* Add user and item if they are not seen before */ 98 | if (uids.add(uid)) { 99 | // event time is omitted since we're not using it 100 | future = client.setUserAsFuture(uid, userProperties); 101 | listOfFutures.add(future); 102 | Futures.addCallback(future.getAPIResponse(), getFutureCallback("user " + uid)); 103 | } 104 | if (iids.add(iid)) { 105 | Map itemProperties = new HashMap<>(); 106 | List genre = new ArrayList<>(); 107 | genre.add("comedy"); 108 | itemProperties.put("genre", genre); 109 | future = client.setItemAsFuture(iid, itemProperties); 110 | listOfFutures.add(future); 111 | Futures.addCallback(future.getAPIResponse(), getFutureCallback("item " + iid)); 112 | } 113 | 114 | /* User rates the movie. We do this asynchronously */ 115 | Map properties = new HashMap<>(); // properties with rating 116 | properties.put("rating", rate); 117 | future = client.userActionItemAsFuture("rate", uid, iid, properties); 118 | listOfFutures.add(future); 119 | Futures.addCallback(future.getAPIResponse(), 120 | getFutureCallback("event " + uid + " rates " + iid + " with " + rate)); 121 | } 122 | } catch (Exception e) { 123 | System.err.println("Error: " + e.getMessage()); 124 | e.printStackTrace(); 125 | } finally { 126 | if (fileReader != null) { 127 | try { 128 | fileReader.close(); 129 | } catch (IOException e) { 130 | System.err.println("Error: " + e.getMessage()); 131 | } 132 | } 133 | // wait for the import result 134 | ListenableFuture> futures = Futures.allAsList(listOfFutures); 135 | try { 136 | List responses = futures.get(); 137 | for (APIResponse response : responses) { 138 | if (response.getStatus() != HTTP_CREATED) { 139 | System.err.println("Error importing some record, first error message is: " 140 | + response.getMessage()); 141 | // only print the first error 142 | break; 143 | } 144 | } 145 | } catch (InterruptedException | ExecutionException e) { 146 | System.err.println("Error importing some record, error message: " + e.getStackTrace()); 147 | } 148 | if (client != null) { 149 | client.close(); 150 | } 151 | } 152 | } 153 | 154 | private static FutureCallback getFutureCallback(final String name) { 155 | return new FutureCallback() { 156 | public void onSuccess(APIResponse response) { 157 | System.out.println(name + " added: " + response.getMessage()); 158 | } 159 | 160 | public void onFailure(Throwable thrown) { 161 | System.out.println("failed to add " + name + ": " + thrown.getMessage()); 162 | } 163 | }; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /examples/quickstart_import/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # IDE working files 9 | *.iws 10 | *.ipr 11 | *.iml 12 | .idea/ 13 | .settings 14 | .project 15 | .classpath 16 | 17 | .DS_Store 18 | 19 | -------------------------------------------------------------------------------- /examples/quickstart_import/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 18 | 4.0.0 19 | org.apache.predictionio.samples 20 | quickstart-import 21 | 0.13.0 22 | jar 23 | PredictionIO Java SDK Examples: Quickstart Import 24 | 25 | 26 | 27 | org.apache.predictionio 28 | predictionio-sdk-java-client 29 | 0.13.0 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-dependency-plugin 38 | 39 | 40 | copy-dependencies 41 | prepare-package 42 | 43 | copy-dependencies 44 | 45 | 46 | ${project.build.directory}/lib 47 | false 48 | false 49 | true 50 | 51 | 52 | 53 | 54 | 55 | org.apache.maven.plugins 56 | maven-compiler-plugin 57 | 3.0 58 | 59 | 1.7 60 | 1.7 61 | 62 | 63 | 64 | org.apache.maven.plugins 65 | maven-assembly-plugin 66 | 2.4 67 | 68 | 69 | 70 | org.apache.predictionio.samples.QuickstartImport 71 | 72 | 73 | 74 | jar-with-dependencies 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /examples/quickstart_import/src/main/java/org/apache/predictionio/samples/QuickstartImport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.predictionio.samples; 19 | 20 | import com.google.common.collect.ImmutableMap; 21 | import java.io.IOException; 22 | import java.util.LinkedList; 23 | import java.util.List; 24 | import java.util.Map; 25 | import java.util.Random; 26 | import java.util.concurrent.ExecutionException; 27 | import org.apache.predictionio.sdk.java.Event; 28 | import org.apache.predictionio.sdk.java.EventClient; 29 | import org.joda.time.DateTime; 30 | 31 | 32 | public class QuickstartImport { 33 | 34 | public static void main(String[] args) 35 | throws ExecutionException, InterruptedException, IOException { 36 | String accessKey = null; 37 | try { 38 | accessKey = args[0]; 39 | } catch (ArrayIndexOutOfBoundsException e) { 40 | System.err.println("You must provide access key as the parameter"); 41 | System.exit(1); 42 | } 43 | EventClient client = new EventClient(accessKey); 44 | Random rand = new Random(); 45 | Map emptyProperty = ImmutableMap.of(); 46 | 47 | // generate 10 users, with user ids 1 to 10 48 | for (int user = 1; user <= 10; user++) { 49 | System.out.println("Add user " + user); 50 | client.setUser("" + user, emptyProperty); 51 | } 52 | 53 | // generate 50 items, with item ids 1 to 50 54 | for (int item = 1; item <= 50; item++) { 55 | System.out.println("Add item " + item); 56 | client.setItem("" + item, emptyProperty); 57 | } 58 | 59 | // each user randomly views 10 items 60 | for (int user = 1; user <= 10; user++) { 61 | for (int i = 1; i <= 10; i++) { 62 | int item = rand.nextInt(50) + 1; 63 | System.out.println("User " + user + " views item " + item); 64 | client.userActionItem("view", "" + user, "" + item, emptyProperty); 65 | } 66 | } 67 | 68 | List events = new LinkedList(); 69 | 70 | // Use only 5 users because max batch size is 50 71 | // Throws IOException w/ details inside if this is exceeded 72 | for (int user = 1; user <= 5; user++) { 73 | for (int i = 1; i <= 10; i++) { 74 | int item = rand.nextInt(50) + 1; 75 | System.out.println("User " + user + " views item " + item); 76 | events.add(new Event() 77 | .event("view") 78 | .entityType("user") 79 | .entityId("" + user) 80 | .targetEntityType("item") 81 | .targetEntityId("" + item) 82 | .properties(emptyProperty) 83 | .eventTime(new DateTime())); 84 | } 85 | } 86 | 87 | client.createEvents(events); 88 | 89 | client.close(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 19 | 4.0.0 20 | org.apache.predictionio 21 | predictionio-sdk-java 22 | 0.13.1-SNAPSHOT 23 | http://predictionio.apache.org 24 | pom 25 | Apache PredictionIO Java SDK 26 | The Apache PredictionIO Java SDK includes an API client and sample code. 27 | 28 | 29 | org.apache 30 | apache 31 | 21 32 | 33 | 34 | 35 | scm:git:https://github.com/apache/predictionio-sdk-java 36 | scm:git:https://git-wip-us.apache.org/repos/asf/predictionio-sdk-java.git 37 | https://github.com/apache/predictionio-sdk-java 38 | HEAD 39 | 40 | 41 | 42 | 43 | com.google.guava 44 | guava 45 | 18.0 46 | 47 | 48 | 49 | 50 | 51 | Cong Qin 52 | Cong.Charlie.Qin@gmail.com 53 | 54 | 55 | 56 | 57 | UTF-8 58 | UTF-8 59 | ${project.build.directory} 60 | ${project.basedir} 61 | 62 | 63 | 64 | client 65 | 66 | 67 | 68 | 69 | 70 | org.apache.maven.plugins 71 | maven-checkstyle-plugin 72 | 3.0.0 73 | 74 | 75 | validate 76 | validate 77 | 78 | google_checks.xml 79 | UTF-8 80 | true 81 | true 82 | false 83 | 84 | 85 | check 86 | 87 | 88 | 89 | 90 | 91 | org.codehaus.mojo 92 | findbugs-maven-plugin 93 | 3.0.5 94 | 95 | 96 | validate 97 | validate 98 | 99 | check 100 | 101 | 102 | 103 | 104 | 105 | org.apache.rat 106 | apache-rat-plugin 107 | 0.12 108 | 109 | ${project.root}/.rat-excludes 110 | 111 | 112 | 113 | validate 114 | validate 115 | 116 | check 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | --------------------------------------------------------------------------------