├── .gitignore ├── LICENSE ├── README.md ├── graphql-example.png ├── metrics.png ├── pom.xml ├── quarkus-client ├── README.md ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── github │ │ └── phillipkruger │ │ └── user │ │ └── client │ │ ├── Person.java │ │ ├── PersonGraphQLClient.java │ │ ├── PersonMain.java │ │ ├── PersonRestClient.java │ │ └── Score.java │ └── resources │ └── application.properties ├── quarkus-example ├── README.md ├── basic.gif ├── grafana.json ├── hotreload.gif ├── native.gif ├── pom.xml ├── prometheus.yml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── github │ │ │ │ └── phillipkruger │ │ │ │ ├── user │ │ │ │ ├── graphql │ │ │ │ │ ├── PersonGraphQLApi.java │ │ │ │ │ └── ScoresNotAvailableException.java │ │ │ │ ├── model │ │ │ │ │ ├── Action.java │ │ │ │ │ ├── Address.java │ │ │ │ │ ├── Age.java │ │ │ │ │ ├── CreditCard.java │ │ │ │ │ ├── Gender.java │ │ │ │ │ ├── ImClient.java │ │ │ │ │ ├── Measurable.java │ │ │ │ │ ├── Person.java │ │ │ │ │ ├── Phone.java │ │ │ │ │ ├── Relation.java │ │ │ │ │ ├── RelationType.java │ │ │ │ │ ├── Score.java │ │ │ │ │ ├── ScoreType.java │ │ │ │ │ ├── SocialMedia.java │ │ │ │ │ └── Weight.java │ │ │ │ ├── rest │ │ │ │ │ ├── PersonRestApi.java │ │ │ │ │ └── ScoreRestApi.java │ │ │ │ └── service │ │ │ │ │ ├── PersonService.java │ │ │ │ │ └── ScoreService.java │ │ │ │ └── zzz │ │ │ │ └── graphql │ │ │ │ ├── Joke.java │ │ │ │ └── JokeOfTheDayApi.java │ │ └── resources │ │ │ ├── META-INF │ │ │ ├── beans.xml │ │ │ ├── branding_bak2 │ │ │ │ ├── smallrye-graphql-ui-graphiql.css │ │ │ │ ├── smallrye-graphql-ui-graphiql.ico │ │ │ │ ├── smallrye-open-api-ui.css │ │ │ │ └── smallrye-open-api-ui.png │ │ │ └── resources │ │ │ │ └── index.html │ │ │ ├── application.properties │ │ │ ├── import.sql │ │ │ └── score.json │ └── test │ │ ├── docker │ │ ├── Dockerfile.jvm │ │ └── Dockerfile.native │ │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── phillipkruger │ │ │ └── graphql │ │ │ ├── ExampleResourceTest.java │ │ │ └── NativeExampleResourceIT.java │ │ └── resources │ │ └── application.properties └── transcript.txt ├── tracing1.png ├── tracing2.png └── wildfly-example ├── pom.xml └── src └── main ├── java └── com │ └── github │ └── phillipkruger │ └── user │ ├── graphql │ ├── ProfileGraphQLApi.java │ └── ScoresNotAvailableException.java │ ├── model │ ├── Action.java │ ├── Address.java │ ├── Age.java │ ├── CreditCard.java │ ├── Event.java │ ├── Gender.java │ ├── ImClient.java │ ├── Measurable.java │ ├── Person.java │ ├── Phone.java │ ├── Profile.java │ ├── ProfileHateos.java │ ├── Relation.java │ ├── RelationType.java │ ├── Score.java │ ├── ScoreType.java │ ├── SocialMedia.java │ └── Weight.java │ ├── rest │ ├── ApplicationConfig.java │ ├── PersonRestApi.java │ └── ScoreRestApi.java │ └── service │ ├── PersonService.java │ └── ScoreService.java ├── resources └── META-INF │ ├── beans.xml │ ├── load.sql │ ├── microprofile-config.properties │ ├── persistence.xml │ └── score.json └── webapp ├── WEB-INF ├── beans.xml ├── jboss-web.xml └── web.xml ├── _data └── mystaticpage-data.json ├── css ├── font-awesome.min.css └── style.css ├── fonts ├── FontAwesome.otf ├── fontawesome-webfont.eot ├── fontawesome-webfont.svg ├── fontawesome-webfont.ttf ├── fontawesome-webfont.woff └── fontawesome-webfont.woff2 ├── images ├── avatar.jpg ├── background.jpg └── logo.png ├── index.html └── license.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | .idea/ 25 | *.iml 26 | nbactions.xml 27 | nb-configuration.xml 28 | /target/ 29 | /example/target/ 30 | /microprofile/target/ 31 | /microprofile/installed 32 | /smallrye/target/ 33 | /smallrye/installed 34 | /person-example/target/ 35 | /shared-backend/target/ 36 | /wildfly-example/target/ 37 | /quarkus-example/target/ 38 | /quarkus-client/target/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!WARNING] 2 | > Rather use https://github.com/phillip-kruger/quarkus-graphql-examples as this is not being maintained and kept us to date. 3 | 4 | 5 | # MicroProfile GraphQL Example 6 | 7 | This is an example of the [MicroProfile GraphQL API](https://github.com/eclipse/microprofile-graphql/) 8 | using the [SmallRye Implementation](https://github.com/smallrye/smallrye-graphql). It's done as part of these blog posts: 9 | 10 | - [Supersonic Subatomic GraphQL](https://quarkus.io/blog/supersonic-subatomic-graphql/) 11 | - [Microprofile GraphQL Introduction](https://www.phillip-kruger.com/post/microprofile_graphql_introduction/) 12 | 13 | and these [presentation](https://docs.google.com/presentation/d/1FCBw-qcjawBNNOSvqD7eJMUV96TwOL-4QyMkQAFt6tg/edit?usp=sharing)s: 14 | 15 | - Upcoming: Global Summit for Java devs'20 16 | - [Quarkus Insights](https://www.youtube.com/watch?v=nMti8-zIDQs) 17 | - [#OffTheChain](https://www.youtube.com/watch?v=OOTkQBCtYg0) 18 | - [joziJUG](https://youtu.be/UqDdDYo-g-8) 19 | - [SouJava](https://youtu.be/OOnpUeblVPM) 20 | - [DevConf.cz](https://www.youtube.com/watch?v=lA0L7iB-GV8) 21 | - [Java cloud conference](http://bit.ly/mp-graphql-presentation) 22 | 23 | The services are exposed with both REST and GraphQL for comparison. 24 | 25 | ## Person example 26 | 27 | This example expose person data as well as scores that the person got for certain activities. 28 | 29 | ### Running in Quarkus 30 | (generate from https://code.quarkus.io/) 31 | 32 | ``` 33 | cd quarkus-example 34 | mvn clean install quarkus:dev 35 | ``` 36 | 37 | ### Running in Wildfly 38 | 39 | ``` 40 | cd wildfly-example 41 | mvn clean install wildfly:run 42 | ``` 43 | 44 | This will start the application on port 8080. 45 | 46 | ## Testing 47 | 48 | Go to http://localhost:8080 to test the application. 49 | 50 | - Click on the 'REST' link to open Swagger UI to test the JAX-RS services. 51 | - Click on the 'GraphQL' link to open GraphiQL UI to test the MicroProfile GraphQL service. 52 | 53 | To stop the application, `ctrl-c` in the maven session. 54 | 55 | ![screenshot](graphql-example.png) 56 | 57 | ### Examples 58 | 59 | See the model in the JavaDoc (target/apidocs/index.html) 60 | 61 | #### Demo 1 : MicroProfile GraphQL vs JAX-RS 62 | 63 | ##### REST 64 | 65 | Schema: http://localhost:8080/openapi 66 | 67 | ``` 68 | curl -X GET "http://localhost:8080/rest/profile/1" -H "accept: application/json" 69 | ``` 70 | 71 | ##### GraphQL 72 | 73 | Schema: http://localhost:8080/graphql/schema.graphql 74 | 75 | ``` 76 | { 77 | person(id:1){ 78 | names 79 | surname 80 | } 81 | } 82 | ``` 83 | 84 | #### Demo 2: Stitching 85 | 86 | ``` 87 | { 88 | person(id:1){ 89 | names 90 | surname 91 | scores{ 92 | name 93 | value 94 | } 95 | } 96 | } 97 | ``` 98 | 99 | in the log file: 100 | 101 | ``` 102 | ======= Getting person [1] ======= 103 | ======= Getting scores [512-46-5065] ======= 104 | ``` 105 | 106 | without score 107 | 108 | ``` 109 | { 110 | person(id:1){ 111 | names 112 | surname 113 | } 114 | } 115 | ``` 116 | 117 | in the log file: 118 | 119 | ``` 120 | ======= Getting person [1] ======= 121 | ``` 122 | 123 | #### Demo 3: Batch 124 | 125 | ``` 126 | { 127 | people{ 128 | names 129 | scores{ 130 | name 131 | } 132 | } 133 | } 134 | ``` 135 | in the log file: 136 | 137 | ``` 138 | ======= Getting scores [797-95-4822, 373-95-3047, 097-87-6795, 347-01-8880, 733-86-4423, 560-99-2165, 091-07-5401, 539-70-2014, 029-18-5986, 287-58-0690] ======= 139 | ``` 140 | 141 | #### Demo 4: More than one request 142 | 143 | ``` 144 | { 145 | person1:person(id:1){ 146 | surname 147 | scores{ 148 | name 149 | value 150 | } 151 | } 152 | person2:person(id:2){ 153 | surname 154 | } 155 | } 156 | ``` 157 | 158 | or more than one query: 159 | 160 | ``` 161 | @Query 162 | public Integer getRandomNumber(long seed){ 163 | Random random = new Random(seed); 164 | return random.nextInt(); 165 | } 166 | ``` 167 | 168 | ``` 169 | { 170 | person1:person(id:1){ 171 | surname 172 | scores{ 173 | name 174 | value 175 | } 176 | } 177 | randomId:randomNumber(seed:11) 178 | } 179 | ``` 180 | 181 | 182 | #### Demo 5: Collections 183 | 184 | ``` 185 | { 186 | people { 187 | surname 188 | } 189 | } 190 | ``` 191 | 192 | #### Demo 6: JsonB Annotations support 193 | 194 | ``` 195 | { 196 | person(id:1){ 197 | surname 198 | birthDate 199 | } 200 | } 201 | ``` 202 | 203 | #### Demo 7: DefaultValue 204 | 205 | ``` 206 | @Query 207 | public List getPersonsWithSurname( 208 | @DefaultValue("Doyle") String surname) { 209 | return personService.getPeopleWithSurname(surname); 210 | } 211 | ``` 212 | 213 | Providing a parameter 214 | 215 | ``` 216 | { 217 | personsWithSurname(surname:"Hyatt") { 218 | names 219 | } 220 | } 221 | ``` 222 | 223 | Uing the default 224 | 225 | ``` 226 | { 227 | personsWithSurname { 228 | names 229 | } 230 | } 231 | ``` 232 | 233 | #### Demo 8: Errors and partial responses 234 | 235 | ##### Validation Errors 236 | 237 | ``` 238 | { 239 | person(id:1){ 240 | surname 241 | scores{ 242 | thisDoesNotExist 243 | } 244 | } 245 | } 246 | ``` 247 | 248 | ##### Partial results 249 | 250 | ``` 251 | { 252 | person(id:1){ 253 | surname 254 | scores{ 255 | name 256 | value 257 | } 258 | } 259 | } 260 | ``` 261 | 262 | #### Demo 9: Metrics and Tracing 263 | 264 | ##### Servers 265 | 266 | This will be specific to your setup. For me: 267 | 268 | **Start Prometheus:** 269 | ``` 270 | cd /opt/Metrics/prometheus-2.19.2.linux-amd64 271 | ./prometheus --config.file=prometheus.yml 272 | ``` 273 | (prometheus.yml is in the root folder) 274 | 275 | **Start Grafana:** 276 | ``` 277 | sudo systemctl start grafana-server 278 | ``` 279 | (grafana.json is in the root folder) 280 | 281 | **Start Jaeger:** 282 | ``` 283 | docker run -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 14268:14268 jaegertracing/all-in-one:latest 284 | ``` 285 | 286 | ##### Metrics 287 | 288 | ``` 289 | @Timed(name = "personTimer", description = "How long does it take to get a Person.", unit = MetricUnits.NANOSECONDS) 290 | @Counted(name = "personCount", description = "How many times did we ask for Person.") 291 | ``` 292 | 293 | [Grafana Dashboard](http://localhost:3000/d/T2kbtqZGk/person-metrics?orgId=1&refresh=5s) 294 | 295 | ![metrics](metrics.png) 296 | 297 | ##### Tracing 298 | 299 | [Jaeger Dashboard](http://localhost:16686/search) 300 | 301 | ![tracing1](tracing1.png) 302 | ![tracing2](tracing2.png) 303 | 304 | #### Demo 10: Security 305 | 306 | ``` 307 | @RolesAllowed("admin") 308 | ``` 309 | 310 | #### Demo 11: Bean validation 311 | 312 | ``` 313 | @Query 314 | public Integer getRandomNumber(@Min(10) long seed){ 315 | Random random = new Random(seed); 316 | return random.nextInt(); 317 | } 318 | ``` 319 | 320 | ``` 321 | { 322 | randomNumber(seed:9) 323 | } 324 | ``` 325 | 326 | #### Demo 12: Mutations 327 | 328 | ``` 329 | @Mutation 330 | public Person updatePerson(Person person){ 331 | return personService.updateOrCreate(person); 332 | } 333 | 334 | @Mutation 335 | public Person deletePerson(Long id){ 336 | return personService.delete(id); 337 | } 338 | ``` 339 | 340 | ##### Create 341 | ``` 342 | mutation CreatePerson{ 343 | updatePerson(person : 344 | { 345 | names: "Phillip" 346 | } 347 | ){ 348 | id 349 | names 350 | surname 351 | profilePictures 352 | website 353 | } 354 | } 355 | ``` 356 | 357 | ##### Update 358 | 359 | (using the generated id) 360 | 361 | ``` 362 | mutation UpdatePerson{ 363 | updatePerson(person : 364 | { 365 | id: 11, 366 | names:"Phillip", 367 | surname: "Kruger", 368 | profilePictures: [ 369 | "https://pbs.twimg.com/profile_images/1170690050524405762/I8KJ_hF4_400x400.jpg" 370 | ], 371 | website: "http://www.phillip-kruger.com" 372 | }){ 373 | id 374 | names 375 | surname 376 | profilePictures 377 | website 378 | } 379 | } 380 | ``` 381 | 382 | ##### Delete 383 | 384 | (using the id) 385 | 386 | ``` 387 | mutation DeletePerson{ 388 | deletePerson(id :11){ 389 | id 390 | surname 391 | } 392 | } 393 | ``` 394 | 395 | #### Demo 13: Context (Experimental) 396 | 397 | ``` 398 | quarkus.hibernate-orm.log.sql=true 399 | ``` 400 | 401 | ``` 402 | @Inject 403 | Context context; 404 | 405 | JsonArray selectedFields = context.getSelectedFields(); 406 | System.out.println("selectedFields [" + selectedFields +"]"); 407 | 408 | ``` 409 | 410 | 411 | 412 | ``` 413 | { 414 | people{ 415 | surname 416 | } 417 | } 418 | ``` 419 | 420 | #### Demo 14: Client (Future) 421 | 422 | See the model in the JavaDoc (target/apidocs/index.html) 423 | 424 | ``` 425 | //@Inject 426 | PersonGraphQLClient graphQLClient = GraphQlClientBuilder.newBuilder().build(PersonGraphQLClient.class); 427 | ``` 428 | 429 | ``` 430 | Person graphQLPerson = graphQLClient.getPerson(id); 431 | 432 | System.err.println("================ GRAPHQL ================"); 433 | System.err.println(graphQLPerson); 434 | ``` 435 | #### Apendix: Introspection 436 | 437 | ``` 438 | { 439 | __schema{ 440 | types { 441 | name 442 | kind 443 | } 444 | } 445 | } 446 | 447 | ``` 448 | 449 | #### The Introspection query used by GrapiQL 450 | 451 | ``` 452 | query IntrospectionQuery { 453 | __schema { 454 | queryType { name } 455 | mutationType { name } 456 | subscriptionType { name } 457 | types { 458 | ...FullType 459 | } 460 | directives { 461 | name 462 | description 463 | locations 464 | args { 465 | ...InputValue 466 | } 467 | } 468 | } 469 | } 470 | 471 | fragment FullType on __Type { 472 | kind 473 | name 474 | description 475 | fields(includeDeprecated: true) { 476 | name 477 | description 478 | args { 479 | ...InputValue 480 | } 481 | type { 482 | ...TypeRef 483 | } 484 | isDeprecated 485 | deprecationReason 486 | } 487 | inputFields { 488 | ...InputValue 489 | } 490 | interfaces { 491 | ...TypeRef 492 | } 493 | enumValues(includeDeprecated: true) { 494 | name 495 | description 496 | isDeprecated 497 | deprecationReason 498 | } 499 | possibleTypes { 500 | ...TypeRef 501 | } 502 | } 503 | 504 | fragment InputValue on __InputValue { 505 | name 506 | description 507 | type { ...TypeRef } 508 | defaultValue 509 | } 510 | 511 | fragment TypeRef on __Type { 512 | kind 513 | name 514 | ofType { 515 | kind 516 | name 517 | ofType { 518 | kind 519 | name 520 | ofType { 521 | kind 522 | name 523 | ofType { 524 | kind 525 | name 526 | ofType { 527 | kind 528 | name 529 | ofType { 530 | kind 531 | name 532 | ofType { 533 | kind 534 | name 535 | } 536 | } 537 | } 538 | } 539 | } 540 | } 541 | } 542 | } 543 | ``` 544 | 545 | ### Schemas 546 | 547 | - REST: http://localhost:8080/openapi 548 | - GraphQL: http://localhost:8080/graphql/schema.graphql 549 | -------------------------------------------------------------------------------- /graphql-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/graphql-example.png -------------------------------------------------------------------------------- /metrics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/metrics.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.github.phillip-kruger.graphql 6 | graphql-example-parent 7 | 1.0.0-SNAPSHOT 8 | pom 9 | 10 | GraphQL Demo 11 | 12 | https://github.com/phillip-kruger/graphql-example 13 | Example application to demonstrate GraphQL 14 | 15 | 16 | 17 | Apache License, Version 2.0 18 | http://www.apache.org/licenses/LICENSE-2.0.txt 19 | repo 20 | 21 | 22 | 23 | 24 | scm:git:https://github.com/phillip-kruger/graphql-example.git 25 | https://github.com/phillip-kruger/graphql-example 26 | 27 | 28 | 29 | 30 | wiki 31 | https://github.com/phillip-kruger/graphql-example/wiki 32 | 33 | 34 | 35 | ossrh 36 | https://oss.sonatype.org/content/repositories/snapshots 37 | 38 | 39 | ossrh 40 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 41 | 42 | 43 | 44 | 45 | 46 | 47 | Phillip Kruger 48 | phillip.kruger@redhat.com 49 | http://www.phillip-kruger.com 50 | 51 | 52 | 53 | 54 | false 55 | UTF-8 56 | UTF-8 57 | 17 58 | 17 59 | 60 | 1.6.0 61 | 2.11.1.Final 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.eclipse.microprofile 69 | microprofile 70 | 4.0.1 71 | pom 72 | provided 73 | 74 | 75 | 76 | 77 | 78 | wildfly-example 79 | quarkus-example 80 | quarkus-client 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /quarkus-client/README.md: -------------------------------------------------------------------------------- 1 | # Quarkus Client example 2 | 3 | This project uses Quarkus Command mode and the SmallRye client. 4 | 5 | ## Build 6 | 7 | ``` 8 | mvn clean install 9 | ``` 10 | 11 | ## Run 12 | 13 | Make sure you have the server running, then: 14 | 15 | ``` 16 | java -jar target/quarkus-client-1.0.0-SNAPSHOT-runner.jar 1 17 | ``` 18 | 19 | Where `1` is the person id. 20 | 21 | This will result in the person being fetched from the server: 22 | 23 | ``` 24 | 25 | ``` -------------------------------------------------------------------------------- /quarkus-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.github.phillip-kruger.graphql 6 | graphql-example-parent 7 | 1.0.0-SNAPSHOT 8 | ../ 9 | 10 | 11 | quarkus-client 12 | jar 13 | 14 | GraphQL Demo :: Client Example 15 | 16 | 17 | ${quarkus.version} 18 | quarkus-bom 19 | io.quarkus 20 | ${quarkus.version} 21 | 3.8.1 22 | 2.22.1 23 | UTF-8 24 | 17 25 | 17 26 | true 27 | 28 | 29 | 30 | 31 | 32 | ${quarkus.platform.group-id} 33 | ${quarkus.platform.artifact-id} 34 | ${quarkus.platform.version} 35 | pom 36 | import 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | io.quarkus 45 | quarkus-rest-client 46 | 47 | 48 | io.quarkus 49 | quarkus-rest-client-jsonb 50 | 51 | 52 | 53 | io.quarkus 54 | quarkus-smallrye-graphql-client 55 | 56 | 57 | 58 | 59 | 60 | 61 | maven-compiler-plugin 62 | ${compiler-plugin.version} 63 | 64 | 65 | maven-surefire-plugin 66 | ${surefire-plugin.version} 67 | 68 | 69 | org.jboss.logmanager.LogManager 70 | 71 | 72 | 73 | 74 | io.quarkus 75 | quarkus-maven-plugin 76 | ${quarkus-plugin.version} 77 | 78 | 79 | 80 | build 81 | 82 | 83 | 84 | 85 | 86 | 87 | org.apache.maven.plugins 88 | maven-javadoc-plugin 89 | 3.2.0 90 | 91 | 92 | attach-javadocs 93 | 94 | jar 95 | 96 | 97 | nl.talsmasoftware.umldoclet.UMLDoclet 98 | 99 | nl.talsmasoftware 100 | umldoclet 101 | 2.0.9 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | native 114 | 115 | 116 | native 117 | 118 | 119 | 120 | 121 | 122 | io.quarkus 123 | quarkus-maven-plugin 124 | ${quarkus-plugin.version} 125 | 126 | 127 | 128 | native-image 129 | 130 | 131 | true 132 | 133 | 134 | 135 | 136 | 137 | maven-failsafe-plugin 138 | ${surefire-plugin.version} 139 | 140 | 141 | 142 | integration-test 143 | verify 144 | 145 | 146 | 147 | ${project.build.directory}/${project.build.finalName}-runner 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /quarkus-client/src/main/java/com/github/phillipkruger/user/client/Person.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.client; 2 | 3 | import java.math.BigInteger; 4 | import java.util.List; 5 | 6 | public class Person { 7 | private BigInteger id; 8 | private String title; 9 | private List names; 10 | private String surname; 11 | private List scores; 12 | 13 | public BigInteger getId() { 14 | return id; 15 | } 16 | 17 | public void setId(BigInteger id) { 18 | this.id = id; 19 | } 20 | 21 | public String getTitle() { 22 | return title; 23 | } 24 | 25 | public void setTitle(String title) { 26 | this.title = title; 27 | } 28 | 29 | public List getNames() { 30 | return names; 31 | } 32 | 33 | public void setNames(List names) { 34 | this.names = names; 35 | } 36 | 37 | public String getSurname() { 38 | return surname; 39 | } 40 | 41 | public void setSurname(String surname) { 42 | this.surname = surname; 43 | } 44 | 45 | public List getScores() { 46 | return scores; 47 | } 48 | 49 | public void setScore(List scores) { 50 | this.scores = scores; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "Person{" + "id=" + id + ", title=" + title + ", names=" + names + ", surname=" + surname + ", scores=" + scores + '}'; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /quarkus-client/src/main/java/com/github/phillipkruger/user/client/PersonGraphQLClient.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.client; 2 | 3 | import io.smallrye.graphql.client.typesafe.api.GraphQLClientApi; 4 | import java.math.BigInteger; 5 | import org.eclipse.microprofile.graphql.Query; 6 | 7 | @GraphQLClientApi 8 | public interface PersonGraphQLClient { 9 | 10 | @Query 11 | public Person getPerson(BigInteger id); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /quarkus-client/src/main/java/com/github/phillipkruger/user/client/PersonMain.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.client; 2 | 3 | import io.quarkus.runtime.QuarkusApplication; 4 | import io.quarkus.runtime.annotations.QuarkusMain; 5 | import io.smallrye.graphql.client.GraphQLClient; 6 | import io.smallrye.graphql.client.Response; 7 | import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; 8 | import java.math.BigInteger; 9 | import javax.inject.Inject; 10 | import org.eclipse.microprofile.rest.client.inject.RestClient; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * Main app to do person operations 17 | * @author Phillip Kruger (phillip.kruger@redhat.com) 18 | */ 19 | @QuarkusMain 20 | public class PersonMain implements QuarkusApplication { 21 | 22 | @Inject 23 | PersonGraphQLClient graphQLClient; 24 | 25 | @Inject @RestClient 26 | PersonRestClient restClient; 27 | 28 | @Inject 29 | @GraphQLClient("person-dynamic") 30 | DynamicGraphQLClient graphQLDynamicClient; 31 | 32 | @Override 33 | public int run(String... args) throws Exception { 34 | BigInteger id = getRequestedPersonId(args); 35 | 36 | System.err.println("================ REST ================"); 37 | Person restPerson = restClient.getPerson(id); 38 | System.err.println(restPerson); 39 | 40 | System.err.println("================ GRAPHQL Typesafe ================"); 41 | Person graphQlPerson = graphQLClient.getPerson(id); 42 | System.err.println(graphQlPerson); 43 | 44 | System.err.println("================ GRAPHQL Dynamic ================"); 45 | 46 | String personQuery = """ 47 | query Person($id: BigInteger = 1){ 48 | person(id:$id){ 49 | id 50 | title 51 | names 52 | surname 53 | scores { 54 | name 55 | value 56 | } 57 | } 58 | }"""; 59 | 60 | Map vars = new HashMap<>(); 61 | vars.put("id",1); 62 | 63 | Response response = graphQLDynamicClient.executeSync(personQuery,vars); 64 | Person graphQLDynamicPerson = response.getObject(Person.class, "person"); 65 | System.err.println(graphQLDynamicPerson); 66 | 67 | return 0; 68 | } 69 | 70 | private BigInteger getRequestedPersonId(String... args){ 71 | BigInteger id = new BigInteger("1"); 72 | if(args.length!=0){ 73 | id = new BigInteger(args[0]); 74 | } 75 | return id; 76 | } 77 | } -------------------------------------------------------------------------------- /quarkus-client/src/main/java/com/github/phillipkruger/user/client/PersonRestClient.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.client; 2 | 3 | import java.math.BigInteger; 4 | import javax.ws.rs.GET; 5 | import javax.ws.rs.Path; 6 | import javax.ws.rs.PathParam; 7 | import javax.ws.rs.Produces; 8 | import javax.ws.rs.core.MediaType; 9 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 10 | 11 | @RegisterRestClient 12 | public interface PersonRestClient { 13 | 14 | @GET 15 | @Path("/person/{id}") 16 | @Produces(MediaType.APPLICATION_JSON) 17 | public Person getPerson(@PathParam("id") BigInteger id); 18 | } 19 | -------------------------------------------------------------------------------- /quarkus-client/src/main/java/com/github/phillipkruger/user/client/Score.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.client; 2 | 3 | /** 4 | * Score of the person 5 | * @author Phillip Kruger (phillip.kruger@redhat.com) 6 | */ 7 | public class Score { 8 | 9 | private String name; 10 | private Long value; 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public void setName(String name) { 17 | this.name = name; 18 | } 19 | 20 | public Long getValue() { 21 | return value; 22 | } 23 | 24 | public void setValue(Long value) { 25 | this.value = value; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "Score{" + "name=" + name + ", value=" + value + '}'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /quarkus-client/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Quarkus Configuration file 2 | quarkus.banner.enabled=false 3 | quarkus.log.level=ERROR 4 | com.github.phillipkruger.user.client.PersonGraphQLClient/mp-graphql/url=http://localhost:8080/graphql 5 | com.github.phillipkruger.user.client.PersonRestClient/mp-rest/url=http://localhost:8080 6 | quarkus.smallrye-graphql-client.person-dynamic.url=http://localhost:8080/graphql -------------------------------------------------------------------------------- /quarkus-example/README.md: -------------------------------------------------------------------------------- 1 | # Quarkus MicroProfile GraphQL Example 2 | 3 | This project uses Quarkus, the Supersonic Subatomic Java Framework. 4 | 5 | If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . 6 | 7 | ## Running the application in dev mode 8 | 9 | ![basic](basic.gif) 10 | 11 | You can run your application in dev mode that enables live coding using: 12 | ``` 13 | ./mvnw quarkus:dev 14 | ``` 15 | 16 | ![hotreload](hotreload.gif) 17 | 18 | ## Packaging and running the application 19 | 20 | The application can be packaged using `./mvnw package`. 21 | It produces the `quarkus-example-1.0.0-SNAPSHOT-runner.jar` file in the `/target` directory. 22 | Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/lib` directory. 23 | 24 | The application is now runnable using `java -jar target/quarkus-example-1.0.0-SNAPSHOT-runner.jar`. 25 | 26 | ## Creating a native executable 27 | 28 | You can create a native executable using: `./mvnw package -Pnative`. 29 | 30 | ![native](native.gif) 31 | 32 | Or, if you don't have GraalVM installed, you can run the native executable build in a container using: `./mvnw package -Pnative -Dquarkus.native.container-build=true`. 33 | 34 | You can then execute your native executable with: `./target/quarkus-example-1.0.0-SNAPSHOT-runner` 35 | 36 | If you want to learn more about building native executables, please consult https://quarkus.io/guides/building-native-image. -------------------------------------------------------------------------------- /quarkus-example/basic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/quarkus-example/basic.gif -------------------------------------------------------------------------------- /quarkus-example/hotreload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/quarkus-example/hotreload.gif -------------------------------------------------------------------------------- /quarkus-example/native.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/quarkus-example/native.gif -------------------------------------------------------------------------------- /quarkus-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.github.phillip-kruger.graphql 7 | graphql-example-parent 8 | 1.0.0-SNAPSHOT 9 | ../ 10 | 11 | 12 | quarkus-example 13 | jar 14 | 15 | GraphQL Demo :: Quarkus Example 16 | 17 | 18 | 3.8.1 19 | true 20 | io.quarkus 21 | quarkus-bom 22 | ${quarkus.version} 23 | ${quarkus.version} 24 | 2.22.1 25 | 26 | 27 | 28 | 29 | 30 | ${quarkus.platform.group-id} 31 | ${quarkus.platform.artifact-id} 32 | ${quarkus.platform.version} 33 | pom 34 | import 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | io.quarkus 43 | quarkus-smallrye-graphql 44 | 45 | 46 | 47 | 48 | io.quarkus 49 | quarkus-resteasy 50 | 51 | 52 | io.quarkus 53 | quarkus-jsonb 54 | 55 | 56 | io.quarkus 57 | quarkus-resteasy-jsonb 58 | 59 | 60 | io.quarkus 61 | quarkus-smallrye-openapi 62 | 63 | 64 | 65 | 66 | io.quarkus 67 | quarkus-hibernate-orm 68 | 69 | 73 | 74 | io.quarkus 75 | quarkus-jdbc-postgresql 76 | 77 | 78 | 79 | 80 | 88 | 89 | 90 | 91 | io.quarkus 92 | quarkus-oidc 93 | 94 | 95 | 96 | 97 | io.quarkus 98 | quarkus-hibernate-validator 99 | 100 | 101 | 102 | 103 | io.quarkus 104 | quarkus-junit5 105 | test 106 | 107 | 108 | io.rest-assured 109 | rest-assured 110 | test 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | io.quarkus 119 | quarkus-maven-plugin 120 | ${quarkus-plugin.version} 121 | 122 | 123 | 124 | build 125 | 126 | 127 | 128 | 129 | 130 | maven-compiler-plugin 131 | ${compiler-plugin.version} 132 | 133 | 134 | maven-surefire-plugin 135 | ${surefire-plugin.version} 136 | 137 | 138 | org.jboss.logmanager.LogManager 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | native 149 | 150 | 151 | native 152 | 153 | 154 | 155 | 156 | 157 | maven-failsafe-plugin 158 | ${surefire-plugin.version} 159 | 160 | 161 | 162 | integration-test 163 | verify 164 | 165 | 166 | 167 | ${project.build.directory}/${project.build.finalName}-runner 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | native 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /quarkus-example/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 5s 3 | evaluation_interval: 5s 4 | alerting: 5 | alertmanagers: 6 | - static_configs: 7 | - targets: 8 | scrape_configs: 9 | - job_name: 'prometheus' 10 | static_configs: 11 | - targets: ['localhost:9090'] 12 | - job_name: 'sampleapp' 13 | static_configs: 14 | - targets: ['localhost:8080'] 15 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/graphql/PersonGraphQLApi.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.graphql; 2 | 3 | import com.github.phillipkruger.user.model.Person; 4 | import com.github.phillipkruger.user.model.Score; 5 | import com.github.phillipkruger.user.service.PersonService; 6 | import com.github.phillipkruger.user.service.ScoreService; 7 | import graphql.GraphQL; 8 | import graphql.schema.GraphQLSchema; 9 | import io.smallrye.graphql.api.Subscription; 10 | import io.smallrye.mutiny.Multi; 11 | 12 | import java.util.List; 13 | import javax.enterprise.event.Observes; 14 | import javax.inject.Inject; 15 | import org.eclipse.microprofile.graphql.DefaultValue; 16 | import org.eclipse.microprofile.graphql.Description; 17 | import org.eclipse.microprofile.graphql.GraphQLApi; 18 | import org.eclipse.microprofile.graphql.Mutation; 19 | import org.eclipse.microprofile.graphql.Query; 20 | import org.eclipse.microprofile.graphql.Source; 21 | 22 | @GraphQLApi 23 | public class PersonGraphQLApi { 24 | 25 | @Inject 26 | PersonService personService; 27 | 28 | @Inject 29 | ScoreService scoreService; 30 | 31 | @Query 32 | @Description("Get a person using the person's Id") 33 | public Person getPerson(Long id){ 34 | return personService.getPerson(id); 35 | } 36 | 37 | @Query 38 | public List getPeople(){ 39 | return personService.getPeople(); 40 | } 41 | 42 | //@RolesAllowed("admin") 43 | public List getScores(@Source Person person) throws ScoresNotAvailableException{ 44 | return scoreService.getScores(person.getIdNumber()); 45 | //throw new ScoresNotAvailableException("Scores for person [" + person.getId() + "] not avaialble"); 46 | } 47 | 48 | // Batch version of above (only this takes effect when both is present) 49 | // public List> getScores(@Source List people) throws ScoresNotAvailableException{ 50 | // List idNumbers = people.stream().map(p -> p.getIdNumber()).collect(Collectors.toList()); 51 | // return scoreService.getScores(idNumbers); 52 | // //throw new ScoresNotAvailableException("Scores not avaialble"); 53 | // } 54 | 55 | // Mutations 56 | @Mutation 57 | public Person updatePerson(Person person){ 58 | return personService.updateOrCreate(person); 59 | } 60 | 61 | @Mutation 62 | public Person deletePerson(Long id){ 63 | return personService.delete(id); 64 | } 65 | 66 | // Default values 67 | @Query 68 | public List getPersonsWithSurname( 69 | @DefaultValue("Doyle") String surname) { 70 | return personService.getPeopleWithSurname(surname); 71 | } 72 | 73 | @Subscription 74 | public Multi personAdded(){ 75 | return personService.personListener(); 76 | } 77 | 78 | public GraphQLSchema.Builder leakyAbstraction(@Observes GraphQLSchema.Builder builder) { 79 | System.err.println(">>>>>>> Here we leak while building the schema"); 80 | // Do what you have to do 81 | return builder; 82 | } 83 | 84 | public GraphQL.Builder leakyAbstraction(@Observes GraphQL.Builder builder) { 85 | System.err.println(">>>>>>> Here we leak while building graphQL"); 86 | // Do what you have to do 87 | return builder; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/graphql/ScoresNotAvailableException.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.graphql; 2 | 3 | public class ScoresNotAvailableException extends Exception { 4 | 5 | public ScoresNotAvailableException() { 6 | } 7 | 8 | public ScoresNotAvailableException(String string) { 9 | super(string); 10 | } 11 | 12 | public ScoresNotAvailableException(String string, Throwable thrwbl) { 13 | super(string, thrwbl); 14 | } 15 | 16 | public ScoresNotAvailableException(Throwable thrwbl) { 17 | super(thrwbl); 18 | } 19 | 20 | public ScoresNotAvailableException(String string, Throwable thrwbl, boolean bln, boolean bln1) { 21 | super(string, thrwbl, bln, bln1); 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Action.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum Action { 4 | Steps,Gym,Drive,Save,CheckUp 5 | } 6 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Address.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.util.List; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.ElementCollection; 6 | import javax.persistence.Entity; 7 | import javax.persistence.FetchType; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.OrderColumn; 12 | 13 | @Entity 14 | public class Address { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.SEQUENCE) 18 | @JsonbTransient 19 | private Integer id; 20 | 21 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 22 | @OrderColumn 23 | private List lines; 24 | private String code; 25 | 26 | public Integer getId() { 27 | return id; 28 | } 29 | 30 | public void setId(Integer id) { 31 | this.id = id; 32 | } 33 | 34 | public List getLines() { 35 | return lines; 36 | } 37 | 38 | public void setLines(List lines) { 39 | this.lines = lines; 40 | } 41 | 42 | public String getCode() { 43 | return code; 44 | } 45 | 46 | public void setCode(String code) { 47 | this.code = code; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Age.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public class Age implements Measurable { 4 | private Long value; 5 | 6 | @Override 7 | public Long getValue() { 8 | return value; 9 | } 10 | 11 | public void setValue(Long value) { 12 | this.value = value; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/CreditCard.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import javax.json.bind.annotation.JsonbTransient; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | 9 | @Entity 10 | public class CreditCard { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.SEQUENCE) 14 | @JsonbTransient 15 | private Integer id; 16 | 17 | private String expiry; 18 | private String number; 19 | private String type; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getExpiry() { 30 | return expiry; 31 | } 32 | 33 | public void setExpiry(String expiry) { 34 | this.expiry = expiry; 35 | } 36 | 37 | public String getNumber() { 38 | return number; 39 | } 40 | 41 | public void setNumber(String number) { 42 | this.number = number; 43 | } 44 | 45 | public String getType() { 46 | return type; 47 | } 48 | 49 | public void setType(String type) { 50 | this.type = type; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Gender.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum Gender { 4 | Male,Female 5 | } 6 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/ImClient.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | 10 | @Entity 11 | public class ImClient { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.IDENTITY) 15 | @JsonbTransient 16 | private Integer id; 17 | 18 | private String im; 19 | private String identifier; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getIm() { 30 | return im; 31 | } 32 | 33 | public void setIm(String im) { 34 | this.im = im; 35 | } 36 | 37 | public String getIdentifier() { 38 | return identifier; 39 | } 40 | 41 | public void setIdentifier(String identifier) { 42 | this.identifier = identifier; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Measurable.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | /** 4 | * Something that can be measured 5 | * @author Phillip Kruger (phillip.kruger@redhat.com) 6 | */ 7 | public interface Measurable { 8 | public Long getValue(); 9 | } 10 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Person.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import java.net.URL; 5 | import java.time.LocalDate; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import javax.json.bind.annotation.JsonbDateFormat; 9 | import javax.persistence.CascadeType; 10 | import javax.persistence.ElementCollection; 11 | import javax.persistence.Entity; 12 | import javax.persistence.FetchType; 13 | import javax.persistence.GeneratedValue; 14 | import javax.persistence.GenerationType; 15 | import javax.persistence.Id; 16 | import javax.persistence.OneToMany; 17 | 18 | @Entity 19 | public class Person implements Serializable { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.SEQUENCE) 23 | private Long id; 24 | 25 | private String locale; 26 | 27 | private String title; 28 | 29 | @ElementCollection(fetch = FetchType.LAZY, targetClass=String.class) 30 | private List names; 31 | 32 | @ElementCollection(targetClass=String.class) 33 | private List nicknames; 34 | 35 | private String surname; 36 | 37 | private String username; 38 | 39 | private String idNumber; 40 | 41 | @ElementCollection(targetClass=URL.class) 42 | private List coverphotos; 43 | 44 | @ElementCollection(targetClass=URL.class) 45 | private List profilePictures; 46 | 47 | private Gender gender; 48 | 49 | @JsonbDateFormat("dd/MM/yyyy") 50 | private LocalDate birthDate; 51 | 52 | private String favColor; 53 | 54 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 55 | private List
addresses; 56 | 57 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 58 | private List emailAddresses; 59 | 60 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 61 | private List phoneNumbers; 62 | 63 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 64 | private List imClients; 65 | 66 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 67 | private List socialMedias; 68 | 69 | private URL website; 70 | 71 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 72 | private List taglines; 73 | 74 | private String biography; 75 | 76 | private String organization; 77 | 78 | private String occupation; 79 | 80 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 81 | private List interests; 82 | 83 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 84 | private List skills; 85 | 86 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 87 | private List relations; 88 | 89 | @JsonbDateFormat("dd/MM/yyyy") 90 | private LocalDate joinDate; 91 | 92 | private String maritalStatus; 93 | 94 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 95 | private List creditCards; 96 | 97 | private String userAgent; 98 | 99 | public void addName(String name){ 100 | if(names==null)names = new LinkedList<>(); 101 | names.add(name); 102 | } 103 | 104 | public void addNickName(String nickname){ 105 | if(nicknames==null)nicknames = new LinkedList<>(); 106 | nicknames.add(nickname); 107 | } 108 | 109 | public void addCoverPhoto(URL coverphoto){ 110 | if(coverphotos==null)coverphotos = new LinkedList<>(); 111 | coverphotos.add(coverphoto); 112 | } 113 | 114 | public void addProfilePicture(URL profilePicture){ 115 | if(profilePictures==null)profilePictures = new LinkedList<>(); 116 | profilePictures.add(profilePicture); 117 | } 118 | 119 | public void addAddress(Address address){ 120 | if(addresses==null)addresses = new LinkedList<>(); 121 | addresses.add(address); 122 | } 123 | 124 | public void addEmailAddress(String emailAddress){ 125 | if(emailAddresses==null)emailAddresses = new LinkedList<>(); 126 | emailAddresses.add(emailAddress); 127 | } 128 | 129 | public void addPhoneNumber(Phone phoneNumber){ 130 | if(phoneNumbers==null)phoneNumbers = new LinkedList<>(); 131 | phoneNumbers.add(phoneNumber); 132 | } 133 | 134 | public void addImClient(ImClient imClient){ 135 | if(imClients==null)imClients = new LinkedList<>(); 136 | imClients.add(imClient); 137 | } 138 | 139 | public void addSocialMedia(SocialMedia socialMedia){ 140 | if(socialMedias==null)socialMedias = new LinkedList<>(); 141 | socialMedias.add(socialMedia); 142 | } 143 | 144 | public void addTagline(String tagline){ 145 | if(taglines==null)taglines = new LinkedList<>(); 146 | taglines.add(tagline); 147 | } 148 | 149 | public void addInterest(String interest){ 150 | if(interests==null)interests = new LinkedList<>(); 151 | interests.add(interest); 152 | } 153 | 154 | public void addSkill(String skill){ 155 | if(skills==null)skills = new LinkedList<>(); 156 | skills.add(skill); 157 | } 158 | 159 | public void addRelationship(Relation relation){ 160 | if(relations==null)relations = new LinkedList<>(); 161 | relations.add(relation); 162 | } 163 | 164 | public void addCreditCard(CreditCard card){ 165 | if(creditCards==null)creditCards = new LinkedList<>(); 166 | creditCards.add(card); 167 | } 168 | 169 | public Long getId() { 170 | return id; 171 | } 172 | 173 | public void setId(Long id) { 174 | this.id = id; 175 | } 176 | 177 | public String getLocale() { 178 | return locale; 179 | } 180 | 181 | public void setLocale(String locale) { 182 | this.locale = locale; 183 | } 184 | 185 | public String getTitle() { 186 | return title; 187 | } 188 | 189 | public void setTitle(String title) { 190 | this.title = title; 191 | } 192 | 193 | public List getNames() { 194 | return names; 195 | } 196 | 197 | public void setNames(List names) { 198 | this.names = names; 199 | } 200 | 201 | public List getNicknames() { 202 | return nicknames; 203 | } 204 | 205 | public void setNicknames(List nicknames) { 206 | this.nicknames = nicknames; 207 | } 208 | 209 | public String getSurname() { 210 | return surname; 211 | } 212 | 213 | public void setSurname(String surname) { 214 | this.surname = surname; 215 | } 216 | 217 | public String getUsername() { 218 | return username; 219 | } 220 | 221 | public void setUsername(String username) { 222 | this.username = username; 223 | } 224 | 225 | public String getIdNumber() { 226 | return idNumber; 227 | } 228 | 229 | public void setIdNumber(String idNumber) { 230 | this.idNumber = idNumber; 231 | } 232 | 233 | public List getCoverphotos() { 234 | return coverphotos; 235 | } 236 | 237 | public void setCoverphotos(List coverphotos) { 238 | this.coverphotos = coverphotos; 239 | } 240 | 241 | public List getProfilePictures() { 242 | return profilePictures; 243 | } 244 | 245 | public void setProfilePictures(List profilePictures) { 246 | this.profilePictures = profilePictures; 247 | } 248 | 249 | public Gender getGender() { 250 | return gender; 251 | } 252 | 253 | public void setGender(Gender gender) { 254 | this.gender = gender; 255 | } 256 | 257 | public LocalDate getBirthDate() { 258 | return birthDate; 259 | } 260 | 261 | public void setBirthDate(LocalDate birthDate) { 262 | this.birthDate = birthDate; 263 | } 264 | 265 | public String getFavColor() { 266 | return favColor; 267 | } 268 | 269 | public void setFavColor(String favColor) { 270 | this.favColor = favColor; 271 | } 272 | 273 | public List
getAddresses() { 274 | return addresses; 275 | } 276 | 277 | public void setAddresses(List
addresses) { 278 | this.addresses = addresses; 279 | } 280 | 281 | public List getEmailAddresses() { 282 | return emailAddresses; 283 | } 284 | 285 | public void setEmailAddresses(List emailAddresses) { 286 | this.emailAddresses = emailAddresses; 287 | } 288 | 289 | public List getPhoneNumbers() { 290 | return phoneNumbers; 291 | } 292 | 293 | public void setPhoneNumbers(List phoneNumbers) { 294 | this.phoneNumbers = phoneNumbers; 295 | } 296 | 297 | public List getImClients() { 298 | return imClients; 299 | } 300 | 301 | public void setImClients(List imClients) { 302 | this.imClients = imClients; 303 | } 304 | 305 | public List getSocialMedias() { 306 | return socialMedias; 307 | } 308 | 309 | public void setSocialMedias(List socialMedias) { 310 | this.socialMedias = socialMedias; 311 | } 312 | 313 | public URL getWebsite() { 314 | return website; 315 | } 316 | 317 | public void setWebsite(URL website) { 318 | this.website = website; 319 | } 320 | 321 | public List getTaglines() { 322 | return taglines; 323 | } 324 | 325 | public void setTaglines(List taglines) { 326 | this.taglines = taglines; 327 | } 328 | 329 | public String getBiography() { 330 | return biography; 331 | } 332 | 333 | public void setBiography(String biography) { 334 | this.biography = biography; 335 | } 336 | 337 | public String getOrganization() { 338 | return organization; 339 | } 340 | 341 | public void setOrganization(String organization) { 342 | this.organization = organization; 343 | } 344 | 345 | public String getOccupation() { 346 | return occupation; 347 | } 348 | 349 | public void setOccupation(String occupation) { 350 | this.occupation = occupation; 351 | } 352 | 353 | public List getInterests() { 354 | return interests; 355 | } 356 | 357 | public void setInterests(List interests) { 358 | this.interests = interests; 359 | } 360 | 361 | public List getSkills() { 362 | return skills; 363 | } 364 | 365 | public void setSkills(List skills) { 366 | this.skills = skills; 367 | } 368 | 369 | public List getRelations() { 370 | return relations; 371 | } 372 | 373 | public void setRelations(List relations) { 374 | this.relations = relations; 375 | } 376 | 377 | public LocalDate getJoinDate() { 378 | return joinDate; 379 | } 380 | 381 | public void setJoinDate(LocalDate joinDate) { 382 | this.joinDate = joinDate; 383 | } 384 | 385 | public String getMaritalStatus() { 386 | return maritalStatus; 387 | } 388 | 389 | public void setMaritalStatus(String maritalStatus) { 390 | this.maritalStatus = maritalStatus; 391 | } 392 | 393 | public List getCreditCards() { 394 | return creditCards; 395 | } 396 | 397 | public void setCreditCards(List creditCards) { 398 | this.creditCards = creditCards; 399 | } 400 | 401 | public String getUserAgent() { 402 | return userAgent; 403 | } 404 | 405 | public void setUserAgent(String userAgent) { 406 | this.userAgent = userAgent; 407 | } 408 | } -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Phone.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import javax.json.bind.annotation.JsonbTransient; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | 9 | @Entity 10 | public class Phone { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.SEQUENCE) 14 | @JsonbTransient 15 | private Integer id; 16 | 17 | private String type; 18 | private String number; 19 | 20 | public Integer getId() { 21 | return id; 22 | } 23 | 24 | public void setId(Integer id) { 25 | this.id = id; 26 | } 27 | 28 | public String getType() { 29 | return type; 30 | } 31 | 32 | public void setType(String type) { 33 | this.type = type; 34 | } 35 | 36 | public String getNumber() { 37 | return number; 38 | } 39 | 40 | public void setNumber(String number) { 41 | this.number = number; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Relation.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import javax.json.bind.annotation.JsonbTransient; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | 9 | @Entity 10 | public class Relation { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.SEQUENCE) 14 | @JsonbTransient 15 | private Integer id; 16 | 17 | private RelationType relationType; 18 | private String personURI; 19 | 20 | public Integer getId() { 21 | return id; 22 | } 23 | 24 | public void setId(Integer id) { 25 | this.id = id; 26 | } 27 | 28 | public RelationType getRelationType() { 29 | return relationType; 30 | } 31 | 32 | public void setRelationType(RelationType relationType) { 33 | this.relationType = relationType; 34 | } 35 | 36 | public String getPersonURI() { 37 | return personURI; 38 | } 39 | 40 | public void setPersonURI(String personURI) { 41 | this.personURI = personURI; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/RelationType.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum RelationType { 4 | Spouse, 5 | Husband, 6 | Wife, 7 | Parent, 8 | Father, 9 | Mother, 10 | StepFather, 11 | StepMother, 12 | LegalGuardian, 13 | Child, 14 | Son, 15 | Daughter, 16 | StepSon, 17 | StepDaughter, 18 | Sibling, 19 | Brother, 20 | Sister, 21 | Stepfamily, 22 | Grandparent, 23 | Grandfather, 24 | Grandmother, 25 | Grandson, 26 | Granddaughter, 27 | Uncle, 28 | Aunt, 29 | Cousin, 30 | Nephew, 31 | Niece, 32 | FamilyInLaw, 33 | FatherInLaw, 34 | MotherInLaw, 35 | BrotherInLaw, 36 | SisterInLaw 37 | } -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Score.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public class Score implements Measurable { 4 | 5 | private String id; 6 | private ScoreType name; 7 | private Long value; 8 | 9 | public String getId() { 10 | return id; 11 | } 12 | 13 | public void setId(String id) { 14 | this.id = id; 15 | } 16 | 17 | public ScoreType getName() { 18 | return name; 19 | } 20 | 21 | public void setName(ScoreType name) { 22 | this.name = name; 23 | } 24 | 25 | @Override 26 | public Long getValue() { 27 | return value; 28 | } 29 | 30 | public void setValue(Long value) { 31 | this.value = value; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/ScoreType.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum ScoreType { 4 | Driving,Fitness,Activity,Financial 5 | } 6 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/SocialMedia.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import javax.json.bind.annotation.JsonbTransient; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | 9 | @Entity 10 | public class SocialMedia { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.SEQUENCE) 14 | @JsonbTransient 15 | private Integer id; 16 | 17 | private String name; 18 | private String username; 19 | 20 | public Integer getId() { 21 | return id; 22 | } 23 | 24 | public void setId(Integer id) { 25 | this.id = id; 26 | } 27 | 28 | public String getName() { 29 | return name; 30 | } 31 | 32 | public void setName(String name) { 33 | this.name = name; 34 | } 35 | 36 | public String getUsername() { 37 | return username; 38 | } 39 | 40 | public void setUsername(String username) { 41 | this.username = username; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/model/Weight.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public class Weight implements Measurable { 4 | private Long value; 5 | 6 | @Override 7 | public Long getValue() { 8 | return value; 9 | } 10 | 11 | public void setValue(Long value) { 12 | this.value = value; 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/rest/PersonRestApi.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.rest; 2 | 3 | import com.github.phillipkruger.user.model.Person; 4 | import com.github.phillipkruger.user.service.PersonService; 5 | 6 | import java.util.List; 7 | import javax.enterprise.context.ApplicationScoped; 8 | import javax.inject.Inject; 9 | import javax.ws.rs.Consumes; 10 | import javax.ws.rs.GET; 11 | import javax.ws.rs.Path; 12 | import javax.ws.rs.PathParam; 13 | import javax.ws.rs.Produces; 14 | import javax.ws.rs.core.MediaType; 15 | import org.eclipse.microprofile.openapi.annotations.Operation; 16 | import org.eclipse.microprofile.openapi.annotations.tags.Tag; 17 | 18 | @ApplicationScoped 19 | @Path("/person") 20 | @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) 21 | @Tag(name = "Person service",description = "Person Services") 22 | public class PersonRestApi { 23 | 24 | @Inject 25 | PersonService personService; 26 | 27 | @GET 28 | @Path("/{id}") 29 | @Operation(description = "Get a person using the person's Id") 30 | public Person getPerson(@PathParam("id") Long id){ 31 | return personService.getPerson(id); 32 | } 33 | 34 | @GET 35 | @Operation(description = "Get all people") 36 | public List getPeople(){ 37 | return personService.getPeople(); 38 | } 39 | } -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/rest/ScoreRestApi.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.rest; 2 | 3 | import com.github.phillipkruger.user.model.Score; 4 | import com.github.phillipkruger.user.service.ScoreService; 5 | import java.util.List; 6 | import javax.enterprise.context.ApplicationScoped; 7 | import javax.inject.Inject; 8 | import javax.ws.rs.Consumes; 9 | import javax.ws.rs.GET; 10 | import javax.ws.rs.Path; 11 | import javax.ws.rs.PathParam; 12 | import javax.ws.rs.Produces; 13 | import javax.ws.rs.core.MediaType; 14 | import org.eclipse.microprofile.openapi.annotations.Operation; 15 | import org.eclipse.microprofile.openapi.annotations.tags.Tag; 16 | 17 | @ApplicationScoped 18 | @Path("/score") 19 | @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) 20 | @Tag(name = "Score service",description = "Score Services") 21 | public class ScoreRestApi { 22 | 23 | @Inject 24 | ScoreService scoreService; 25 | 26 | @GET 27 | @Path("/{idNumber}") 28 | @Operation(description = "Get a person's scores using the person's Id Number") 29 | public List getScores(@PathParam("idNumber") String idNumber){ 30 | return scoreService.getScores(idNumber); 31 | } 32 | } -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/service/PersonService.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.service; 2 | 3 | import com.github.phillipkruger.user.model.Person; 4 | import io.smallrye.mutiny.Multi; 5 | import io.smallrye.mutiny.operators.multi.processors.BroadcastProcessor; 6 | import java.util.List; 7 | import javax.enterprise.context.ApplicationScoped; 8 | import javax.persistence.EntityManager; 9 | import javax.persistence.PersistenceContext; 10 | import javax.transaction.Transactional; 11 | 12 | @ApplicationScoped 13 | public class PersonService { 14 | 15 | BroadcastProcessor processor = BroadcastProcessor.create(); 16 | 17 | @PersistenceContext(name="PersonDS") 18 | EntityManager em; 19 | 20 | public Person getPerson(Long id){ 21 | System.out.println("======= Getting person [" + id +"] ======="); 22 | return em.find(Person.class,id); 23 | } 24 | 25 | public Person getPerson(Person person) { 26 | System.out.println("======= Getting person [" + person +"] ======="); 27 | return em.find(Person.class, person); 28 | } 29 | 30 | public List getPeople(){ 31 | return (List)em.createQuery("SELECT p FROM Person p",Person.class) 32 | .getResultList(); 33 | } 34 | 35 | public List getPeopleWithSurname(String surname) { 36 | return (List)em.createQuery("SELECT p FROM Person p WHERE p.surname=:surname",Person.class) 37 | .setParameter("surname", surname) 38 | .getResultList(); 39 | } 40 | 41 | @Transactional 42 | public Person updateOrCreate(Person person) { 43 | if(person.getId()==null){ 44 | em.persist(person); 45 | processor.onNext(person); 46 | return person; 47 | }else{ 48 | Person existing = em.find(Person.class, person.getId()); 49 | if(existing!=null){ 50 | processor.onNext(person); 51 | return em.merge(person); 52 | }else { 53 | em.persist(person); 54 | processor.onNext(person); 55 | return person; 56 | } 57 | } 58 | } 59 | 60 | @Transactional 61 | public Person delete(Long id) { 62 | Person p = em.find(Person.class,id); 63 | 64 | if(p!=null){ 65 | em.remove(p); 66 | } 67 | return p; 68 | } 69 | 70 | public Multi personListener(){ 71 | return processor; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/user/service/ScoreService.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.service; 2 | 3 | import com.github.phillipkruger.user.model.Score; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Stack; 12 | import javax.annotation.PostConstruct; 13 | import javax.enterprise.context.ApplicationScoped; 14 | import javax.json.bind.Jsonb; 15 | import javax.json.bind.JsonbBuilder; 16 | import javax.json.bind.JsonbConfig; 17 | 18 | @ApplicationScoped 19 | public class ScoreService { 20 | 21 | private final Map> scoreDatabase = new HashMap<>(); 22 | 23 | public List getScores(String idNumber){ 24 | System.err.println("======= Getting scores [" + idNumber + "] ======="); 25 | return scoreDatabase.get(idNumber); 26 | } 27 | 28 | public List> getScores(List idNumbers){ 29 | System.err.println("======= Getting scores " + idNumbers + " ======="); 30 | List> allscores = new ArrayList<>(); 31 | for(String idNumber:idNumbers){ 32 | allscores.add(scoreDatabase.get(idNumber)); 33 | } 34 | return allscores; 35 | } 36 | 37 | @PostConstruct 38 | void init(){ 39 | try(InputStream jsonStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("score.json")){ 40 | if(jsonStream!=null){ 41 | List> loaded = JSONB.fromJson(jsonStream, new ArrayList>(){}.getClass().getGenericSuperclass()); 42 | for(List s:loaded){ 43 | scoreDatabase.put(ids.pop(), s); 44 | } 45 | } 46 | } catch (IOException ex) { 47 | ex.printStackTrace(); 48 | } 49 | } 50 | 51 | private static final Jsonb JSONB = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); 52 | 53 | private static Stack ids = new Stack<>(); 54 | static{ 55 | ids.addAll(Arrays.asList(new String[]{"797-95-4822","373-95-3047","097-87-6795","347-01-8880","733-86-4423","560-99-2165","091-07-5401","539-70-2014","029-18-5986","287-58-0690"})); 56 | } 57 | } -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/zzz/graphql/Joke.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.zzz.graphql; 2 | 3 | 4 | public class Joke { 5 | public String question; 6 | public String answer; 7 | 8 | public static Joke questionAndAnswer(String q, String a){ 9 | Joke j = new Joke(); 10 | j.question = q; 11 | j.answer = a; 12 | return j; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /quarkus-example/src/main/java/com/github/phillipkruger/zzz/graphql/JokeOfTheDayApi.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.zzz.graphql; 2 | 3 | import java.util.List; 4 | import java.util.Random; 5 | import org.eclipse.microprofile.graphql.GraphQLApi; 6 | import org.eclipse.microprofile.graphql.Query; 7 | 8 | @GraphQLApi 9 | public class JokeOfTheDayApi { 10 | 11 | Random r = new Random(); 12 | 13 | @Query 14 | public Joke randomJoke(){ 15 | return jokes.get(r.nextInt(jokes.size())); 16 | } 17 | 18 | 19 | private static List jokes = List.of(Joke.questionAndAnswer("What do you call a fish without eyes?","Fsh"), 20 | Joke.questionAndAnswer("What do you call an alligator detective?","An investi-gator"), 21 | Joke.questionAndAnswer("Why did the scarecrow win an award?","Because he was outstanding in his field"), 22 | Joke.questionAndAnswer("Why shouldn’t you write with a broken pencil?","Because it’s pointless"), 23 | Joke.questionAndAnswer("What did the policeman say to his bellybutton?","You’re under a vest"), 24 | Joke.questionAndAnswer("What do you call a fake noodle?","An impasta!"), 25 | Joke.questionAndAnswer("What do you call something that runs but never gets anywhere?","A refrigerator."), 26 | Joke.questionAndAnswer("What do you call something that’s easy to get into, but hard to get out of?","Trouble."), 27 | Joke.questionAndAnswer("What do you do to get a robot mad?","Push all of its buttons."), 28 | Joke.questionAndAnswer("What do you call a joke without a punchline?","Silence."), 29 | Joke.questionAndAnswer("What do you call a horse that can’t lose a race?","A sherbet."), 30 | Joke.questionAndAnswer("What do you call the security guards outside the Samsung factory?","The Guardians of the Galaxy."), 31 | Joke.questionAndAnswer("What do you call someone that saw an iPhone being stolen?","An iWitness."), 32 | Joke.questionAndAnswer("What do you call someone who never passes gas in public?","A private tutor."), 33 | Joke.questionAndAnswer("What do you call it when a prisoner takes his own mugshot?","A cellfie."), 34 | Joke.questionAndAnswer("What do you call blackbirds that stick together?","Vel-crows."), 35 | Joke.questionAndAnswer("What do you call the daughter of a hamburger?","Patty."), 36 | Joke.questionAndAnswer("What do you call a tiny mother?","A minimum!"), 37 | Joke.questionAndAnswer("What do you call a policeman in bed?","An undercover cop."), 38 | Joke.questionAndAnswer("What do you call a soldier who survived mustard gas and pepper spray?","A seasoned veteran."), 39 | Joke.questionAndAnswer("What do you call a funny mountain?","Hill-arious."), 40 | Joke.questionAndAnswer("What do you call a boomerang that doesn’t come back?","A stick."), 41 | Joke.questionAndAnswer("What do you call a factory that manufactures products that are just OK?","A satisfactory."), 42 | Joke.questionAndAnswer("What do you call a bagel that can fly?","A plain bagel."), 43 | Joke.questionAndAnswer("What do you call a person with a briefcase in a tree?","Branch manager."), 44 | Joke.questionAndAnswer("What do you call someone who cleans the bottom of the ocean?","A mer-maid."), 45 | Joke.questionAndAnswer("What do you call something that goes up when the rain comes down?","An umbrella."), 46 | Joke.questionAndAnswer("What do you call a doctor who fixes websites?","A URL-ologist.") 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /quarkus-example/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /quarkus-example/src/main/resources/META-INF/branding_bak2/smallrye-graphql-ui-graphiql.css: -------------------------------------------------------------------------------- 1 | body { 2 | height: 100%; 3 | margin: 0; 4 | width: 100%; 5 | overflow: hidden; 6 | } 7 | #graphiql { 8 | height: 100vh; 9 | } 10 | 11 | .graphiql-container .topBar { 12 | background: #151515; 13 | } 14 | .graphiql-container .execute-button{ 15 | box-shadow:unset; 16 | } 17 | -------------------------------------------------------------------------------- /quarkus-example/src/main/resources/META-INF/branding_bak2/smallrye-graphql-ui-graphiql.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/quarkus-example/src/main/resources/META-INF/branding_bak2/smallrye-graphql-ui-graphiql.ico -------------------------------------------------------------------------------- /quarkus-example/src/main/resources/META-INF/branding_bak2/smallrye-open-api-ui.css: -------------------------------------------------------------------------------- 1 | html{ 2 | box-sizing: border-box; 3 | overflow: -moz-scrollbars-vertical; 4 | overflow-y: scroll; 5 | } 6 | 7 | *, 8 | *:before, 9 | *:after 10 | { 11 | box-sizing: inherit; 12 | } 13 | 14 | body{ 15 | margin:0; 16 | background: #fafafa; 17 | } 18 | 19 | .swagger-ui .topbar { 20 | background-color: #151515; 21 | } 22 | -------------------------------------------------------------------------------- /quarkus-example/src/main/resources/META-INF/branding_bak2/smallrye-open-api-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/quarkus-example/src/main/resources/META-INF/branding_bak2/smallrye-open-api-ui.png -------------------------------------------------------------------------------- /quarkus-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.smallrye-graphql.events.enabled=true 2 | quarkus.smallrye-graphql.ui.always-include=true 3 | quarkus.smallrye-graphql.error-extension-fields=exception,classification,code,description,validationErrorType,queryPath 4 | 5 | quarkus.hibernate-orm.second-level-caching-enabled=false 6 | quarkus.hibernate-orm.log-session-metrics=true 7 | #quarkus.hibernate-orm.log.sql=true 8 | quarkus.hibernate-orm.log.format-sql=true -------------------------------------------------------------------------------- /quarkus-example/src/main/resources/score.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | { 4 | "id": "d13ba7c4-6c7d-4661-ad6d-858a1731e8fd", 5 | "name": "Driving", 6 | "value": 53 7 | }, 8 | { 9 | "id": "d2552177-1445-4f02-91a2-8865bb050610", 10 | "name": "Fitness", 11 | "value": 19 12 | }, 13 | { 14 | "id": "90443d40-abbe-4040-83dc-5e08ec452e3f", 15 | "name": "Activity", 16 | "value": 26 17 | }, 18 | { 19 | "id": "9ca4847c-2e77-43a1-9478-fa37d6b950d3", 20 | "name": "Financial", 21 | "value": 16 22 | } 23 | ], 24 | [ 25 | { 26 | "id": "81fbd922-094c-4e9f-8362-cbfcceb4b9df", 27 | "name": "Driving", 28 | "value": 57 29 | }, 30 | { 31 | "id": "c90bcccd-f900-4c5b-84eb-f5d30bb28298", 32 | "name": "Fitness", 33 | "value": 25 34 | }, 35 | { 36 | "id": "271c7683-abbf-4e14-a857-e7c3c8ff4ab0", 37 | "name": "Activity", 38 | "value": 0 39 | }, 40 | { 41 | "id": "db1683e7-c358-4e4a-b200-42a9296160d8", 42 | "name": "Financial", 43 | "value": 61 44 | } 45 | ], 46 | [ 47 | { 48 | "id": "07b1ddf0-af06-41e5-858d-0c188fed230b", 49 | "name": "Driving", 50 | "value": 48 51 | }, 52 | { 53 | "id": "acf3bf4f-cc22-4a12-b0b7-1eabd275af83", 54 | "name": "Fitness", 55 | "value": 73 56 | }, 57 | { 58 | "id": "56405c21-04a4-4c22-b2bb-7e6466019ded", 59 | "name": "Activity", 60 | "value": 62 61 | }, 62 | { 63 | "id": "3a4009e6-5513-4fe5-b391-9c8d34a67079", 64 | "name": "Financial", 65 | "value": 54 66 | } 67 | ], 68 | [ 69 | { 70 | "id": "6a3d949c-d4a5-4ad4-aac4-2847c0140a85", 71 | "name": "Driving", 72 | "value": 42 73 | }, 74 | { 75 | "id": "51ac6824-e05c-492a-bd25-145bc67d9122", 76 | "name": "Fitness", 77 | "value": 95 78 | }, 79 | { 80 | "id": "d5f3f78c-9104-48c7-9aa9-52a3eef0a896", 81 | "name": "Activity", 82 | "value": 57 83 | }, 84 | { 85 | "id": "bde2d353-c513-4e60-9fe5-39a9636d282f", 86 | "name": "Financial", 87 | "value": 44 88 | } 89 | ], 90 | [ 91 | { 92 | "id": "10a85beb-8063-4efa-9b45-74aaf5dbbf4a", 93 | "name": "Driving", 94 | "value": 15 95 | }, 96 | { 97 | "id": "9c12ba10-d231-4715-bda3-1f219caf46c0", 98 | "name": "Fitness", 99 | "value": 94 100 | }, 101 | { 102 | "id": "64abc30b-21bd-4beb-860d-a5aba69798c8", 103 | "name": "Activity", 104 | "value": 63 105 | }, 106 | { 107 | "id": "8472e4a2-c26a-4041-be37-e2c2af167862", 108 | "name": "Financial", 109 | "value": 22 110 | } 111 | ], 112 | [ 113 | { 114 | "id": "6cc43771-2b11-4b59-9aca-bcfa4d73e8f8", 115 | "name": "Driving", 116 | "value": 43 117 | }, 118 | { 119 | "id": "089a1dec-a96c-4572-86bb-2a22d5c7bbbb", 120 | "name": "Fitness", 121 | "value": 89 122 | }, 123 | { 124 | "id": "c75beb58-f7a5-4d36-bba8-d343339879dc", 125 | "name": "Activity", 126 | "value": 47 127 | }, 128 | { 129 | "id": "a125ca4f-5616-4ed4-92f8-2ae7ca646e38", 130 | "name": "Financial", 131 | "value": 12 132 | } 133 | ], 134 | [ 135 | { 136 | "id": "4f931428-8197-4738-b639-6a31e3278486", 137 | "name": "Driving", 138 | "value": 55 139 | }, 140 | { 141 | "id": "fb36ff5b-6727-46d2-a730-7b815353f690", 142 | "name": "Fitness", 143 | "value": 13 144 | }, 145 | { 146 | "id": "83ddc3bb-93c6-40e5-9a10-fc16d4068408", 147 | "name": "Activity", 148 | "value": 20 149 | }, 150 | { 151 | "id": "fbabdbec-8717-427c-b768-39eb0ef464d1", 152 | "name": "Financial", 153 | "value": 51 154 | } 155 | ], 156 | [ 157 | { 158 | "id": "da594a0b-cfd8-42dc-8997-d94041d8824a", 159 | "name": "Driving", 160 | "value": 27 161 | }, 162 | { 163 | "id": "c61df030-f193-4dbb-8c67-ca1980ad3521", 164 | "name": "Fitness", 165 | "value": 3 166 | }, 167 | { 168 | "id": "2e175db3-fd69-4004-95df-6f99fa91f210", 169 | "name": "Activity", 170 | "value": 47 171 | }, 172 | { 173 | "id": "a3124670-16eb-451d-ab89-e7dcb7979816", 174 | "name": "Financial", 175 | "value": 92 176 | } 177 | ], 178 | [ 179 | { 180 | "id": "f136f83c-f07a-4190-9c17-4ad38972c27e", 181 | "name": "Driving", 182 | "value": 31 183 | }, 184 | { 185 | "id": "2707ef06-d394-41e9-baca-9fbc899d3f20", 186 | "name": "Fitness", 187 | "value": 37 188 | }, 189 | { 190 | "id": "ac5e2b50-e710-4471-8400-54f8412ab4c1", 191 | "name": "Activity", 192 | "value": 15 193 | }, 194 | { 195 | "id": "c9a24e83-1c49-4a46-b12d-20f8a4788a16", 196 | "name": "Financial", 197 | "value": 5 198 | } 199 | ], 200 | [ 201 | { 202 | "id": "6aa6dcc1-d0cd-45a7-8b5c-d3c6cf1e5fa6", 203 | "name": "Driving", 204 | "value": 2 205 | }, 206 | { 207 | "id": "63d116aa-3091-4e0a-b492-57dd6918df9c", 208 | "name": "Fitness", 209 | "value": 68 210 | }, 211 | { 212 | "id": "019a3c99-d7c6-458e-9dc8-aacc4cb40f06", 213 | "name": "Activity", 214 | "value": 53 215 | }, 216 | { 217 | "id": "c586d351-cea5-49d4-8842-365728d7a218", 218 | "name": "Financial", 219 | "value": 24 220 | } 221 | ] 222 | ] -------------------------------------------------------------------------------- /quarkus-example/src/test/docker/Dockerfile.jvm: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the docker image run: 5 | # 6 | # mvn package 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.jvm -t quarkus/quarkus-example-jvm . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/quarkus-example-jvm 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 18 | # 19 | # Then run the container using : 20 | # 21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/quarkus-example-jvm 22 | # 23 | ### 24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 25 | 26 | ARG JAVA_PACKAGE=java-11-openjdk-headless 27 | ARG RUN_JAVA_VERSION=1.3.5 28 | 29 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' 30 | 31 | # Install java and the run-java script 32 | # Also set up permissions for user `1001` 33 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ 34 | && microdnf update \ 35 | && microdnf clean all \ 36 | && mkdir /deployments \ 37 | && chown 1001 /deployments \ 38 | && chmod "g+rwX" /deployments \ 39 | && chown 1001:root /deployments \ 40 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ 41 | && chown 1001 /deployments/run-java.sh \ 42 | && chmod 540 /deployments/run-java.sh \ 43 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security 44 | 45 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. 46 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 47 | 48 | COPY target/lib/* /deployments/lib/ 49 | COPY target/*-runner.jar /deployments/app.jar 50 | 51 | EXPOSE 8080 52 | USER 1001 53 | 54 | ENTRYPOINT [ "/deployments/run-java.sh" ] -------------------------------------------------------------------------------- /quarkus-example/src/test/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode 3 | # 4 | # Before building the docker image run: 5 | # 6 | # mvn package -Pnative -Dquarkus.native.container-build=true 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-example . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/quarkus-example 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 18 | WORKDIR /work/ 19 | COPY target/*-runner /work/application 20 | 21 | # set up permissions for user `1001` 22 | RUN chmod 775 /work /work/application \ 23 | && chown -R 1001 /work \ 24 | && chmod -R "g+rwX" /work \ 25 | && chown -R 1001:root /work 26 | 27 | EXPOSE 8080 28 | USER 1001 29 | 30 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] -------------------------------------------------------------------------------- /quarkus-example/src/test/java/com/github/phillipkruger/graphql/ExampleResourceTest.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.graphql; 2 | 3 | import io.quarkus.test.junit.QuarkusTest; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static io.restassured.RestAssured.given; 7 | import static org.hamcrest.CoreMatchers.is; 8 | 9 | @QuarkusTest 10 | public class ExampleResourceTest { 11 | 12 | //@Test 13 | public void testHelloEndpoint() { 14 | given() 15 | .when().get("/hello") 16 | .then() 17 | .statusCode(200) 18 | .body(is("hello")); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /quarkus-example/src/test/java/com/github/phillipkruger/graphql/NativeExampleResourceIT.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.graphql; 2 | 3 | import io.quarkus.test.junit.NativeImageTest; 4 | 5 | @NativeImageTest 6 | public class NativeExampleResourceIT extends ExampleResourceTest { 7 | 8 | // Execute the same tests but in native mode. 9 | } -------------------------------------------------------------------------------- /quarkus-example/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Configuration file 2 | # key = value -------------------------------------------------------------------------------- /quarkus-example/transcript.txt: -------------------------------------------------------------------------------- 1 | 2 | == Rest == 3 | 4 | - Show all (overfetch) 5 | - Show single (underfetch) 6 | 7 | == GraphQL == 8 | 9 | - Modify Query (person) 10 | - Show schema 11 | - Show that there is no score 12 | - Add Source (score) 13 | 14 | ------- BACK TO SLIDES HERE (show compare to REST) 15 | 16 | == Batch == 17 | 18 | List ids = people.stream().map(Person::getIdNumber).collect(Collectors.toList()); 19 | 20 | == Multiple requests == 21 | 22 | 23 | 24 | == Errors and partial response == 25 | 26 | 27 | ------- BACK TO SLIDES HERE 28 | 29 | == Transformation and mapping == 30 | 31 | On birthdate: @DateFormat("dd/MM/yyyy") 32 | On id: @ToScalar(Scalar.Int.class) 33 | On email @ToScalar(Scalar.String.class) 34 | 35 | == Mutation == 36 | 37 | @Mutation 38 | public Person updatePerson(Person person){ 39 | return personService.updateOrCreate(person); 40 | } 41 | 42 | @Mutation 43 | public Person deletePerson(Long id){ 44 | return personService.delete(id); 45 | } 46 | 47 | mutation CreatePerson{ 48 | updatePerson(person : 49 | { 50 | names: "Phillip" 51 | } 52 | ){ 53 | id 54 | names 55 | surname 56 | profilePictures 57 | website 58 | } 59 | } 60 | 61 | mutation UpdatePerson{ 62 | updatePerson(person : 63 | { 64 | id: 11, 65 | names:"Phillip", 66 | surname: "Kruger", 67 | profilePictures: [ 68 | "https://pbs.twimg.com/profile_images/1311017429242437636/CbUoiAeP_400x400.jpg" 69 | ], 70 | website: "http://www.phillip-kruger.com" 71 | }){ 72 | id 73 | names 74 | surname 75 | profilePictures 76 | website 77 | } 78 | } 79 | 80 | == Subscription == 81 | 82 | @Subscription 83 | public Multi personAdded(){ 84 | return personService.personListener(); 85 | } 86 | 87 | subscription PersonAdded { 88 | personAdded { 89 | names 90 | } 91 | } 92 | 93 | == Security == 94 | 95 | @RolesAllowed("user") 96 | 97 | { 98 | "authorization": "Bearer " 99 | } 100 | 101 | == Client == -------------------------------------------------------------------------------- /tracing1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/tracing1.png -------------------------------------------------------------------------------- /tracing2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/tracing2.png -------------------------------------------------------------------------------- /wildfly-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.github.phillip-kruger.graphql 7 | graphql-example-parent 8 | 1.0.0-SNAPSHOT 9 | ../ 10 | 11 | 12 | wildfly-example 13 | 14 | GraphQL Demo :: Wildfly Example 15 | 16 | 17 | 18 | 19 | org.eclipse.microprofile 20 | microprofile 21 | pom 22 | provided 23 | 24 | 25 | 26 | 27 | io.smallrye 28 | smallrye-graphql-servlet 29 | ${smallrye-graphql.version} 30 | 31 | 32 | 33 | 34 | io.smallrye 35 | smallrye-graphql-ui-graphiql 36 | ${smallrye-graphql.version} 37 | runtime 38 | 39 | 40 | 41 | 42 | io.smallrye 43 | smallrye-open-api-ui 44 | 2.0.15 45 | runtime 46 | 47 | 48 | 49 | 50 | jakarta.persistence 51 | jakarta.persistence-api 52 | 2.2.3 53 | provided 54 | 55 | 56 | jakarta.transaction 57 | jakarta.transaction-api 58 | 1.3.3 59 | provided 60 | 61 | 62 | 63 | 64 | commons-beanutils 65 | commons-beanutils 66 | 1.9.4 67 | 68 | 69 | 70 | 71 | com.h2database 72 | h2 73 | 1.4.200 74 | 75 | 76 | 77 | 78 | ${project.artifactId} 79 | 80 | 81 | 82 | 83 | 98 | 99 | 100 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | jdk11plus 131 | 132 | [11,) 133 | 134 | 135 | --add-modules java.se 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/graphql/ProfileGraphQLApi.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.graphql; 2 | 3 | import com.github.phillipkruger.user.model.Person; 4 | import com.github.phillipkruger.user.model.Score; 5 | import com.github.phillipkruger.user.service.PersonService; 6 | import com.github.phillipkruger.user.service.ScoreService; 7 | import graphql.GraphQL; 8 | import graphql.schema.GraphQLSchema; 9 | import java.util.List; 10 | import javax.enterprise.event.Observes; 11 | import javax.inject.Inject; 12 | import org.eclipse.microprofile.graphql.DefaultValue; 13 | import org.eclipse.microprofile.graphql.Name; 14 | import org.eclipse.microprofile.graphql.GraphQLApi; 15 | import org.eclipse.microprofile.graphql.Mutation; 16 | import org.eclipse.microprofile.graphql.Query; 17 | import org.eclipse.microprofile.graphql.Source; 18 | 19 | @GraphQLApi 20 | public class ProfileGraphQLApi { 21 | 22 | @Inject 23 | private PersonService personService; 24 | 25 | @Inject 26 | private ScoreService scoreService; 27 | 28 | // Queries 29 | 30 | @Query("person") 31 | public Person getPerson(@Name("personId") int personId){ 32 | return personService.getPerson(personId); 33 | } 34 | 35 | public List getScores(@Source Person person) { 36 | return scoreService.getScores(person.getIdNumber()); 37 | } 38 | 39 | public List getScores2(@Source Person person) throws ScoresNotAvailableException { 40 | throw new ScoresNotAvailableException("Scores for person [" + person.getIdNumber() + "] is not available"); 41 | } 42 | 43 | // List Queries 44 | 45 | @Query 46 | public List getPeople(){ 47 | return personService.getPeople(); 48 | } 49 | 50 | // Mutations 51 | 52 | @Mutation 53 | public Person updatePerson(Person person){ 54 | return personService.updatePerson(person); 55 | } 56 | 57 | @Mutation 58 | public Person deletePerson(int id){ 59 | return personService.deletePerson(id); 60 | } 61 | 62 | // Default values 63 | @Query 64 | public List getPersonsWithSurname( 65 | @DefaultValue("Kruger") String surname) { 66 | 67 | return personService.getPeopleWithSurname(surname); 68 | } 69 | 70 | 71 | public GraphQLSchema.Builder leakyAbstraction(@Observes GraphQLSchema.Builder builder) { 72 | System.err.println(">>>>>>> Here we leak while building the schema"); 73 | // Do what you have to do 74 | return builder; 75 | } 76 | 77 | public GraphQL.Builder leakyAbstraction(@Observes GraphQL.Builder builder) { 78 | System.err.println(">>>>>>> Here we leak while building graphQL"); 79 | // Do what you have to do 80 | return builder; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/graphql/ScoresNotAvailableException.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.graphql; 2 | 3 | public class ScoresNotAvailableException extends Exception { 4 | 5 | public ScoresNotAvailableException() { 6 | } 7 | 8 | public ScoresNotAvailableException(String string) { 9 | super(string); 10 | } 11 | 12 | public ScoresNotAvailableException(String string, Throwable thrwbl) { 13 | super(string, thrwbl); 14 | } 15 | 16 | public ScoresNotAvailableException(Throwable thrwbl) { 17 | super(thrwbl); 18 | } 19 | 20 | public ScoresNotAvailableException(String string, Throwable thrwbl, boolean bln, boolean bln1) { 21 | super(string, thrwbl, bln, bln1); 22 | } 23 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Action.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum Action { 4 | Steps,Gym,Drive,Save,CheckUp 5 | } 6 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Address.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.ElementCollection; 6 | import javax.persistence.Entity; 7 | import javax.persistence.FetchType; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.GenerationType; 10 | import javax.persistence.Id; 11 | import javax.persistence.OrderColumn; 12 | 13 | @Entity 14 | public class Address implements Serializable { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.AUTO) 18 | @JsonbTransient 19 | private Integer id; 20 | 21 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 22 | @OrderColumn 23 | private String[] lines; 24 | private String code; 25 | 26 | public Integer getId() { 27 | return id; 28 | } 29 | 30 | public void setId(Integer id) { 31 | this.id = id; 32 | } 33 | 34 | public String[] getLines() { 35 | return lines; 36 | } 37 | 38 | public void setLines(String[] lines) { 39 | this.lines = lines; 40 | } 41 | 42 | public String getCode() { 43 | return code; 44 | } 45 | 46 | public void setCode(String code) { 47 | this.code = code; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Age.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public class Age implements Measurable { 4 | private Long value; 5 | 6 | @Override 7 | public Long getValue() { 8 | return value; 9 | } 10 | 11 | public void setValue(Long value) { 12 | this.value = value; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/CreditCard.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | 10 | @Entity 11 | public class CreditCard implements Serializable { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.AUTO) 15 | @JsonbTransient 16 | private Integer id; 17 | 18 | private String expiry; 19 | private String number; 20 | private String type; 21 | 22 | public Integer getId() { 23 | return id; 24 | } 25 | 26 | public void setId(Integer id) { 27 | this.id = id; 28 | } 29 | 30 | public String getExpiry() { 31 | return expiry; 32 | } 33 | 34 | public void setExpiry(String expiry) { 35 | this.expiry = expiry; 36 | } 37 | 38 | public String getNumber() { 39 | return number; 40 | } 41 | 42 | public void setNumber(String number) { 43 | this.number = number; 44 | } 45 | 46 | public String getType() { 47 | return type; 48 | } 49 | 50 | public void setType(String type) { 51 | this.type = type; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Event.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.math.BigDecimal; 4 | import java.time.LocalDateTime; 5 | import javax.json.bind.annotation.JsonbDateFormat; 6 | 7 | public class Event { 8 | 9 | private Action action; 10 | private BigDecimal value; 11 | private LocalDateTime dateTime; 12 | @JsonbDateFormat("dd MMM yyyy 'at' HH:MM") 13 | private LocalDateTime when; 14 | 15 | public Action getAction() { 16 | return action; 17 | } 18 | 19 | public void setAction(Action action) { 20 | this.action = action; 21 | } 22 | 23 | public BigDecimal getValue() { 24 | return value; 25 | } 26 | 27 | public void setValue(BigDecimal value) { 28 | this.value = value; 29 | } 30 | 31 | public LocalDateTime getDateTime() { 32 | return dateTime; 33 | } 34 | 35 | public void setDateTime(LocalDateTime dateTime) { 36 | this.dateTime = dateTime; 37 | } 38 | 39 | public LocalDateTime getWhen() { 40 | return when; 41 | } 42 | 43 | public void setWhen(LocalDateTime when) { 44 | this.when = when; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Gender.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum Gender { 4 | Male,Female 5 | } 6 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/ImClient.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | 10 | @Entity 11 | public class ImClient implements Serializable { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.AUTO) 15 | @JsonbTransient 16 | private Integer id; 17 | 18 | private String im; 19 | private String identifier; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getIm() { 30 | return im; 31 | } 32 | 33 | public void setIm(String im) { 34 | this.im = im; 35 | } 36 | 37 | public String getIdentifier() { 38 | return identifier; 39 | } 40 | 41 | public void setIdentifier(String identifier) { 42 | this.identifier = identifier; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Measurable.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | /** 4 | * Something that can be measured 5 | * @author Phillip Kruger (phillip.kruger@redhat.com) 6 | */ 7 | public interface Measurable { 8 | public Long getValue(); 9 | } 10 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Person.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import java.net.URL; 5 | import java.time.LocalDate; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import javax.json.bind.annotation.JsonbDateFormat; 9 | import javax.persistence.CascadeType; 10 | import javax.persistence.ElementCollection; 11 | import javax.persistence.Entity; 12 | import javax.persistence.FetchType; 13 | import javax.persistence.GeneratedValue; 14 | import javax.persistence.GenerationType; 15 | import javax.persistence.Id; 16 | import javax.persistence.OneToMany; 17 | 18 | @Entity 19 | public class Person implements Serializable { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.AUTO) 23 | private Integer id; 24 | 25 | private String locale; 26 | 27 | private String title; 28 | 29 | @ElementCollection(targetClass=String.class) 30 | private List names; 31 | 32 | @ElementCollection(targetClass=String.class) 33 | private List nicknames; 34 | 35 | private String surname; 36 | 37 | private String username; 38 | 39 | private String idNumber; 40 | 41 | @ElementCollection(targetClass=URL.class) 42 | private List coverphotos; 43 | 44 | @ElementCollection(targetClass=URL.class) 45 | private List profilePictures; 46 | 47 | private Gender gender; 48 | 49 | @JsonbDateFormat("dd/MM/yyyy") 50 | private LocalDate birthDate; 51 | 52 | private String favColor; 53 | 54 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 55 | private List
addresses; 56 | 57 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 58 | private List emailAddresses; 59 | 60 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 61 | private List phoneNumbers; 62 | 63 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 64 | private List imClients; 65 | 66 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 67 | private List socialMedias; 68 | 69 | private URL website; 70 | 71 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 72 | private List taglines; 73 | 74 | private String biography; 75 | 76 | private String organization; 77 | 78 | private String occupation; 79 | 80 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 81 | private List interests; 82 | 83 | @ElementCollection(fetch = FetchType.LAZY,targetClass=String.class) 84 | private List skills; 85 | 86 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 87 | private List relations; 88 | 89 | @JsonbDateFormat("dd/MM/yyyy") 90 | private LocalDate joinDate; 91 | 92 | private String maritalStatus; 93 | 94 | @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 95 | private List creditCards; 96 | 97 | private String userAgent; 98 | 99 | public void addName(String name){ 100 | if(names==null)names = new LinkedList<>(); 101 | names.add(name); 102 | } 103 | 104 | public void addNickName(String nickname){ 105 | if(nicknames==null)nicknames = new LinkedList<>(); 106 | nicknames.add(nickname); 107 | } 108 | 109 | public void addCoverPhoto(URL coverphoto){ 110 | if(coverphotos==null)coverphotos = new LinkedList<>(); 111 | coverphotos.add(coverphoto); 112 | } 113 | 114 | public void addProfilePicture(URL profilePicture){ 115 | if(profilePictures==null)profilePictures = new LinkedList<>(); 116 | profilePictures.add(profilePicture); 117 | } 118 | 119 | public void addAddress(Address address){ 120 | if(addresses==null)addresses = new LinkedList<>(); 121 | addresses.add(address); 122 | } 123 | 124 | public void addEmailAddress(String emailAddress){ 125 | if(emailAddresses==null)emailAddresses = new LinkedList<>(); 126 | emailAddresses.add(emailAddress); 127 | } 128 | 129 | public void addPhoneNumber(Phone phoneNumber){ 130 | if(phoneNumbers==null)phoneNumbers = new LinkedList<>(); 131 | phoneNumbers.add(phoneNumber); 132 | } 133 | 134 | public void addImClient(ImClient imClient){ 135 | if(imClients==null)imClients = new LinkedList<>(); 136 | imClients.add(imClient); 137 | } 138 | 139 | public void addSocialMedia(SocialMedia socialMedia){ 140 | if(socialMedias==null)socialMedias = new LinkedList<>(); 141 | socialMedias.add(socialMedia); 142 | } 143 | 144 | public void addTagline(String tagline){ 145 | if(taglines==null)taglines = new LinkedList<>(); 146 | taglines.add(tagline); 147 | } 148 | 149 | public void addInterest(String interest){ 150 | if(interests==null)interests = new LinkedList<>(); 151 | interests.add(interest); 152 | } 153 | 154 | public void addSkill(String skill){ 155 | if(skills==null)skills = new LinkedList<>(); 156 | skills.add(skill); 157 | } 158 | 159 | public void addRelationship(Relation relation){ 160 | if(relations==null)relations = new LinkedList<>(); 161 | relations.add(relation); 162 | } 163 | 164 | public void addCreditCard(CreditCard card){ 165 | if(creditCards==null)creditCards = new LinkedList<>(); 166 | creditCards.add(card); 167 | } 168 | 169 | public Integer getId() { 170 | return id; 171 | } 172 | 173 | public void setId(Integer id) { 174 | this.id = id; 175 | } 176 | 177 | public String getLocale() { 178 | return locale; 179 | } 180 | 181 | public void setLocale(String locale) { 182 | this.locale = locale; 183 | } 184 | 185 | public String getTitle() { 186 | return title; 187 | } 188 | 189 | public void setTitle(String title) { 190 | this.title = title; 191 | } 192 | 193 | public List getNames() { 194 | return names; 195 | } 196 | 197 | public void setNames(List names) { 198 | this.names = names; 199 | } 200 | 201 | public List getNicknames() { 202 | return nicknames; 203 | } 204 | 205 | public void setNicknames(List nicknames) { 206 | this.nicknames = nicknames; 207 | } 208 | 209 | public String getSurname() { 210 | return surname; 211 | } 212 | 213 | public void setSurname(String surname) { 214 | this.surname = surname; 215 | } 216 | 217 | public String getUsername() { 218 | return username; 219 | } 220 | 221 | public void setUsername(String username) { 222 | this.username = username; 223 | } 224 | 225 | public String getIdNumber() { 226 | return idNumber; 227 | } 228 | 229 | public void setIdNumber(String idNumber) { 230 | this.idNumber = idNumber; 231 | } 232 | 233 | public List getCoverphotos() { 234 | return coverphotos; 235 | } 236 | 237 | public void setCoverphotos(List coverphotos) { 238 | this.coverphotos = coverphotos; 239 | } 240 | 241 | public List getProfilePictures() { 242 | return profilePictures; 243 | } 244 | 245 | public void setProfilePictures(List profilePictures) { 246 | this.profilePictures = profilePictures; 247 | } 248 | 249 | public Gender getGender() { 250 | return gender; 251 | } 252 | 253 | public void setGender(Gender gender) { 254 | this.gender = gender; 255 | } 256 | 257 | public LocalDate getBirthDate() { 258 | return birthDate; 259 | } 260 | 261 | public void setBirthDate(LocalDate birthDate) { 262 | this.birthDate = birthDate; 263 | } 264 | 265 | public String getFavColor() { 266 | return favColor; 267 | } 268 | 269 | public void setFavColor(String favColor) { 270 | this.favColor = favColor; 271 | } 272 | 273 | public List
getAddresses() { 274 | return addresses; 275 | } 276 | 277 | public void setAddresses(List
addresses) { 278 | this.addresses = addresses; 279 | } 280 | 281 | public List getEmailAddresses() { 282 | return emailAddresses; 283 | } 284 | 285 | public void setEmailAddresses(List emailAddresses) { 286 | this.emailAddresses = emailAddresses; 287 | } 288 | 289 | public List getPhoneNumbers() { 290 | return phoneNumbers; 291 | } 292 | 293 | public void setPhoneNumbers(List phoneNumbers) { 294 | this.phoneNumbers = phoneNumbers; 295 | } 296 | 297 | public List getImClients() { 298 | return imClients; 299 | } 300 | 301 | public void setImClients(List imClients) { 302 | this.imClients = imClients; 303 | } 304 | 305 | public List getSocialMedias() { 306 | return socialMedias; 307 | } 308 | 309 | public void setSocialMedias(List socialMedias) { 310 | this.socialMedias = socialMedias; 311 | } 312 | 313 | public URL getWebsite() { 314 | return website; 315 | } 316 | 317 | public void setWebsite(URL website) { 318 | this.website = website; 319 | } 320 | 321 | public List getTaglines() { 322 | return taglines; 323 | } 324 | 325 | public void setTaglines(List taglines) { 326 | this.taglines = taglines; 327 | } 328 | 329 | public String getBiography() { 330 | return biography; 331 | } 332 | 333 | public void setBiography(String biography) { 334 | this.biography = biography; 335 | } 336 | 337 | public String getOrganization() { 338 | return organization; 339 | } 340 | 341 | public void setOrganization(String organization) { 342 | this.organization = organization; 343 | } 344 | 345 | public String getOccupation() { 346 | return occupation; 347 | } 348 | 349 | public void setOccupation(String occupation) { 350 | this.occupation = occupation; 351 | } 352 | 353 | public List getInterests() { 354 | return interests; 355 | } 356 | 357 | public void setInterests(List interests) { 358 | this.interests = interests; 359 | } 360 | 361 | public List getSkills() { 362 | return skills; 363 | } 364 | 365 | public void setSkills(List skills) { 366 | this.skills = skills; 367 | } 368 | 369 | public List getRelations() { 370 | return relations; 371 | } 372 | 373 | public void setRelations(List relations) { 374 | this.relations = relations; 375 | } 376 | 377 | public LocalDate getJoinDate() { 378 | return joinDate; 379 | } 380 | 381 | public void setJoinDate(LocalDate joinDate) { 382 | this.joinDate = joinDate; 383 | } 384 | 385 | public String getMaritalStatus() { 386 | return maritalStatus; 387 | } 388 | 389 | public void setMaritalStatus(String maritalStatus) { 390 | this.maritalStatus = maritalStatus; 391 | } 392 | 393 | public List getCreditCards() { 394 | return creditCards; 395 | } 396 | 397 | public void setCreditCards(List creditCards) { 398 | this.creditCards = creditCards; 399 | } 400 | 401 | public String getUserAgent() { 402 | return userAgent; 403 | } 404 | 405 | public void setUserAgent(String userAgent) { 406 | this.userAgent = userAgent; 407 | } 408 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Phone.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | 10 | @Entity 11 | public class Phone implements Serializable { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.AUTO) 15 | @JsonbTransient 16 | private Integer id; 17 | 18 | private String type; 19 | private String number; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getType() { 30 | return type; 31 | } 32 | 33 | public void setType(String type) { 34 | this.type = type; 35 | } 36 | 37 | public String getNumber() { 38 | return number; 39 | } 40 | 41 | public void setNumber(String number) { 42 | this.number = number; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Profile.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.util.List; 4 | 5 | public class Profile { 6 | private String id; 7 | private Person person; 8 | private List scores; 9 | 10 | public String getId() { 11 | return id; 12 | } 13 | 14 | public void setId(String id) { 15 | this.id = id; 16 | } 17 | 18 | public Person getPerson() { 19 | return person; 20 | } 21 | 22 | public void setPerson(Person person) { 23 | this.person = person; 24 | } 25 | 26 | public List getScores() { 27 | return scores; 28 | } 29 | 30 | public void setScores(List scores) { 31 | this.scores = scores; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/ProfileHateos.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public class ProfileHateos { 4 | private String id; 5 | private String person; 6 | private String scores; 7 | 8 | public String getId() { 9 | return id; 10 | } 11 | 12 | public void setId(String id) { 13 | this.id = id; 14 | } 15 | 16 | public String getPerson() { 17 | return person; 18 | } 19 | 20 | public void setPerson(String person) { 21 | this.person = person; 22 | } 23 | 24 | public String getScores() { 25 | return scores; 26 | } 27 | 28 | public void setScores(String scores) { 29 | this.scores = scores; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Relation.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | 10 | @Entity 11 | public class Relation implements Serializable { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.AUTO) 15 | @JsonbTransient 16 | private Integer id; 17 | 18 | private RelationType relationType; 19 | private String personURI; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public RelationType getRelationType() { 30 | return relationType; 31 | } 32 | 33 | public void setRelationType(RelationType relationType) { 34 | this.relationType = relationType; 35 | } 36 | 37 | public String getPersonURI() { 38 | return personURI; 39 | } 40 | 41 | public void setPersonURI(String personURI) { 42 | this.personURI = personURI; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/RelationType.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum RelationType { 4 | Spouse, 5 | Husband, 6 | Wife, 7 | Parent, 8 | Father, 9 | Mother, 10 | StepFather, 11 | StepMother, 12 | LegalGuardian, 13 | Child, 14 | Son, 15 | Daughter, 16 | StepSon, 17 | StepDaughter, 18 | Sibling, 19 | Brother, 20 | Sister, 21 | Stepfamily, 22 | Grandparent, 23 | Grandfather, 24 | Grandmother, 25 | Grandson, 26 | Granddaughter, 27 | Uncle, 28 | Aunt, 29 | Cousin, 30 | Nephew, 31 | Niece, 32 | FamilyInLaw, 33 | FatherInLaw, 34 | MotherInLaw, 35 | BrotherInLaw, 36 | SisterInLaw 37 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Score.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public class Score implements Measurable { 4 | 5 | private String id; 6 | private ScoreType name; 7 | private Long value; 8 | 9 | public String getId() { 10 | return id; 11 | } 12 | 13 | public void setId(String id) { 14 | this.id = id; 15 | } 16 | 17 | public ScoreType getName() { 18 | return name; 19 | } 20 | 21 | public void setName(ScoreType name) { 22 | this.name = name; 23 | } 24 | 25 | @Override 26 | public Long getValue() { 27 | return value; 28 | } 29 | 30 | public void setValue(Long value) { 31 | this.value = value; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/ScoreType.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public enum ScoreType { 4 | Driving,Fitness,Activity,Financial 5 | } 6 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/SocialMedia.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | import java.io.Serializable; 4 | import javax.json.bind.annotation.JsonbTransient; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | 10 | @Entity 11 | public class SocialMedia implements Serializable { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.AUTO) 15 | @JsonbTransient 16 | private Integer id; 17 | 18 | private String name; 19 | private String username; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public String getUsername() { 38 | return username; 39 | } 40 | 41 | public void setUsername(String username) { 42 | this.username = username; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/model/Weight.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.model; 2 | 3 | public class Weight implements Measurable { 4 | private Long value; 5 | 6 | @Override 7 | public Long getValue() { 8 | return value; 9 | } 10 | 11 | public void setValue(Long value) { 12 | this.value = value; 13 | } 14 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/rest/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.rest; 2 | 3 | import javax.ws.rs.ApplicationPath; 4 | import javax.ws.rs.core.Application; 5 | import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition; 6 | import org.eclipse.microprofile.openapi.annotations.info.Contact; 7 | import org.eclipse.microprofile.openapi.annotations.info.Info; 8 | import org.eclipse.microprofile.openapi.annotations.servers.Server; 9 | 10 | @ApplicationPath("/rest") 11 | @OpenAPIDefinition( 12 | info = @Info( 13 | title = "Profile Service", 14 | version = "1.0.0", 15 | contact = 16 | @Contact( 17 | name = "Phillip Kruger", 18 | email = "phillip.kruger@phillip-kruger.com", 19 | url = "http://www.phillip-kruger.com") 20 | ),servers = @Server(url = "/",description = "Localhost") 21 | ) 22 | public class ApplicationConfig extends Application { 23 | 24 | } 25 | -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/rest/PersonRestApi.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.rest; 2 | 3 | import com.github.phillipkruger.user.service.PersonService; 4 | import javax.inject.Inject; 5 | import javax.ws.rs.Consumes; 6 | import javax.ws.rs.GET; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.PathParam; 9 | import javax.ws.rs.Produces; 10 | import javax.ws.rs.core.MediaType; 11 | import javax.ws.rs.core.Response; 12 | import org.eclipse.microprofile.openapi.annotations.Operation; 13 | import org.eclipse.microprofile.openapi.annotations.tags.Tag; 14 | 15 | @Path("/person") 16 | @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) 17 | @Tag(name = "Person service",description = "Person Services") 18 | public class PersonRestApi { 19 | 20 | @Inject 21 | private PersonService personService; 22 | 23 | @GET 24 | @Path("/{id}") 25 | @Operation(description = "Get a person using the person's Id") 26 | public Response getPerson(@PathParam("id") int id){ 27 | return Response.ok(personService.getPerson(id)).build(); 28 | } 29 | 30 | @GET 31 | @Operation(description = "Get all people") 32 | public Response getPeople(){ 33 | return Response.ok(personService.getPeople()).build(); 34 | } 35 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/rest/ScoreRestApi.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.rest; 2 | 3 | import com.github.phillipkruger.user.model.Score; 4 | import com.github.phillipkruger.user.service.ScoreService; 5 | import java.util.List; 6 | import javax.inject.Inject; 7 | import javax.ws.rs.Consumes; 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.PathParam; 11 | import javax.ws.rs.Produces; 12 | import javax.ws.rs.core.MediaType; 13 | import org.eclipse.microprofile.openapi.annotations.Operation; 14 | import org.eclipse.microprofile.openapi.annotations.tags.Tag; 15 | 16 | @Path("/score") 17 | @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) 18 | @Tag(name = "Score service",description = "Score Services") 19 | public class ScoreRestApi { 20 | 21 | @Inject 22 | private ScoreService scoreService; 23 | 24 | @GET 25 | @Path("/{idNumber}") 26 | @Operation(description = "Get a person's scores using the person's Id Number") 27 | public List getScores(@PathParam("idNumber") String idNumber){ 28 | return scoreService.getScores(idNumber); 29 | } 30 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/service/PersonService.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.service; 2 | 3 | import com.github.phillipkruger.user.model.Person; 4 | import java.util.List; 5 | import javax.enterprise.context.ApplicationScoped; 6 | import javax.persistence.EntityManager; 7 | import javax.persistence.PersistenceContext; 8 | import javax.transaction.Transactional; 9 | 10 | @ApplicationScoped 11 | public class PersonService { 12 | 13 | @PersistenceContext(name="PersonDS") 14 | private EntityManager em; 15 | 16 | public Person getPerson(int id){ 17 | return em.find(Person.class,id); 18 | } 19 | 20 | public List getPeople(){ 21 | return (List)em.createQuery("SELECT p FROM Person p",Person.class) 22 | .getResultList(); 23 | } 24 | 25 | public List getPeopleWithSurname(String surname) { 26 | return (List)em.createQuery("SELECT p FROM Person p WHERE p.surname=:surname",Person.class) 27 | .setParameter("surname", surname) 28 | .getResultList(); 29 | } 30 | 31 | @Transactional 32 | public Person updatePerson(Person person) { 33 | if(person.getId()==null){ 34 | em.persist(person); 35 | return person; 36 | }else{ 37 | return em.merge(person); 38 | } 39 | 40 | } 41 | 42 | @Transactional 43 | public Person deletePerson(int id) { 44 | Person p = em.find(Person.class,id); 45 | if(p!=null){ 46 | em.remove(p); 47 | } 48 | return p; 49 | } 50 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/java/com/github/phillipkruger/user/service/ScoreService.java: -------------------------------------------------------------------------------- 1 | package com.github.phillipkruger.user.service; 2 | 3 | import com.github.phillipkruger.user.model.Score; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Stack; 12 | import javax.annotation.PostConstruct; 13 | import javax.enterprise.context.ApplicationScoped; 14 | import javax.json.bind.Jsonb; 15 | import javax.json.bind.JsonbBuilder; 16 | import javax.json.bind.JsonbConfig; 17 | 18 | @ApplicationScoped 19 | public class ScoreService { 20 | 21 | private final Map> scoreDatabase = new HashMap<>(); 22 | 23 | public List getScores(String idNumber){ 24 | return scoreDatabase.get(idNumber); 25 | } 26 | 27 | @PostConstruct 28 | void init(){ 29 | try(InputStream jsonStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/score.json")){ 30 | if(jsonStream!=null){ 31 | List> loaded = JSONB.fromJson(jsonStream, new ArrayList>(){}.getClass().getGenericSuperclass()); 32 | for(List s:loaded){ 33 | scoreDatabase.put(ids.pop(), s); 34 | } 35 | } 36 | } catch (IOException ex) { 37 | ex.printStackTrace(); 38 | } 39 | } 40 | 41 | private static final Jsonb JSONB = JsonbBuilder.create(new JsonbConfig().withFormatting(true)); 42 | 43 | private static Stack ids = new Stack<>(); 44 | static{ 45 | ids.addAll(Arrays.asList(new String[]{"797-95-4822","373-95-3047","097-87-6795","347-01-8880","733-86-4423","560-99-2165","091-07-5401","539-70-2014","029-18-5986","287-58-0690"})); 46 | } 47 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /wildfly-example/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | openapi-ui.copyrightBy=Phillip Kruger 2 | smallrye.graphql.printDataFetcherException=true -------------------------------------------------------------------------------- /wildfly-example/src/main/resources/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | java:global/person/PersonDS 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /wildfly-example/src/main/resources/META-INF/score.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | { 4 | "id": "d13ba7c4-6c7d-4661-ad6d-858a1731e8fd", 5 | "name": "Driving", 6 | "value": 53 7 | }, 8 | { 9 | "id": "d2552177-1445-4f02-91a2-8865bb050610", 10 | "name": "Fitness", 11 | "value": 19 12 | }, 13 | { 14 | "id": "90443d40-abbe-4040-83dc-5e08ec452e3f", 15 | "name": "Activity", 16 | "value": 26 17 | }, 18 | { 19 | "id": "9ca4847c-2e77-43a1-9478-fa37d6b950d3", 20 | "name": "Financial", 21 | "value": 16 22 | } 23 | ], 24 | [ 25 | { 26 | "id": "81fbd922-094c-4e9f-8362-cbfcceb4b9df", 27 | "name": "Driving", 28 | "value": 57 29 | }, 30 | { 31 | "id": "c90bcccd-f900-4c5b-84eb-f5d30bb28298", 32 | "name": "Fitness", 33 | "value": 25 34 | }, 35 | { 36 | "id": "271c7683-abbf-4e14-a857-e7c3c8ff4ab0", 37 | "name": "Activity", 38 | "value": 0 39 | }, 40 | { 41 | "id": "db1683e7-c358-4e4a-b200-42a9296160d8", 42 | "name": "Financial", 43 | "value": 61 44 | } 45 | ], 46 | [ 47 | { 48 | "id": "07b1ddf0-af06-41e5-858d-0c188fed230b", 49 | "name": "Driving", 50 | "value": 48 51 | }, 52 | { 53 | "id": "acf3bf4f-cc22-4a12-b0b7-1eabd275af83", 54 | "name": "Fitness", 55 | "value": 73 56 | }, 57 | { 58 | "id": "56405c21-04a4-4c22-b2bb-7e6466019ded", 59 | "name": "Activity", 60 | "value": 62 61 | }, 62 | { 63 | "id": "3a4009e6-5513-4fe5-b391-9c8d34a67079", 64 | "name": "Financial", 65 | "value": 54 66 | } 67 | ], 68 | [ 69 | { 70 | "id": "6a3d949c-d4a5-4ad4-aac4-2847c0140a85", 71 | "name": "Driving", 72 | "value": 42 73 | }, 74 | { 75 | "id": "51ac6824-e05c-492a-bd25-145bc67d9122", 76 | "name": "Fitness", 77 | "value": 95 78 | }, 79 | { 80 | "id": "d5f3f78c-9104-48c7-9aa9-52a3eef0a896", 81 | "name": "Activity", 82 | "value": 57 83 | }, 84 | { 85 | "id": "bde2d353-c513-4e60-9fe5-39a9636d282f", 86 | "name": "Financial", 87 | "value": 44 88 | } 89 | ], 90 | [ 91 | { 92 | "id": "10a85beb-8063-4efa-9b45-74aaf5dbbf4a", 93 | "name": "Driving", 94 | "value": 15 95 | }, 96 | { 97 | "id": "9c12ba10-d231-4715-bda3-1f219caf46c0", 98 | "name": "Fitness", 99 | "value": 94 100 | }, 101 | { 102 | "id": "64abc30b-21bd-4beb-860d-a5aba69798c8", 103 | "name": "Activity", 104 | "value": 63 105 | }, 106 | { 107 | "id": "8472e4a2-c26a-4041-be37-e2c2af167862", 108 | "name": "Financial", 109 | "value": 22 110 | } 111 | ], 112 | [ 113 | { 114 | "id": "6cc43771-2b11-4b59-9aca-bcfa4d73e8f8", 115 | "name": "Driving", 116 | "value": 43 117 | }, 118 | { 119 | "id": "089a1dec-a96c-4572-86bb-2a22d5c7bbbb", 120 | "name": "Fitness", 121 | "value": 89 122 | }, 123 | { 124 | "id": "c75beb58-f7a5-4d36-bba8-d343339879dc", 125 | "name": "Activity", 126 | "value": 47 127 | }, 128 | { 129 | "id": "a125ca4f-5616-4ed4-92f8-2ae7ca646e38", 130 | "name": "Financial", 131 | "value": 12 132 | } 133 | ], 134 | [ 135 | { 136 | "id": "4f931428-8197-4738-b639-6a31e3278486", 137 | "name": "Driving", 138 | "value": 55 139 | }, 140 | { 141 | "id": "fb36ff5b-6727-46d2-a730-7b815353f690", 142 | "name": "Fitness", 143 | "value": 13 144 | }, 145 | { 146 | "id": "83ddc3bb-93c6-40e5-9a10-fc16d4068408", 147 | "name": "Activity", 148 | "value": 20 149 | }, 150 | { 151 | "id": "fbabdbec-8717-427c-b768-39eb0ef464d1", 152 | "name": "Financial", 153 | "value": 51 154 | } 155 | ], 156 | [ 157 | { 158 | "id": "da594a0b-cfd8-42dc-8997-d94041d8824a", 159 | "name": "Driving", 160 | "value": 27 161 | }, 162 | { 163 | "id": "c61df030-f193-4dbb-8c67-ca1980ad3521", 164 | "name": "Fitness", 165 | "value": 3 166 | }, 167 | { 168 | "id": "2e175db3-fd69-4004-95df-6f99fa91f210", 169 | "name": "Activity", 170 | "value": 47 171 | }, 172 | { 173 | "id": "a3124670-16eb-451d-ab89-e7dcb7979816", 174 | "name": "Financial", 175 | "value": 92 176 | } 177 | ], 178 | [ 179 | { 180 | "id": "f136f83c-f07a-4190-9c17-4ad38972c27e", 181 | "name": "Driving", 182 | "value": 31 183 | }, 184 | { 185 | "id": "2707ef06-d394-41e9-baca-9fbc899d3f20", 186 | "name": "Fitness", 187 | "value": 37 188 | }, 189 | { 190 | "id": "ac5e2b50-e710-4471-8400-54f8412ab4c1", 191 | "name": "Activity", 192 | "value": 15 193 | }, 194 | { 195 | "id": "c9a24e83-1c49-4a46-b12d-20f8a4788a16", 196 | "name": "Financial", 197 | "value": 5 198 | } 199 | ], 200 | [ 201 | { 202 | "id": "6aa6dcc1-d0cd-45a7-8b5c-d3c6cf1e5fa6", 203 | "name": "Driving", 204 | "value": 2 205 | }, 206 | { 207 | "id": "63d116aa-3091-4e0a-b492-57dd6918df9c", 208 | "name": "Fitness", 209 | "value": 68 210 | }, 211 | { 212 | "id": "019a3c99-d7c6-458e-9dc8-aacc4cb40f06", 213 | "name": "Activity", 214 | "value": 53 215 | }, 216 | { 217 | "id": "c586d351-cea5-49d4-8842-365728d7a218", 218 | "name": "Financial", 219 | "value": 24 220 | } 221 | ] 222 | ] -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/WEB-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/WEB-INF/jboss-web.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | / 8 | -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 30 9 | 10 | 11 | 12 | 13 | java:global/person/PersonDS 14 | org.h2.jdbcx.JdbcDataSource 15 | jdbc:h2:./target/data/person 16 | sa 17 | "" 18 | true 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/_data/mystaticpage-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MicroProfile GraphQL Example", 3 | "briefIntro": "Example Application that shows the new MicroProfile GraphQL API", 4 | "fullBio": "You can compare REST and GraphQL:\n\n* [REST](http://localhost:8080/rest/openapi-ui/)\n* [GraphQL](http://localhost:8080/graphiql/)\n\n", 5 | "links": [ 6 | { 7 | "linkType": "twitter", 8 | "linkLabel": "Twitter", 9 | "url": "https://twitter.com/phillipkruger", 10 | "isImportant": false 11 | } 12 | ], 13 | "avatarUrl": "images/avatar.jpg" 14 | } -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} 5 | -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | height: 100vh; } 4 | 5 | body { 6 | min-height: 100%; 7 | padding: 0px; 8 | margin: 0px; } 9 | 10 | body { 11 | background-color: #fff; 12 | background-image: url("../images/background.jpg"); 13 | background-size: cover; 14 | background-position: left bottom; 15 | background-attachment: fixed; 16 | font-family: "Segoe UI", "Lucida Grande", "Lucida Sans", "Helvetica Neue", "Arial", "Helvetica", sans-serif; 17 | color: #333; } 18 | 19 | a { 20 | text-decoration: none; 21 | color: #00ade0; } 22 | a:hover { 23 | color: #00c1fa; } 24 | 25 | #mainContainer { 26 | background-color: #fff; 27 | background-color: rgba(255, 255, 255, 0.7); 28 | display: -webkit-box; 29 | display: -ms-flexbox; 30 | display: flex; 31 | -webkit-box-orient: vertical; 32 | -webkit-box-direction: normal; 33 | -ms-flex-direction: column; 34 | flex-direction: column; 35 | -webkit-box-pack: justify; 36 | -ms-flex-pack: justify; 37 | justify-content: space-between; 38 | -ms-flex-line-pack: stretch; 39 | align-content: stretch; 40 | min-height: 100%; 41 | max-width: 80%; 42 | margin: 0px; 43 | -webkit-animation: fadeIn 0.5s ease-out both; 44 | animation: fadeIn 0.5s ease-out both; } 45 | #mainContainer #mainContentBlock { 46 | -webkit-box-flex: 1; 47 | -ms-flex: 1 0 auto; 48 | flex: 1 0 auto; 49 | display: -webkit-box; 50 | display: -ms-flexbox; 51 | display: flex; 52 | -webkit-box-orient: vertical; 53 | -webkit-box-direction: normal; 54 | -ms-flex-direction: column; 55 | flex-direction: column; 56 | -webkit-box-pack: end; 57 | -ms-flex-pack: end; 58 | justify-content: flex-end; 59 | -ms-flex-line-pack: left; 60 | align-content: left; 61 | padding: 0px; } 62 | #mainContainer #mainContentBlock #mainContent { 63 | margin: 0px; 64 | overflow: hidden; 65 | display: -webkit-box; 66 | display: -ms-flexbox; 67 | display: flex; 68 | -webkit-box-orient: vertical; 69 | -webkit-box-direction: normal; 70 | -ms-flex-direction: column; 71 | flex-direction: column; 72 | -ms-flex-line-pack: center; 73 | align-content: center; 74 | padding-top: 100px; } 75 | #mainContainer #mainContentBlock #mainContent #avatarImageBlock { 76 | width: 150px; 77 | height: 150px; 78 | margin: 10px 50px; 79 | border-radius: 50%; 80 | background-position: center center; 81 | background-size: cover; 82 | opacity: 0.95; 83 | -webkit-animation: intro 0.5s ease-out both; 84 | animation: intro 0.5s ease-out both; } 85 | #mainContainer #mainContentBlock #mainContent #introBox { 86 | text-align: left; 87 | margin: 0px; 88 | padding: 0px 50px; } 89 | #mainContainer #mainContentBlock #mainContent #introBox h1 { 90 | font-size: 3em; 91 | font-weight: normal; 92 | margin: 0px; 93 | -webkit-animation: intro 0.5s 0.2s ease-out both; 94 | animation: intro 0.5s 0.2s ease-out both; } 95 | #mainContainer #mainContentBlock #mainContent #introBox h2 { 96 | font-size: 1.8em; 97 | font-weight: lighter; 98 | margin: 0px; 99 | -webkit-animation: intro 0.5s 0.4s ease-out both; 100 | animation: intro 0.5s 0.4s ease-out both; } 101 | #mainContainer #mainContentBlock #mainContent #introBox #linkBox { 102 | padding: 0px; 103 | list-style: none; 104 | max-width: 80%; 105 | display: -webkit-box; 106 | display: -ms-flexbox; 107 | display: flex; 108 | -webkit-box-orient: horizontal; 109 | -webkit-box-direction: normal; 110 | -ms-flex-direction: row; 111 | flex-direction: row; 112 | -webkit-box-pack: start; 113 | -ms-flex-pack: start; 114 | justify-content: flex-start; 115 | -ms-flex-wrap: wrap; 116 | flex-wrap: wrap; 117 | -webkit-animation: intro 0.5s 0.6s ease-out both; 118 | animation: intro 0.5s 0.6s ease-out both; } 119 | #mainContainer #mainContentBlock #mainContent #introBox #linkBox li { 120 | margin-right: 10px; 121 | display: inline; } 122 | #mainContainer #mainContentBlock #mainContent #introBox #linkBox li .link-icon:hover { 123 | color: #00c1fa; } 124 | #mainContainer #mainContentBlock #mainContent #introBox #linkBox li a .description { 125 | display: none; 126 | font-size: 0.8em; } 127 | #mainContainer #mainContentBlock #mainContent #introBox #linkBox li.featured a .description { 128 | color: #333; 129 | padding-left: 5px; 130 | padding-right: 2px; } 131 | #mainContainer #mainContentBlock #mainContent #introBox #linkBox li.featured a .description:hover { 132 | color: #00c1fa; } 133 | #mainContainer #mainContentBlock #mainContent #introBox #linkBox li.featured .description { 134 | display: inline; } 135 | #mainContainer #mainContentBlock #mainContent #fullBioBox { 136 | font-size: 0.9em; 137 | color: #4d4d4d; 138 | padding: 10px 50px; 139 | -webkit-animation: intro 0.5s 0.8s ease-out both; 140 | animation: intro 0.5s 0.8s ease-out both; } 141 | 142 | div.footer { 143 | text-align: left; 144 | font-size: 0.7em; 145 | padding-left: 50px; 146 | opacity: 0.8; } 147 | 148 | @media only screen and (max-width: 768px) { 149 | #mainContainer { 150 | max-width: 90%; } 151 | #mainContainer #mainContentBlock #mainContent #avatarImageBlock { 152 | margin-left: 25px; } 153 | #mainContainer #mainContentBlock #mainContent #introBox { 154 | padding: 0px 25px; } 155 | #mainContainer #mainContentBlock #mainContent #fullBioBox { 156 | padding: 0px 25px; } 157 | div.footer { 158 | padding-left: 25px; } } 159 | 160 | @-webkit-keyframes fadeIn { 161 | from { 162 | opacity: 0; } 163 | to { 164 | opacity: 1; } } 165 | 166 | @keyframes fadeIn { 167 | from { 168 | opacity: 0; } 169 | to { 170 | opacity: 1; } } 171 | 172 | @-webkit-keyframes intro { 173 | 0% { 174 | -webkit-transform: translateY(40px); 175 | transform: translateY(40px); 176 | opacity: 0; } 177 | 50% { 178 | opacity: 0.2; } 179 | 100% { 180 | -webkit-transform: translateY(0px); 181 | transform: translateY(0px); 182 | opacity: 1; } } 183 | 184 | @keyframes intro { 185 | 0% { 186 | -webkit-transform: translateY(40px); 187 | transform: translateY(40px); 188 | opacity: 0; } 189 | 50% { 190 | opacity: 0.2; } 191 | 100% { 192 | -webkit-transform: translateY(0px); 193 | transform: translateY(0px); 194 | opacity: 1; } } 195 | -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/images/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/images/avatar.jpg -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/images/background.jpg -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phillip-kruger/graphql-example/c6bacfcba9c918b2f6778ca9566eb00bd3b4ce9f/wildfly-example/src/main/webapp/images/logo.png -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MicroProfile GraphQL Example 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |

MicroProfile GraphQL 1.0 ExampleSmallRye

20 |

Example Application that showcase MicroProfile GraphQL 1.0 API

21 | 28 |
29 | 30 |
31 | You can compare REST and GraphQL: 32 | 36 | 37 | Also see the presentation 38 | and the source code 39 |
40 |
41 | 42 |
43 | 44 | 57 |
58 | 59 | -------------------------------------------------------------------------------- /wildfly-example/src/main/webapp/license.txt: -------------------------------------------------------------------------------- 1 | This work is licensed to you by MyStaticPage.com under 2 | Creative Commons Attribution 4.0 International license 3 | https://creativecommons.org/licenses/by/4.0/ 4 | 5 | You may use and modify this work freely as long as you keep the link back to 6 | MyStaticPage.com visible on the page. 7 | 8 | Note that this work is licensed to you as a whole and individual parts 9 | (such as scripts, fonts, images, etc.) are not licensed to be used 10 | separately under this license. --------------------------------------------------------------------------------