├── .editorconfig ├── .github ├── dependabot.yml ├── maven-cd-settings.xml ├── maven-ci-settings.xml └── workflows │ ├── ci-4.x.yml │ ├── ci-5.x-stable.yml │ ├── ci-5.x.yml │ ├── ci-matrix-5.x.yml │ ├── ci.yml │ └── deploy.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── pom.xml └── src ├── main ├── asciidoc │ └── index.adoc ├── java │ ├── examples │ │ ├── Examples.java │ │ ├── SomeDatabaseService.java │ │ ├── SomeDatabaseServiceImpl.java │ │ └── package-info.java │ ├── io │ │ └── vertx │ │ │ └── serviceproxy │ │ │ ├── AuthenticationInterceptor.java │ │ │ ├── AuthorizationInterceptor.java │ │ │ ├── HelperUtils.java │ │ │ ├── ProxyHandler.java │ │ │ ├── ProxyUtils.java │ │ │ ├── ServiceBinder.java │ │ │ ├── ServiceException.java │ │ │ ├── ServiceExceptionMessageCodec.java │ │ │ ├── ServiceInterceptor.java │ │ │ ├── ServiceProxyBuilder.java │ │ │ ├── generator │ │ │ ├── GeneratorUtils.java │ │ │ ├── ServiceProxyGen.java │ │ │ ├── ServiceProxyGenLoader.java │ │ │ ├── ServiceProxyHandlerGen.java │ │ │ └── model │ │ │ │ ├── ProxyMethodInfo.java │ │ │ │ ├── ProxyModel.java │ │ │ │ └── ProxyModelProvider.java │ │ │ ├── impl │ │ │ ├── AuthenticationInterceptorImpl.java │ │ │ ├── AuthorizationInterceptorImpl.java │ │ │ ├── InterceptorHolder.java │ │ │ ├── InterceptorPriority.java │ │ │ └── utils │ │ │ │ └── InterceptorUtils.java │ │ │ └── package-info.java │ └── module-info.java └── resources │ └── META-INF │ ├── services │ ├── io.vertx.codegen.processor.GeneratorLoader │ └── io.vertx.codegen.processor.ModelProvider │ └── vertx │ └── vertx-service-proxy │ ├── class_header.txt │ ├── handler_close_accessed.txt │ ├── handler_constructor_body.txt │ ├── handler_gen_import.txt │ ├── proxy_gen_import.txt │ └── roger.txt └── test ├── java └── io │ └── vertx │ └── serviceproxy │ └── tests │ ├── FuturizedServiceProxyTest.java │ ├── SecureServiceBinderTest.java │ ├── ServiceBinderTest.java │ ├── ServiceProxyTest.java │ ├── clustered │ ├── ClusteredTest.java │ ├── LocalServiceProviderVerticle.java │ ├── Service.java │ ├── ServiceProvider.java │ ├── ServiceProviderVerticle.java │ └── package-info.java │ ├── codegen │ ├── ProxyTest.java │ ├── future │ │ ├── FuturizedProxy.java │ │ └── package-info.java │ └── proxytestapi │ │ ├── Concrete.java │ │ ├── InvalidClose1.java │ │ ├── InvalidClose2.java │ │ ├── InvalidClose3.java │ │ ├── InvalidOverloaded.java │ │ ├── InvalidParams1.java │ │ ├── InvalidParams2.java │ │ ├── InvalidParams3.java │ │ ├── InvalidParams4.java │ │ ├── InvalidParamsDataObject.java │ │ ├── InvalidReturn1.java │ │ ├── InvalidReturn2.java │ │ ├── InvalidReturn3.java │ │ ├── ProxyConnection.java │ │ ├── ProxyDataObject.java │ │ ├── ProxyDataObjectParent.java │ │ ├── ProxyDataObjectWithParent.java │ │ ├── ProxyDataObjectWithParentOverride.java │ │ ├── SomeEnum.java │ │ ├── ValidProxy.java │ │ ├── ValidProxyCloseWithFuture.java │ │ └── package-info.java │ ├── testmodel │ ├── Mappers.java │ ├── MyServiceException.java │ ├── MyServiceExceptionMessageCodec.java │ ├── OKService.java │ ├── OKServiceImpl.java │ ├── SomeEnum.java │ ├── SomeEnumWithCustomConstructor.java │ ├── SomeVertxEnum.java │ ├── StringDataObject.java │ ├── TestBaseImportsService.java │ ├── TestConnection.java │ ├── TestDataObject.java │ ├── TestService.java │ ├── impl │ │ ├── TestConnectionImpl.java │ │ ├── TestServiceImpl.java │ │ └── TestSubConnectionImpl.java │ ├── package-info.java │ └── sub │ │ └── TestSubConnection.java │ ├── testmodel2 │ ├── FuturizedTestService.java │ ├── impl │ │ └── FuturizedTestServiceImpl.java │ └── package-info.java │ └── utils │ └── InterceptorUtilsTest.java └── resources ├── META-INF └── vertx │ └── json-mappers.properties └── keystore.jceks /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | trim_trailing_whitespace = true 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | [**/examples/**.java] 12 | # 84 looks like a odd number, however 13 | # it accounts for 4 spaces (class and example method indentation) 14 | max_line_length = 84 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "maven" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /.github/maven-cd-settings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | false 20 | 21 | 22 | 23 | vertx-snapshots-repository 24 | ${env.VERTX_NEXUS_USERNAME} 25 | ${env.VERTX_NEXUS_PASSWORD} 26 | 27 | 28 | 29 | 30 | 31 | google-mirror 32 | 33 | true 34 | 35 | 36 | 37 | google-maven-central 38 | GCS Maven Central mirror EU 39 | https://maven-central.storage-download.googleapis.com/maven2/ 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | google-maven-central 51 | GCS Maven Central mirror 52 | https://maven-central.storage-download.googleapis.com/maven2/ 53 | 54 | true 55 | 56 | 57 | false 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /.github/maven-ci-settings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | false 20 | 21 | 22 | 23 | google-mirror 24 | 25 | true 26 | 27 | 28 | 29 | google-maven-central 30 | GCS Maven Central mirror EU 31 | https://maven-central.storage-download.googleapis.com/maven2/ 32 | 33 | true 34 | 35 | 36 | false 37 | 38 | 39 | 40 | 41 | 42 | google-maven-central 43 | GCS Maven Central mirror 44 | https://maven-central.storage-download.googleapis.com/maven2/ 45 | 46 | true 47 | 48 | 49 | false 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /.github/workflows/ci-4.x.yml: -------------------------------------------------------------------------------- 1 | name: vertx-service-proxy (4.x) 2 | on: 3 | schedule: 4 | - cron: '0 4 * * *' 5 | jobs: 6 | CI: 7 | strategy: 8 | matrix: 9 | include: 10 | - os: ubuntu-latest 11 | jdk: 8 12 | - os: ubuntu-latest 13 | jdk: 17 14 | uses: ./.github/workflows/ci.yml 15 | with: 16 | branch: 4.x 17 | jdk: ${{ matrix.jdk }} 18 | os: ${{ matrix.os }} 19 | secrets: inherit 20 | Deploy: 21 | if: ${{ github.repository_owner == 'vert-x3' && (github.event_name == 'push' || github.event_name == 'schedule') }} 22 | needs: CI 23 | uses: ./.github/workflows/deploy.yml 24 | with: 25 | branch: 4.x 26 | jdk: 8 27 | secrets: inherit 28 | -------------------------------------------------------------------------------- /.github/workflows/ci-5.x-stable.yml: -------------------------------------------------------------------------------- 1 | name: vertx-service-proxy (5.x-stable) 2 | on: 3 | push: 4 | branches: 5 | - '5.[0-9]+' 6 | pull_request: 7 | branches: 8 | - '5.[0-9]+' 9 | schedule: 10 | - cron: '0 6 * * *' 11 | jobs: 12 | CI-CD: 13 | uses: ./.github/workflows/ci-matrix-5.x.yml 14 | secrets: inherit 15 | with: 16 | branch: ${{ github.event_name == 'schedule' && vars.VERTX_5_STABLE_BRANCH || github.event.pull_request.head.sha || github.ref_name }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-5.x.yml: -------------------------------------------------------------------------------- 1 | name: vertx-service-proxy (5.x) 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | schedule: 10 | - cron: '0 5 * * *' 11 | jobs: 12 | CI-CD: 13 | uses: ./.github/workflows/ci-matrix-5.x.yml 14 | secrets: inherit 15 | with: 16 | branch: ${{ github.event.pull_request.head.sha || github.ref_name }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-matrix-5.x.yml: -------------------------------------------------------------------------------- 1 | name: CI matrix (5.x) 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jobs: 9 | CI: 10 | strategy: 11 | matrix: 12 | include: 13 | - os: ubuntu-latest 14 | jdk: 11 15 | - os: ubuntu-latest 16 | jdk: 21 17 | uses: ./.github/workflows/ci.yml 18 | with: 19 | branch: ${{ inputs.branch }} 20 | jdk: ${{ matrix.jdk }} 21 | os: ${{ matrix.os }} 22 | secrets: inherit 23 | Deploy: 24 | if: ${{ github.repository_owner == 'vert-x3' && (github.event_name == 'push' || github.event_name == 'schedule') }} 25 | needs: CI 26 | uses: ./.github/workflows/deploy.yml 27 | with: 28 | branch: ${{ inputs.branch }} 29 | jdk: 11 30 | secrets: inherit 31 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jdk: 9 | default: 8 10 | type: string 11 | os: 12 | default: ubuntu-latest 13 | type: string 14 | jobs: 15 | Test: 16 | name: Run tests 17 | runs-on: ${{ inputs.os }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | with: 22 | ref: ${{ inputs.branch }} 23 | - name: Install JDK 24 | uses: actions/setup-java@v2 25 | with: 26 | java-version: ${{ inputs.jdk }} 27 | distribution: temurin 28 | - name: Run tests 29 | run: mvn -s .github/maven-ci-settings.xml -q clean verify -B 30 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jdk: 9 | default: 8 10 | type: string 11 | jobs: 12 | Deploy: 13 | name: Deploy to OSSRH 14 | runs-on: ubuntu-latest 15 | env: 16 | VERTX_NEXUS_USERNAME: ${{ secrets.VERTX_NEXUS_USERNAME }} 17 | VERTX_NEXUS_PASSWORD: ${{ secrets.VERTX_NEXUS_PASSWORD }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | with: 22 | ref: ${{ inputs.branch }} 23 | - name: Install JDK 24 | uses: actions/setup-java@v2 25 | with: 26 | java-version: ${{ inputs.jdk }} 27 | distribution: temurin 28 | - name: Get project version 29 | run: echo "PROJECT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -q -DforceStdout | grep -v '\[')" >> $GITHUB_ENV 30 | - name: Maven deploy 31 | if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }} 32 | run: mvn deploy -s .github/maven-cd-settings.xml -DskipTests -B 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vertx 2 | .DS_Store 3 | .gradle 4 | .idea 5 | .classpath 6 | .project 7 | .settings 8 | .yardoc 9 | .yardopts 10 | bin 11 | build 12 | target 13 | out 14 | *.iml 15 | *.ipr 16 | *.iws 17 | test-output 18 | Scratch.java 19 | ScratchTest.java 20 | test-results 21 | test-tmp 22 | *.class 23 | src/gen 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 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 | # Service Proxies 2 | 3 | [![Build Status (5.x)](https://github.com/vert-x3/vertx-service-proxy/actions/workflows/ci-5.x.yml/badge.svg)](https://github.com/vert-x3/vertx-service-proxy/actions/workflows/ci-5.x.yml) 4 | [![Build Status (4.x)](https://github.com/vert-x3/vertx-service-proxy/actions/workflows/ci-4.x.yml/badge.svg)](https://github.com/vert-x3/vertx-service-proxy/actions/workflows/ci-4.x.yml) 5 | 6 | Please see the main documentation on the web-site for a full description: 7 | 8 | * [Web-site documentation](https://vertx.io/docs/vertx-service-proxy/java/) 9 | 10 | Many Vert.x applications include various services which do useful things and often can be reused from one application 11 | to another. An example would be a database service. 12 | 13 | Usually those services run in their own verticle and interact with other verticles by receiving and sending messages, e.g. 14 | 15 | // Assume database service is already deployed somewhere.... 16 | 17 | // Save some data in the database 18 | 19 | JsonObject message = new JsonObject(); 20 | message.putString("collection", "mycollection"); 21 | message.putObject("document", new JsonObject().putString("name", "tim")); 22 | DeliveryOptions options = new DeliveryOptions().addHeader("action", "save"); 23 | vertx.eventBus().send("database-service-address", message, options, res2 -> { 24 | if (res2.succeeded()) { 25 | // done 26 | } 27 | } 28 | 29 | 30 | When creating a service there's a certain amount of boiler-plate code to listen on the eventbus for incoming messages, 31 | route them to the appropriate method and return results on the event bus. 32 | 33 | With Vert.x service proxies, you can avoid writing all that boiler-plate code and concentrate on writing your service. 34 | 35 | You write your service as a Java interface and annotate it with the `@ProxyGen` annotation, for example: 36 | 37 | @ProxyGen 38 | public interface SomeDatabaseService { 39 | 40 | // A couple of factory methods to create an instance and a proxy 41 | 42 | static SomeDatabaseService create(Vertx vertx) { 43 | return new SomeDatabaseServiceImpl(vertx); 44 | } 45 | 46 | static SomeDatabaseService createProxy(Vertx vertx, String address) { 47 | return new SomeDatabaseServiceVertxEBProxy(vertx, address); 48 | } 49 | 50 | // Actual service operations here... 51 | 52 | void save(String collection, JsonObject document, Handler> resultHandler); 53 | } 54 | 55 | Given the interface, Vert.x will generate all the boiler-plate required to access your service over the event bus, and it 56 | will also generate a *client side proxy* for your service, so your clients can use a rich idiomatic API for your 57 | service instead of having to manually craft event bus messages to send. The client side proxy will work irrespective 58 | of where your service actually lives on the event bus (potentially on a different machine). 59 | 60 | That means you can interact with your service like this: 61 | 62 | // Assume database service is already deployed somewhere.... 63 | 64 | // Create a proxy 65 | SomeDatabaseService service = SomeDatabaseService.createProxy(vertx, "database-service-address"); 66 | 67 | // Save some data in the database - this time using the proxy 68 | service.save("mycollection", new JsonObject().putString("name", "tim"), res2 -> { 69 | if (res2.succeeded()) { 70 | // done 71 | } 72 | }); 73 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | io.vertx 6 | vertx5-parent 7 | 12 8 | 9 | 10 | 4.0.0 11 | 12 | vertx-service-proxy 13 | 5.1.0-SNAPSHOT 14 | 15 | 16 | scm:git:git@github.com:vert-x3/vertx-service-proxy.git 17 | scm:git:git@github.com:vert-x3/vertx-service-proxy.git 18 | git@github.com:vert-x3/vertx-service-proxy.git 19 | 20 | 21 | 22 | false 23 | ${path.separator} 24 | 25 | 26 | 27 | 28 | 29 | io.vertx 30 | vertx-dependencies 31 | ${project.version} 32 | pom 33 | import 34 | 35 | 36 | junit 37 | junit 38 | 4.13.2 39 | 40 | 41 | 42 | 43 | 44 | 45 | io.vertx 46 | vertx-codegen-api 47 | 48 | 49 | io.vertx 50 | vertx-codegen-json 51 | 52 | 53 | io.vertx 54 | vertx-codegen-processor 55 | 56 | 57 | io.vertx 58 | vertx-core 59 | 60 | 61 | io.vertx 62 | vertx-auth-jwt 63 | true 64 | 65 | 66 | 67 | io.vertx 68 | vertx-docgen-api 69 | true 70 | 71 | 72 | 73 | junit 74 | junit 75 | test 76 | 77 | 78 | com.fasterxml.jackson.core 79 | jackson-databind 80 | test 81 | 82 | 83 | io.vertx 84 | vertx-core 85 | test-jar 86 | test 87 | 88 | 89 | io.vertx 90 | vertx-codegen-processor 91 | test-jar 92 | test 93 | 94 | 95 | 96 | org.assertj 97 | assertj-core 98 | 3.3.0 99 | test 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | maven-jar-plugin 108 | 109 | 110 | default-jar 111 | 112 | 113 | META-INF/services/javax.annotation.processing.Processor 114 | examples/** 115 | 116 | 117 | 118 | 119 | 120 | 121 | maven-compiler-plugin 122 | 123 | 124 | default-compile 125 | 126 | 127 | 128 | io.vertx 129 | vertx-docgen-processor 130 | processor 131 | 132 | 133 | 134 | 135 | 136 | default-testCompile 137 | 138 | false 139 | 140 | io.vertx.codegen.processor.Processor 141 | 142 | 143 | **/InvalidParamsDataObject.java 144 | **/InvalidOverloaded.java 145 | **/InvalidParams1.java 146 | **/InvalidParams2.java 147 | **/InvalidParams3.java 148 | **/InvalidParams4.java 149 | **/InvalidReturn1.java 150 | **/InvalidReturn2.java 151 | **/InvalidReturn3.java 152 | **/InvalidClose1.java 153 | **/InvalidClose2.java 154 | **/InvalidClose3.java 155 | 156 | 157 | ${project.build.directory}/classes${s}${io.vertx:vertx-codegen-api:jar}${s}${io.vertx:vertx-codegen-processor:jar} 158 | 159 | 160 | 161 | 162 | 163 | 164 | org.apache.maven.plugins 165 | maven-surefire-plugin 166 | 167 | 168 | default-test 169 | 170 | 171 | ${project.build.testSourceDirectory} 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | org.apache.maven.plugins 183 | maven-dependency-plugin 184 | 185 | 186 | initialize 187 | 188 | properties 189 | 190 | 191 | 192 | 193 | 194 | maven-assembly-plugin 195 | 196 | 197 | package-docs 198 | 199 | single 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /src/main/java/examples/Examples.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import io.vertx.core.Vertx; 4 | import io.vertx.core.eventbus.DeliveryOptions; 5 | import io.vertx.core.eventbus.MessageConsumer; 6 | import io.vertx.core.json.JsonObject; 7 | import io.vertx.ext.auth.authorization.PermissionBasedAuthorization; 8 | import io.vertx.ext.auth.authorization.RoleBasedAuthorization; 9 | import io.vertx.ext.auth.jwt.JWTAuth; 10 | import io.vertx.ext.auth.jwt.JWTAuthOptions; 11 | import io.vertx.ext.auth.jwt.authorization.JWTAuthorization; 12 | import io.vertx.serviceproxy.AuthenticationInterceptor; 13 | import io.vertx.serviceproxy.AuthorizationInterceptor; 14 | import io.vertx.serviceproxy.ServiceBinder; 15 | import io.vertx.serviceproxy.ServiceProxyBuilder; 16 | 17 | /** 18 | * @author Clement Escoffier 19 | */ 20 | public class Examples { 21 | 22 | public void example1(Vertx vertx) { 23 | // Assume database service is already deployed somewhere.... 24 | // Save some data in the database 25 | JsonObject message = new JsonObject(); 26 | 27 | message 28 | .put("collection", "mycollection") 29 | .put("document", new JsonObject().put("name", "tim")); 30 | 31 | DeliveryOptions options = new DeliveryOptions().addHeader("action", "save"); 32 | 33 | vertx.eventBus() 34 | .request("database-service-address", message, options) 35 | .onSuccess(msg -> { 36 | // done 37 | }).onFailure(err -> { 38 | // failure 39 | }); 40 | } 41 | 42 | public void example2(Vertx vertx) { 43 | // Assume database service is already deployed somewhere.... 44 | 45 | // Create a proxy 46 | SomeDatabaseService service = SomeDatabaseService 47 | .createProxy(vertx, "database-service-address"); 48 | 49 | // Save some data in the database - this time using the proxy 50 | service.save( 51 | "mycollection", 52 | new JsonObject().put("name", "tim")).onComplete( 53 | res2 -> { 54 | if (res2.succeeded()) { 55 | // done 56 | } 57 | }); 58 | } 59 | 60 | public void register(Vertx vertx) { 61 | // Create an instance of your service implementation 62 | SomeDatabaseService service = new SomeDatabaseServiceImpl(); 63 | // Register the handler 64 | new ServiceBinder(vertx) 65 | .setAddress("database-service-address") 66 | .register(SomeDatabaseService.class, service); 67 | } 68 | 69 | public void unregister(Vertx vertx) { 70 | ServiceBinder binder = new ServiceBinder(vertx); 71 | 72 | // Create an instance of your service implementation 73 | SomeDatabaseService service = new SomeDatabaseServiceImpl(); 74 | // Register the handler 75 | MessageConsumer consumer = binder 76 | .setAddress("database-service-address") 77 | .register(SomeDatabaseService.class, service); 78 | 79 | // .... 80 | 81 | // Unregister your service. 82 | binder.unregister(consumer); 83 | } 84 | 85 | public void proxyCreation(Vertx vertx, DeliveryOptions options) { 86 | ServiceProxyBuilder builder = new ServiceProxyBuilder(vertx) 87 | .setAddress("database-service-address"); 88 | 89 | SomeDatabaseService service = builder.build(SomeDatabaseService.class); 90 | // or with delivery options: 91 | SomeDatabaseService service2 = builder.setOptions(options) 92 | .build(SomeDatabaseService.class); 93 | } 94 | 95 | public void secure(Vertx vertx) { 96 | // Create an instance of your service implementation 97 | SomeDatabaseService service = new SomeDatabaseServiceImpl(); 98 | // Register the handler 99 | new ServiceBinder(vertx) 100 | .setAddress("database-service-address") 101 | // Secure the messages in transit 102 | .addInterceptor( 103 | "action", 104 | // Tokens will be validated using JWT authentication 105 | AuthenticationInterceptor.create( 106 | JWTAuth.create(vertx, new JWTAuthOptions()))) 107 | .addInterceptor( 108 | AuthorizationInterceptor.create(JWTAuthorization.create("permissions")) 109 | // optionally we can secure permissions too: 110 | // an admin 111 | .addAuthorization(RoleBasedAuthorization.create("admin")) 112 | // that can print 113 | .addAuthorization(PermissionBasedAuthorization.create("print"))) 114 | .register(SomeDatabaseService.class, service); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/examples/SomeDatabaseService.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.core.Future; 5 | import io.vertx.core.Vertx; 6 | import io.vertx.core.json.JsonObject; 7 | 8 | /** 9 | * @author Clement Escoffier 10 | */ 11 | @ProxyGen 12 | public interface SomeDatabaseService { 13 | 14 | Future save(String collection, JsonObject document); 15 | 16 | Future foo(String collection, JsonObject document); 17 | 18 | static SomeDatabaseService createProxy(Vertx vertx, String address) { 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/examples/SomeDatabaseServiceImpl.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import io.vertx.core.AsyncResult; 4 | import io.vertx.core.Future; 5 | import io.vertx.core.Handler; 6 | import io.vertx.core.json.JsonObject; 7 | 8 | /** 9 | * @author Clement Escoffier 10 | */ 11 | public class SomeDatabaseServiceImpl implements SomeDatabaseService { 12 | 13 | @Override 14 | public Future save(String collection, JsonObject document) { 15 | return null; 16 | } 17 | 18 | @Override 19 | public Future foo(String collection, JsonObject document) { 20 | return null; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/examples/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | @Source(translate = false) 18 | @ModuleGen(name = "examples", groupPackage = "examples") 19 | package examples; 20 | 21 | import io.vertx.codegen.annotations.ModuleGen; 22 | import io.vertx.docgen.Source; 23 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/AuthenticationInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.codegen.annotations.VertxGen; 19 | import io.vertx.ext.auth.authentication.AuthenticationProvider; 20 | import io.vertx.serviceproxy.impl.AuthenticationInterceptorImpl; 21 | 22 | /** 23 | * Create an event bus service interceptor that will provide an authentication check 24 | */ 25 | @VertxGen 26 | public interface AuthenticationInterceptor extends ServiceInterceptor { 27 | 28 | static AuthenticationInterceptor create(AuthenticationProvider authenticationProvider) { 29 | return new AuthenticationInterceptorImpl(authenticationProvider); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/AuthorizationInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.codegen.annotations.VertxGen; 19 | import io.vertx.ext.auth.authorization.Authorization; 20 | import io.vertx.ext.auth.authorization.AuthorizationProvider; 21 | import io.vertx.serviceproxy.impl.AuthorizationInterceptorImpl; 22 | 23 | import java.util.Set; 24 | 25 | /** 26 | * Create an event bus service interceptor that will provide an authorization check 27 | */ 28 | @VertxGen 29 | public interface AuthorizationInterceptor extends ServiceInterceptor { 30 | 31 | static AuthorizationInterceptor create(AuthorizationProvider authorizationProvider) { 32 | return new AuthorizationInterceptorImpl(authorizationProvider); 33 | } 34 | 35 | /** 36 | * Set the required authorities for the service, once a JWT is validated it will be 37 | * queried for these authorities. If authorities are missing a error 403 is returned. 38 | * 39 | * @param authorizations set of authorities 40 | * @return self 41 | */ 42 | AuthorizationInterceptor setAuthorizations(Set authorizations); 43 | 44 | /** 45 | * Add a single authority to the authorities set. 46 | * 47 | * @param authorization authority 48 | * @return self 49 | */ 50 | AuthorizationInterceptor addAuthorization(Authorization authorization); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/HelperUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.core.AsyncResult; 19 | import io.vertx.core.Handler; 20 | import io.vertx.core.eventbus.Message; 21 | import io.vertx.core.json.JsonArray; 22 | import io.vertx.core.json.JsonObject; 23 | 24 | import java.util.*; 25 | 26 | /** 27 | * @author Francesco Guardiani @slinkydeveloper 28 | */ 29 | @SuppressWarnings({"unchecked", "rawtypes"}) 30 | public class HelperUtils { 31 | 32 | public static Handler> createHandler(Message msg, boolean includeDebugInfo) { 33 | return res -> { 34 | if (res.failed()) { 35 | manageFailure(msg, res.cause(), includeDebugInfo); 36 | } else { 37 | if (res.result() != null && res.result().getClass().isEnum()) { 38 | msg.reply(((Enum) res.result()).name()); 39 | } else { 40 | msg.reply(res.result()); 41 | } 42 | } 43 | }; 44 | } 45 | 46 | public static Handler>> createListHandler(Message msg, boolean includeDebugInfo) { 47 | return res -> { 48 | if (res.failed()) { 49 | manageFailure(msg, res.cause(), includeDebugInfo); 50 | } else { 51 | msg.reply(new JsonArray(res.result())); 52 | } 53 | }; 54 | } 55 | 56 | public static Handler>> createSetHandler(Message msg, boolean includeDebugInfo) { 57 | return res -> { 58 | if (res.failed()) { 59 | manageFailure(msg, res.cause(), includeDebugInfo); 60 | } else { 61 | msg.reply(new JsonArray(new ArrayList<>(res.result()))); 62 | } 63 | }; 64 | } 65 | 66 | public static Handler>> createMapHandler(Message msg, boolean includeDebugInfo) { 67 | return res -> { 68 | if (res.failed()) { 69 | manageFailure(msg, res.cause(), includeDebugInfo); 70 | } else { 71 | msg.reply(new JsonObject(new HashMap<>(res.result()))); 72 | } 73 | }; 74 | } 75 | 76 | public static Handler>> createListCharHandler(Message msg, boolean includeDebugInfo) { 77 | return res -> { 78 | if (res.failed()) { 79 | manageFailure(msg, res.cause(), includeDebugInfo); 80 | } else { 81 | JsonArray arr = new JsonArray(); 82 | for (Character chr: res.result()) { 83 | arr.add((int) chr); 84 | } 85 | msg.reply(arr); 86 | } 87 | }; 88 | } 89 | 90 | public static Handler>> createSetCharHandler(Message msg, boolean includeDebugInfo) { 91 | return res -> { 92 | if (res.failed()) { 93 | manageFailure(msg, res.cause(), includeDebugInfo); 94 | } else { 95 | JsonArray arr = new JsonArray(); 96 | for (Character chr: res.result()) { 97 | arr.add((int) chr); 98 | } 99 | msg.reply(arr); 100 | } 101 | }; 102 | } 103 | 104 | public static Handler>> createMapCharHandler(Message msg, boolean includeDebugInfo) { 105 | return res -> { 106 | if (res.failed()) { 107 | manageFailure(msg, res.cause(), includeDebugInfo); 108 | } else { 109 | JsonObject obj = new JsonObject(); 110 | for (Map.Entry chr: res.result().entrySet()) { 111 | obj.put(chr.getKey(), (int) chr.getValue()); 112 | } 113 | msg.reply(obj); 114 | } 115 | }; 116 | } 117 | 118 | public static void manageFailure(Message msg, Throwable cause, boolean includeDebugInfo) { 119 | if (cause instanceof ServiceException) { 120 | msg.reply(cause); 121 | } else { 122 | if (includeDebugInfo) 123 | msg.reply(new ServiceException(-1, cause.getMessage(), generateDebugInfo(cause))); 124 | else 125 | msg.reply(new ServiceException(-1, cause.getMessage())); 126 | } 127 | } 128 | 129 | public static Map convertMap(Map map) { 130 | return (Map)map; 131 | } 132 | 133 | public static List convertList(List list) { 134 | return (List)list; 135 | } 136 | 137 | public static Set convertSet(List list) { 138 | return new HashSet((List)list); 139 | } 140 | 141 | public static JsonObject generateDebugInfo(Throwable cause) { 142 | if (cause == null) return null; 143 | JsonObject obj = new JsonObject(); 144 | obj.put("causeName", cause.getClass().getCanonicalName()); 145 | obj.put("causeMessage", cause.getMessage()); 146 | obj.put("causeStackTrace", convertStackTrace(cause)); 147 | return obj; 148 | } 149 | 150 | public static JsonArray convertStackTrace(Throwable cause) { 151 | if (cause == null || cause.getStackTrace() == null) return new JsonArray(); 152 | return Arrays 153 | .stream(cause.getStackTrace()) 154 | .map(StackTraceElement::toString) 155 | .collect(JsonArray::new, JsonArray::add, JsonArray::addAll); 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/ProxyHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy; 18 | 19 | import io.vertx.core.Handler; 20 | import io.vertx.core.Vertx; 21 | import io.vertx.core.eventbus.EventBus; 22 | import io.vertx.core.eventbus.Message; 23 | import io.vertx.core.eventbus.MessageConsumer; 24 | import io.vertx.core.eventbus.ReplyException; 25 | import io.vertx.core.json.JsonObject; 26 | import io.vertx.serviceproxy.impl.InterceptorHolder; 27 | 28 | import java.util.HashMap; 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.Objects; 32 | 33 | /** 34 | * @author Tim Fox 35 | */ 36 | public abstract class ProxyHandler implements Handler> { 37 | 38 | protected boolean closed; 39 | protected MessageConsumer consumer; 40 | 41 | public void close() { 42 | consumer.unregister(); 43 | closed = true; 44 | } 45 | 46 | /** 47 | * Register the proxy handle on the event bus. 48 | * 49 | * @param eventBus the event bus 50 | * @param address the proxy address 51 | */ 52 | public MessageConsumer register(EventBus eventBus, String address) { 53 | consumer = eventBus.consumer(address, this); 54 | return consumer; 55 | } 56 | 57 | /** 58 | * Register the proxy handle on the event bus. 59 | * 60 | * @param vertx the VertX instance 61 | * @param address the proxy address 62 | * @param interceptorHolders the interceptorHolders 63 | */ 64 | public MessageConsumer register(Vertx vertx, String address, 65 | List interceptorHolders) { 66 | Objects.requireNonNull(interceptorHolders); 67 | Handler> handler = configureHandler(vertx, interceptorHolders); 68 | consumer = vertx.eventBus().consumer(address, handler); 69 | return consumer; 70 | } 71 | 72 | /** 73 | * Register the local proxy handle on the event bus. 74 | * The registration will not be propagated to other nodes in the cluster. 75 | * 76 | * @param eventBus the event bus 77 | * @param address the proxy address 78 | */ 79 | public MessageConsumer registerLocal(EventBus eventBus, String address) { 80 | consumer = eventBus.localConsumer(address, this); 81 | return consumer; 82 | } 83 | 84 | /** 85 | * Register the local proxy handle on the event bus. 86 | * The registration will not be propagated to other nodes in the cluster. 87 | * 88 | * @param vertx the VertX instance 89 | * @param address the proxy address 90 | * @param interceptorHolders the {@link InterceptorHolder} interceptorHolders 91 | */ 92 | public MessageConsumer registerLocal(Vertx vertx, String address, 93 | List interceptorHolders) { 94 | Objects.requireNonNull(interceptorHolders); 95 | Handler> handler = configureHandler(vertx, interceptorHolders); 96 | consumer = vertx.eventBus().localConsumer(address, handler); 97 | return consumer; 98 | } 99 | 100 | private Handler> configureHandler(Vertx vertx, List interceptorHolders) { 101 | Handler> handler = this; 102 | Map context = new HashMap<>(); 103 | // construct the handler backwards, this allows the checks to be performed in the correct order 104 | for (int i = interceptorHolders.size() - 1; i >= 0; i--) { 105 | final InterceptorHolder interceptorHolder = interceptorHolders.get(i); 106 | Handler> prev = handler; 107 | handler = msg -> { 108 | String action = msg.headers().get("action"); 109 | String holderAction = interceptorHolder.action(); 110 | if (holderAction == null || action.equals(holderAction)) { 111 | interceptorHolder.interceptor().intercept(vertx, context, msg) 112 | .onSuccess(prev) 113 | .onFailure(err -> { 114 | ReplyException exception = (ReplyException) err; 115 | msg.fail(exception.failureCode(), exception.getMessage()); 116 | }); 117 | } else { 118 | prev.handle(msg); 119 | } 120 | }; 121 | } 122 | return handler; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/ProxyUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.core.json.JsonArray; 19 | import io.vertx.core.json.JsonObject; 20 | 21 | import java.util.*; 22 | import java.util.function.Function; 23 | import java.util.stream.Collectors; 24 | 25 | /** 26 | * @author Francesco Guardiani @slinkydeveloper 27 | */ 28 | @SuppressWarnings({"unchecked", "rawtypes"}) 29 | public class ProxyUtils { 30 | 31 | public static List convertToListChar(JsonArray arr) { 32 | return arr.stream().map(ProxyUtils::javaObjToChar).collect(Collectors.toList()); 33 | } 34 | 35 | public static Set convertToSetChar(JsonArray arr) { 36 | return arr.stream().map(ProxyUtils::javaObjToChar).collect(Collectors.toSet()); 37 | } 38 | 39 | public static Map convertToMapChar(JsonObject obj) { 40 | return obj.stream().collect(Collectors.toMap(Map.Entry::getKey, e -> javaObjToChar(e.getValue()))); 41 | } 42 | 43 | public static Character javaObjToChar(Object obj) { 44 | Integer jobj = (Integer)obj; 45 | return (char)(int)jobj; 46 | } 47 | 48 | public static Map convertMap(Map map) { 49 | if (map.isEmpty()) { 50 | return (Map) map; 51 | } 52 | 53 | Object elem = map.values().stream().findFirst().get(); 54 | if (!(elem instanceof Map) && !(elem instanceof List)) { 55 | return (Map) map; 56 | } else { 57 | Function converter; 58 | if (elem instanceof List) { 59 | converter = object -> (T) new JsonArray((List) object); 60 | } else { 61 | converter = object -> (T) new JsonObject((Map) object); 62 | } 63 | return ((Map) map).entrySet() 64 | .stream() 65 | .collect(Collectors.toMap(Map.Entry::getKey, converter::apply)); 66 | } 67 | } 68 | 69 | public static List convertList(List list) { 70 | if (list.isEmpty()) { 71 | return (List) list; 72 | } 73 | 74 | Object elem = list.get(0); 75 | if (!(elem instanceof Map) && !(elem instanceof List)) { 76 | return (List) list; 77 | } else { 78 | Function converter; 79 | if (elem instanceof List) { 80 | converter = object -> (T) new JsonArray((List) object); 81 | } else { 82 | converter = object -> (T) new JsonObject((Map) object); 83 | } 84 | return (List) list.stream().map(converter).collect(Collectors.toList()); 85 | } 86 | } 87 | 88 | public static Set convertSet(List list) { 89 | return new HashSet(convertList(list)); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/ServiceBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.core.Future; 19 | import io.vertx.core.Vertx; 20 | import io.vertx.core.eventbus.Message; 21 | import io.vertx.core.eventbus.MessageConsumer; 22 | import io.vertx.core.json.JsonObject; 23 | import io.vertx.serviceproxy.impl.InterceptorHolder; 24 | 25 | import java.lang.reflect.Constructor; 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | import java.util.Objects; 29 | import java.util.function.Function; 30 | 31 | import static io.vertx.serviceproxy.impl.utils.InterceptorUtils.checkInterceptorOrder; 32 | 33 | /** 34 | * A binder for Service Proxies which state can be reused during the binder lifecycle. 35 | * 36 | * @author Paulo Lopes 37 | */ 38 | public class ServiceBinder { 39 | 40 | public static final long DEFAULT_CONNECTION_TIMEOUT = 5 * 60; // 5 minutes 41 | 42 | private final Vertx vertx; 43 | 44 | private String address; 45 | private boolean topLevel = true; 46 | private long timeoutSeconds = DEFAULT_CONNECTION_TIMEOUT; 47 | private List interceptorHolders; 48 | private boolean includeDebugInfo = false; 49 | 50 | /** 51 | * Creates a factory. 52 | * 53 | * @param vertx a non null instance of vertx. 54 | */ 55 | public ServiceBinder(Vertx vertx) { 56 | Objects.requireNonNull(vertx); 57 | 58 | this.vertx = vertx; 59 | } 60 | 61 | /** 62 | * Set the address to use on the subsequent proxy creations or service registrations. 63 | * 64 | * @param address an eventbus address 65 | * @return self 66 | */ 67 | public ServiceBinder setAddress(String address) { 68 | this.address = address; 69 | return this; 70 | } 71 | 72 | /** 73 | * Set if the services to create are a top level services. 74 | * 75 | * @param topLevel true for top level (default: true) 76 | * @return self 77 | */ 78 | public ServiceBinder setTopLevel(boolean topLevel) { 79 | this.topLevel = topLevel; 80 | return this; 81 | } 82 | 83 | /** 84 | * Set the default timeout in seconds while waiting for a reply. 85 | * 86 | * @param timeoutSeconds the default timeout (default: 5 minutes) 87 | * @return self 88 | */ 89 | public ServiceBinder setTimeoutSeconds(long timeoutSeconds) { 90 | this.timeoutSeconds = timeoutSeconds; 91 | return this; 92 | } 93 | 94 | /** 95 | * When an exception is thrown by the service or the underlying handler, include 96 | * debugging info in the ServiceException, that you can access with {@link ServiceException#getDebugInfo()} 97 | * 98 | * @param includeDebugInfo the parameter 99 | * @return self 100 | */ 101 | public ServiceBinder setIncludeDebugInfo(boolean includeDebugInfo) { 102 | this.includeDebugInfo = includeDebugInfo; 103 | return this; 104 | } 105 | 106 | public ServiceBinder addInterceptor(String action, ServiceInterceptor interceptor) { 107 | checkAndAddInterceptor(action, interceptor); 108 | return this; 109 | } 110 | 111 | public ServiceBinder addInterceptor(ServiceInterceptor interceptor) { 112 | checkAndAddInterceptor(interceptor); 113 | return this; 114 | } 115 | 116 | /** 117 | * Registers a service on the event bus. 118 | * 119 | * @param clazz the service class (interface) 120 | * @param service the service object 121 | * @param the type of the service interface 122 | * @return the consumer used to unregister the service 123 | */ 124 | public MessageConsumer register(Class clazz, T service) { 125 | Objects.requireNonNull(address); 126 | // register 127 | return getProxyHandler(clazz, service).register(vertx, address, getInterceptorHolders()); 128 | } 129 | 130 | /** 131 | * Registers a local service on the event bus. 132 | * The registration will not be propagated to other nodes in the cluster. 133 | * 134 | * @param clazz the service class (interface) 135 | * @param service the service object 136 | * @param the type of the service interface 137 | * @return the consumer used to unregister the service 138 | */ 139 | public MessageConsumer registerLocal(Class clazz, T service) { 140 | Objects.requireNonNull(address); 141 | // register 142 | return getProxyHandler(clazz, service).registerLocal(vertx, address, getInterceptorHolders()); 143 | } 144 | 145 | /** 146 | * Unregisters a published service. 147 | * 148 | * @param consumer the consumer returned by {@link #register(Class, Object)}. 149 | */ 150 | public void unregister(MessageConsumer consumer) { 151 | Objects.requireNonNull(consumer); 152 | 153 | if (consumer instanceof ProxyHandler) { 154 | ((ProxyHandler) consumer).close(); 155 | } else { 156 | // Fall back to plain unregister. 157 | consumer.unregister(); 158 | } 159 | } 160 | 161 | /** 162 | * Checks current interceptors correct order and adds a new one if it's OK 163 | * 164 | * @param action interceptor's action 165 | * @param interceptor interceptor to add 166 | */ 167 | private void checkAndAddInterceptor(String action, 168 | ServiceInterceptor interceptor) { 169 | List currentInterceptorHolders = getInterceptorHolders(); 170 | checkInterceptorOrder(currentInterceptorHolders, interceptor); 171 | currentInterceptorHolders.add(new InterceptorHolder(action, interceptor)); 172 | } 173 | 174 | /** 175 | * Checks current interceptors correct order and adds a new one if it's OK 176 | * 177 | * @param interceptor interceptor to add 178 | */ 179 | private void checkAndAddInterceptor(ServiceInterceptor interceptor) { 180 | List currentInterceptorHolders = getInterceptorHolders(); 181 | checkInterceptorOrder(currentInterceptorHolders, interceptor); 182 | currentInterceptorHolders.add(new InterceptorHolder(interceptor)); 183 | } 184 | 185 | private ProxyHandler getProxyHandler(Class clazz, T service) { 186 | String handlerClassName = clazz.getName() + "VertxProxyHandler"; 187 | Class handlerClass = loadClass(handlerClassName, clazz); 188 | Constructor constructor = getConstructor( 189 | handlerClass, Vertx.class, clazz, boolean.class, long.class, boolean.class 190 | ); 191 | Object instance = createInstance(constructor, vertx, service, topLevel, timeoutSeconds, includeDebugInfo); 192 | return (ProxyHandler) instance; 193 | } 194 | 195 | private static Class loadClass(String name, Class origin) { 196 | try { 197 | return origin.getClassLoader().loadClass(name); 198 | } catch (ClassNotFoundException e) { 199 | throw new IllegalStateException("Cannot find proxyClass: " + name, e); 200 | } 201 | } 202 | 203 | private static Constructor getConstructor(Class clazz, Class... types) { 204 | try { 205 | return clazz.getDeclaredConstructor(types); 206 | } catch (NoSuchMethodException e) { 207 | throw new IllegalStateException("Cannot find constructor on: " + clazz.getName(), e); 208 | } 209 | } 210 | 211 | private static Object createInstance(Constructor constructor, Object... args) { 212 | try { 213 | return constructor.newInstance(args); 214 | } catch (Exception e) { 215 | throw new IllegalStateException("Failed to call constructor on", e); 216 | } 217 | } 218 | 219 | private List getInterceptorHolders() { 220 | if (interceptorHolders == null) { 221 | interceptorHolders = new ArrayList<>(); 222 | } 223 | return interceptorHolders; 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/ServiceException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.core.AsyncResult; 19 | import io.vertx.core.Future; 20 | import io.vertx.core.eventbus.ReplyException; 21 | import io.vertx.core.eventbus.ReplyFailure; 22 | import io.vertx.core.json.JsonObject; 23 | 24 | /** 25 | * An Exception to be returned from Service implementations. 26 | * 27 | * @author Dan O'Reilly 28 | */ 29 | public class ServiceException extends ReplyException { 30 | 31 | private final JsonObject debugInfo; 32 | 33 | /** 34 | * Create a ServiceException. 35 | * 36 | * @param failureCode The failure code. 37 | * @param message The failure message. 38 | */ 39 | public ServiceException(int failureCode, String message) { 40 | this(failureCode, message, new JsonObject()); 41 | } 42 | 43 | public ServiceException(int failureCode, String message, JsonObject debugInfo) { 44 | super(ReplyFailure.RECIPIENT_FAILURE, failureCode, message); 45 | this.debugInfo = debugInfo; 46 | 47 | } 48 | 49 | /** 50 | * Get the Debugging information provided to this ServiceException 51 | * 52 | * @return The debug info. 53 | */ 54 | public JsonObject getDebugInfo() { 55 | return debugInfo; 56 | } 57 | 58 | /** 59 | * Create a failed Future containing a ServiceException. 60 | * 61 | * @param failureCode The failure code. 62 | * @param message The failure message. 63 | * @param The type of the AsyncResult. 64 | * @return A failed Future containing the ServiceException. 65 | */ 66 | public static Future fail(int failureCode, String message) { 67 | return Future.failedFuture(new ServiceException(failureCode, message)); 68 | } 69 | 70 | /** 71 | * 72 | * Create a failed Future containing a ServiceException. 73 | * 74 | * @param failureCode The failure code. 75 | * @param message The failure message. 76 | * @param debugInfo The debug info. 77 | * @param The type of the AsyncResult. 78 | * @return A failed Future containing the ServiceException. 79 | */ 80 | public static Future fail(int failureCode, String message, JsonObject debugInfo) { 81 | return Future.failedFuture(new ServiceException(failureCode, message, debugInfo)); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/ServiceExceptionMessageCodec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.core.buffer.Buffer; 19 | import io.vertx.core.eventbus.MessageCodec; 20 | import io.vertx.core.json.JsonObject; 21 | 22 | import java.nio.charset.StandardCharsets; 23 | 24 | /** 25 | * A MessageCodec for ServiceException 26 | * 27 | * @author Dan O'Reilly 28 | */ 29 | public class ServiceExceptionMessageCodec implements MessageCodec { 30 | 31 | @Override 32 | public void encodeToWire(Buffer buffer, ServiceException body) { 33 | buffer.appendInt(body.failureCode()); 34 | if (body.getMessage() == null) { 35 | buffer.appendByte((byte)0); 36 | } else { 37 | buffer.appendByte((byte)1); 38 | byte[] encoded = body.getMessage().getBytes(StandardCharsets.UTF_8); 39 | buffer.appendInt(encoded.length); 40 | buffer.appendBytes(encoded); 41 | } 42 | body.getDebugInfo().writeToBuffer(buffer); 43 | } 44 | 45 | @Override 46 | public ServiceException decodeFromWire(int pos, Buffer buffer) { 47 | int failureCode = buffer.getInt(pos); 48 | pos += 4; 49 | boolean isNull = buffer.getByte(pos) == (byte)0; 50 | pos++; 51 | String message; 52 | if (!isNull) { 53 | int strLength = buffer.getInt(pos); 54 | pos += 4; 55 | byte[] bytes = buffer.getBytes(pos, pos + strLength); 56 | message = new String(bytes, StandardCharsets.UTF_8); 57 | pos += strLength; 58 | } else { 59 | message = null; 60 | } 61 | JsonObject debugInfo = new JsonObject(); 62 | debugInfo.readFromBuffer(pos, buffer); 63 | return new ServiceException(failureCode, message, debugInfo); 64 | } 65 | 66 | @Override 67 | public ServiceException transform(ServiceException exception) { 68 | return exception; 69 | } 70 | 71 | @Override 72 | public String name() { 73 | return "ServiceException"; 74 | } 75 | 76 | @Override 77 | public byte systemCodecID() { 78 | return -1; 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/ServiceInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.codegen.annotations.VertxGen; 19 | import io.vertx.core.Future; 20 | import io.vertx.core.Vertx; 21 | import io.vertx.core.eventbus.Message; 22 | import io.vertx.core.json.JsonObject; 23 | 24 | import java.util.Map; 25 | 26 | @VertxGen 27 | @FunctionalInterface 28 | public interface ServiceInterceptor { 29 | 30 | /** 31 | * Perform the interceptor handling 32 | * 33 | * @param vertx the VertX instance 34 | * @param interceptorContext context to be shared between interceptors 35 | * @param body message body 36 | * @return {@link Future} 37 | */ 38 | Future> intercept(Vertx vertx, Map interceptorContext, Message body); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/ServiceProxyBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy; 17 | 18 | import io.vertx.core.Vertx; 19 | import io.vertx.core.eventbus.DeliveryOptions; 20 | 21 | import java.lang.reflect.Constructor; 22 | import java.util.Objects; 23 | 24 | /** 25 | * A builder for Service Proxies which state can be reused during the builder lifecycle. 26 | * 27 | * @author Paulo Lopes 28 | */ 29 | public class ServiceProxyBuilder { 30 | 31 | private final Vertx vertx; 32 | 33 | private String address; 34 | private DeliveryOptions options; 35 | private String token; 36 | 37 | /** 38 | * Creates a builder. 39 | * 40 | * @param vertx a non null instance of vertx. 41 | */ 42 | public ServiceProxyBuilder(Vertx vertx) { 43 | Objects.requireNonNull(vertx); 44 | 45 | this.vertx = vertx; 46 | } 47 | 48 | /** 49 | * Set the address to use on the subsequent proxy creations or service registrations. 50 | * 51 | * @param address an eventbus address 52 | * @return self 53 | */ 54 | public ServiceProxyBuilder setAddress(String address) { 55 | this.address = address; 56 | return this; 57 | } 58 | 59 | /** 60 | * Set a JWT token to be used on proxy calls. 61 | * 62 | * @param token a JWT token 63 | * @return self 64 | */ 65 | public ServiceProxyBuilder setToken(String token) { 66 | this.token = token; 67 | return this; 68 | } 69 | 70 | /** 71 | * Set delivery options to be used during a proxy call. 72 | * 73 | * @param options delivery options 74 | * @return self 75 | */ 76 | public ServiceProxyBuilder setOptions(DeliveryOptions options) { 77 | this.options = options; 78 | return this; 79 | } 80 | 81 | /** 82 | * Creates a proxy to a service on the event bus. 83 | * 84 | * @param clazz the service class (interface) 85 | * @param the type of the service interface 86 | * @return a proxy to the service 87 | */ 88 | public T build(Class clazz) { 89 | Objects.requireNonNull(address); 90 | 91 | String proxyClassName = clazz.getName() + "VertxEBProxy"; 92 | Class proxyClass = loadClass(proxyClassName, clazz); 93 | Constructor constructor; 94 | Object instance; 95 | 96 | if (token != null) { 97 | if (options == null) { 98 | options = new DeliveryOptions(); 99 | } 100 | options.addHeader("auth-token", token); 101 | } 102 | 103 | if (options == null) { 104 | constructor = getConstructor(proxyClass, Vertx.class, String.class); 105 | instance = createInstance(constructor, vertx, address); 106 | } else { 107 | constructor = getConstructor(proxyClass, Vertx.class, String.class, DeliveryOptions.class); 108 | instance = createInstance(constructor, vertx, address, options); 109 | } 110 | return (T) instance; 111 | } 112 | 113 | private static Class loadClass(String name, Class origin) { 114 | try { 115 | return origin.getClassLoader().loadClass(name); 116 | } catch (ClassNotFoundException e) { 117 | throw new IllegalStateException("Cannot find proxyClass: " + name, e); 118 | } 119 | } 120 | 121 | private static Constructor getConstructor(Class clazz, Class... types) { 122 | try { 123 | return clazz.getDeclaredConstructor(types); 124 | } catch (NoSuchMethodException e) { 125 | throw new IllegalStateException("Cannot find constructor on: " + clazz.getName(), e); 126 | } 127 | } 128 | 129 | private static Object createInstance(Constructor constructor, Object... args) { 130 | try { 131 | return constructor.newInstance(args); 132 | } catch (Exception e) { 133 | throw new IllegalStateException("Failed to call constructor on", e); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/generator/GeneratorUtils.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.generator; 2 | 3 | import io.vertx.codegen.processor.ParamInfo; 4 | import io.vertx.codegen.processor.type.ClassKind; 5 | import io.vertx.codegen.processor.type.ClassTypeInfo; 6 | import io.vertx.codegen.processor.type.MapperInfo; 7 | import io.vertx.codegen.processor.type.ParameterizedTypeInfo; 8 | import io.vertx.serviceproxy.generator.model.ProxyModel; 9 | 10 | import java.io.InputStream; 11 | import java.io.PrintWriter; 12 | import java.nio.charset.StandardCharsets; 13 | import java.util.Scanner; 14 | import java.util.stream.Stream; 15 | 16 | /** 17 | * @author Francesco Guardiani @slinkydeveloper 18 | */ 19 | public class GeneratorUtils { 20 | 21 | final String classHeader; 22 | final String proxyGenImports; 23 | final String handlerGenImports; 24 | final String roger; 25 | final String handlerConstructorBody; 26 | final String handlerCloseAccessed; 27 | 28 | public GeneratorUtils() { 29 | classHeader = loadResource("class_header") + "\n"; 30 | proxyGenImports = loadResource("proxy_gen_import") + "\n"; 31 | handlerGenImports = loadResource("handler_gen_import") + "\n"; 32 | handlerConstructorBody = loadResource("handler_constructor_body") + "\n"; 33 | handlerCloseAccessed = loadResource("handler_close_accessed") + "\n"; 34 | roger = loadResource("roger") + "\n"; 35 | } 36 | 37 | public Stream additionalImports(ProxyModel model) { 38 | return Stream.concat( 39 | Stream 40 | .concat( 41 | model.getImportedTypes().stream(), 42 | model.getReferencedDataObjectTypes() 43 | .stream() 44 | .filter(t -> t.isDataObjectHolder() && t.getDataObject().getJsonType() instanceof ClassTypeInfo) 45 | .map(t -> (ClassTypeInfo) t.getDataObject().getJsonType()) 46 | ) 47 | .filter(c -> !c.getPackageName().equals("java.lang") && !c.getPackageName().equals("io.vertx.core.json")) 48 | .map(ClassTypeInfo::toString), 49 | model.getReferencedTypes() 50 | .stream() 51 | .filter(t -> t.isProxyGen() && !t.getPackageName().equals(model.getIfacePackageName())) 52 | .map(t -> t.getName() + "VertxEBProxy")) 53 | .distinct(); 54 | } 55 | 56 | public void classHeader(PrintWriter w) { 57 | w.print(classHeader); 58 | } 59 | 60 | public void proxyGenImports(PrintWriter w) { 61 | w.print(proxyGenImports); 62 | } 63 | 64 | public void handlerGenImports(PrintWriter w) { w.print(handlerGenImports); } 65 | 66 | public void roger(PrintWriter w) { w.print(roger); } 67 | 68 | public void handlerConstructorBody(PrintWriter w) { w.print(handlerConstructorBody); } 69 | 70 | public void handleCloseAccessed(PrintWriter w) { w.print(handlerCloseAccessed); } 71 | 72 | public void writeImport(PrintWriter w, String i) { 73 | w.print("import " + i + ";\n"); 74 | } 75 | 76 | public String loadResource(String resource) { 77 | return loadResource(resource, "vertx-service-proxy"); 78 | } 79 | 80 | public String loadResource(String resource, String moduleName) { 81 | InputStream input = GeneratorUtils.class.getResourceAsStream("/META-INF/vertx/" + moduleName + "/" + resource + ".txt"); 82 | try (Scanner scanner = new Scanner(input, StandardCharsets.UTF_8.name())) { 83 | return scanner.useDelimiter("\\A").next(); 84 | } 85 | } 86 | 87 | public static String generateDeserializeDataObject(String stmt, ClassTypeInfo doTypeInfo) { 88 | MapperInfo deserializer = doTypeInfo.getDataObject().getDeserializer(); 89 | String s; 90 | switch (deserializer.getKind()) { 91 | case SELF: 92 | s = String.format("new %s((%s)%s)", doTypeInfo.getName(), doTypeInfo.getDataObject().getJsonType().getSimpleName(), stmt); 93 | break; 94 | case STATIC_METHOD: 95 | StringBuilder sb = new StringBuilder(deserializer.getQualifiedName()); 96 | deserializer.getSelectors().forEach(selector -> { 97 | sb.append('.').append(selector); 98 | }); 99 | sb.append("((").append(deserializer.getJsonType().getSimpleName()).append(')').append(stmt).append(')'); 100 | s = sb.toString(); 101 | break; 102 | default: 103 | throw new AssertionError(); 104 | } 105 | return String.format("%s != null ? %s : null", stmt, s); 106 | } 107 | 108 | public static String generateSerializeDataObject(String stmt, ClassTypeInfo doTypeInfo) { 109 | MapperInfo serializer = doTypeInfo.getDataObject().getSerializer(); 110 | StringBuilder sb = new StringBuilder(); 111 | serializer.getSelectors().forEach(selector -> { 112 | sb.append('.').append(selector); 113 | }); 114 | String s; 115 | switch (serializer.getKind()) { 116 | case SELF: 117 | s = stmt + sb + "()"; 118 | break; 119 | case STATIC_METHOD: 120 | s = serializer.getQualifiedName() + sb + "(" + stmt + ")"; 121 | break; 122 | default: 123 | throw new AssertionError(); 124 | } 125 | return String.format("%s != null ? %s : null", stmt, s); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/generator/ServiceProxyGen.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.generator; 2 | 3 | import io.vertx.codegen.processor.Generator; 4 | import io.vertx.codegen.processor.MethodInfo; 5 | import io.vertx.codegen.processor.MethodKind; 6 | import io.vertx.codegen.processor.ParamInfo; 7 | import io.vertx.codegen.processor.TypeParamInfo; 8 | import io.vertx.codegen.annotations.ModuleGen; 9 | import io.vertx.codegen.annotations.ProxyGen; 10 | import io.vertx.codegen.processor.type.*; 11 | import io.vertx.codegen.processor.writer.CodeWriter; 12 | import io.vertx.serviceproxy.generator.model.ProxyMethodInfo; 13 | import io.vertx.serviceproxy.generator.model.ProxyModel; 14 | 15 | import java.io.StringWriter; 16 | import java.lang.annotation.Annotation; 17 | import java.util.*; 18 | 19 | /** 20 | * @author Francesco Guardiani @slinkydeveloper 21 | */ 22 | public class ServiceProxyGen extends Generator { 23 | 24 | final GeneratorUtils utils; 25 | 26 | public ServiceProxyGen(GeneratorUtils utils) { 27 | kinds = Collections.singleton("proxy"); 28 | name = "service_proxy"; 29 | this.utils = utils; 30 | } 31 | 32 | @Override 33 | public Collection> annotations() { 34 | return Arrays.asList(ProxyGen.class, ModuleGen.class); 35 | } 36 | 37 | @Override 38 | public String filename(ProxyModel model) { 39 | return model.getIfaceFQCN() + "VertxEBProxy.java"; 40 | } 41 | 42 | @Override 43 | public String render(ProxyModel model, int index, int size, Map session) { 44 | StringWriter buffer = new StringWriter(); 45 | CodeWriter writer = new CodeWriter(buffer); 46 | 47 | String className = model.getIfaceSimpleName() + "VertxEBProxy"; 48 | 49 | utils.classHeader(writer); 50 | writer.code("package " + model.getIfacePackageName() + ";\n"); 51 | writer.code("\n"); 52 | utils.proxyGenImports(writer); 53 | utils.additionalImports(model).forEach(i -> utils.writeImport(writer, i)); 54 | utils.roger(writer); 55 | writer 56 | .code("@SuppressWarnings({\"unchecked\", \"rawtypes\"})\n") 57 | .code("public class " + className + " implements " + model.getIfaceSimpleName() + " {\n") 58 | .indent() 59 | .stmt("private Vertx _vertx") 60 | .stmt("private String _address") 61 | .stmt("private DeliveryOptions _options") 62 | .stmt("private boolean closed") 63 | .newLine() 64 | .code("public " + className + "(Vertx vertx, String address) {\n") 65 | .indent() 66 | .stmt("this(vertx, address, null)") 67 | .unindent() 68 | .code("}\n") 69 | .newLine() 70 | .code("public " + className + "(Vertx vertx, String address, DeliveryOptions options) {\n") 71 | .indent() 72 | .stmt("this._vertx = vertx") 73 | .stmt("this._address = address") 74 | .stmt("this._options = options") 75 | .code("try {") 76 | .indent() 77 | .stmt("this._vertx.eventBus().registerDefaultCodec(ServiceException.class, new ServiceExceptionMessageCodec())") 78 | .unindent() 79 | .code("} catch (IllegalStateException ex) {\n}") 80 | .unindent() 81 | .code("}\n") 82 | .newLine(); 83 | generateMethods(model, writer); 84 | writer 85 | .unindent() 86 | .code("}\n"); 87 | return buffer.toString(); 88 | } 89 | 90 | private void generateMethods(ProxyModel model, CodeWriter writer) { 91 | for (MethodInfo m : model.getMethods()) { 92 | if (!m.isStaticMethod()) { 93 | writer.code("@Override\n"); 94 | writer.code("public"); 95 | if (!m.getTypeParams().isEmpty()) { 96 | writer.write(" <"); 97 | writer.writeSeq(m.getTypeParams().stream().map(TypeParamInfo::getName), ", "); 98 | writer.write(">"); 99 | } 100 | writer.write(" " + m.getReturnType().getSimpleName() + " " + m.getName() + "("); 101 | writer.writeSeq(m.getParams().stream().map(p -> p.getType().getSimpleName() + " " + p.getName()), ", "); 102 | writer.write("){\n"); 103 | writer.indent(); 104 | if (!((ProxyMethodInfo) m).isProxyIgnore()) generateMethodBody((ProxyMethodInfo) m, writer); 105 | if (m.isFluent()) writer.stmt("return this"); 106 | writer.unindent(); 107 | writer.code("}\n"); 108 | } 109 | } 110 | } 111 | 112 | private void generateMethodBody(ProxyMethodInfo method, CodeWriter writer) { 113 | ParamInfo lastParam = !method.getParams().isEmpty() ? method.getParam(method.getParams().size() - 1) : null; 114 | if (method.getKind() == MethodKind.FUTURE) { 115 | writer.code("if (closed) return io.vertx.core.Future.failedFuture(\"Proxy is closed\");\n"); 116 | } else { 117 | writer.code("if (closed) throw new IllegalStateException(\"Proxy is closed\");\n"); 118 | } 119 | if (method.isProxyClose()) 120 | writer.stmt("closed = true"); 121 | writer.stmt("JsonObject _json = new JsonObject()"); 122 | List paramsExcludedHandler = 123 | (method.getParams().isEmpty()) ? new ArrayList<>() : method.getParams(); 124 | paramsExcludedHandler.forEach(p -> generateAddToJsonStmt(p, writer)); 125 | writer.newLine(); 126 | writer.stmt("DeliveryOptions _deliveryOptions = (_options != null) ? new DeliveryOptions(_options) : new DeliveryOptions()"); 127 | writer.stmt("_deliveryOptions.addHeader(\"action\", \"" + method.getName() + "\")"); 128 | writer.stmt("_deliveryOptions.getHeaders().set(\"action\", \"" + method.getName() + "\")"); 129 | if (method.getKind() == MethodKind.FUTURE) { 130 | TypeInfo t = ((ParameterizedTypeInfo)method.getReturnType()).getArg(0); 131 | generateSendCallWithResultHandler(t, null, writer, true); 132 | } else { 133 | writer.stmt("_vertx.eventBus().send(_address, _json, _deliveryOptions)"); 134 | } 135 | } 136 | 137 | private void generateAddToJsonStmt(ParamInfo param, CodeWriter writer) { 138 | TypeInfo t = param.getType(); 139 | String name = param.getName(); 140 | if ("char".equals(t.getName())) 141 | writer.stmt("_json.put(\"" + name + "\", (int)" + name + ")"); 142 | else if ("java.lang.Character".equals(t.getName())) 143 | writer.stmt("_json.put(\"" + name + "\", " + name + " == null ? null : (int)" + name + ")"); 144 | else if (t.getKind() == ClassKind.ENUM) { 145 | if (t.isDataObjectHolder()) { 146 | writer.stmt(String.format( 147 | "_json.put(\"%s\", %s)", 148 | name, 149 | GeneratorUtils.generateSerializeDataObject(name, (ClassTypeInfo) t) 150 | )); 151 | } else { 152 | writer.stmt("_json.put(\"" + name + "\", " + name + " == null ? null : " + name + ".name())"); 153 | } 154 | } 155 | else if (t.getKind() == ClassKind.LIST) { 156 | if (((ParameterizedTypeInfo)t).getArg(0).isDataObjectHolder()) { 157 | ClassTypeInfo doType = (ClassTypeInfo) ((ParameterizedTypeInfo) t).getArg(0); 158 | writer.stmt(String.format( 159 | "_json.put(\"%s\", new JsonArray(%s == null ? java.util.Collections.emptyList() : %s.stream().map(v -> %s).collect(Collectors.toList())))", 160 | name, 161 | name, 162 | name, 163 | GeneratorUtils.generateSerializeDataObject("v", doType) 164 | )); 165 | } else 166 | writer.stmt("_json.put(\"" + name + "\", new JsonArray(" + name + "))"); 167 | } else if (t.getKind() == ClassKind.SET) { 168 | if (((ParameterizedTypeInfo)t).getArg(0).isDataObjectHolder()) { 169 | ClassTypeInfo doType = (ClassTypeInfo) ((ParameterizedTypeInfo) t).getArg(0); 170 | writer.stmt(String.format( 171 | "_json.put(\"%s\", new JsonArray(%s == null ? java.util.Collections.emptyList() : %s.stream().map(v -> %s).collect(Collectors.toList())))", 172 | name, 173 | name, 174 | name, 175 | GeneratorUtils.generateSerializeDataObject("v", doType) 176 | )); 177 | } else 178 | writer.stmt("_json.put(\"" + name + "\", new JsonArray(new ArrayList<>(" + name + ")))"); 179 | } else if (t.getKind() == ClassKind.MAP) { 180 | if (((ParameterizedTypeInfo)t).getArg(1).isDataObjectHolder()) { 181 | ClassTypeInfo doType = (ClassTypeInfo) ((ParameterizedTypeInfo) t).getArg(1); 182 | writer.stmt(String.format( 183 | "_json.put(\"%s\", new JsonObject(%s == null ? java.util.Collections.emptyMap() : %s.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> %s))))", 184 | name, 185 | name, 186 | name, 187 | GeneratorUtils.generateSerializeDataObject("e.getValue()", doType) 188 | )); 189 | } else { 190 | writer.stmt("_json.put(\"" + name + "\", new JsonObject(ProxyUtils.convertMap(" + name + ")))"); 191 | } 192 | } 193 | else if (t.isDataObjectHolder()) { 194 | writer.stmt(String.format( 195 | "_json.put(\"%s\", %s)", 196 | name, 197 | GeneratorUtils.generateSerializeDataObject(name, (ClassTypeInfo) t) 198 | )); 199 | } else 200 | writer.stmt("_json.put(\"" + name + "\", " + name + ")"); 201 | } 202 | 203 | private void generateSendCallWithResultHandler(TypeInfo futurType, String name, CodeWriter writer, boolean promise) { 204 | wrapResult(futurType, name, promise, writer); 205 | } 206 | 207 | private void wrapResult(TypeInfo t, String name, boolean promise, CodeWriter writer) { 208 | if (promise) { 209 | writer.print("return "); 210 | } 211 | writer 212 | .print("_vertx.eventBus().<" + sendTypeParameter(t) + ">request(_address, _json, _deliveryOptions"); 213 | if (promise) { 214 | writer.println(").map(msg -> {"); 215 | writer.indent(); 216 | writer.print("return "); 217 | } else { 218 | writer.println(").onComplete(res -> {"); 219 | writer.indent() 220 | .code("if (res.failed()) {\n") 221 | .indent(); 222 | writer.stmt(name + ".handle(Future.failedFuture(res.cause()))"); 223 | writer.unindent() 224 | .code("} else {\n") 225 | .indent(); 226 | 227 | writer.print(name + ".handle(Future.succeededFuture("); 228 | } 229 | String resultStr = promise ? "msg" : "res.result()"; 230 | 231 | if (t.getKind() == ClassKind.LIST) { 232 | if ("java.lang.Character".equals(((ParameterizedTypeInfo) t).getArg(0).getName())) 233 | writer.print("ProxyUtils.convertToListChar(" + resultStr + ".body())"); 234 | else if (((ParameterizedTypeInfo) t).getArg(0).isDataObjectHolder()) { 235 | ClassTypeInfo doType = (ClassTypeInfo) ((ParameterizedTypeInfo) t).getArg(0); 236 | writer.print(resultStr + ".body().stream()\n"); 237 | writer.indent() 238 | .codeln(".map(v -> " + GeneratorUtils.generateDeserializeDataObject("v", doType) + ")") 239 | .code(".collect(Collectors.toList())") 240 | .unindent(); 241 | } else { 242 | writer.print("ProxyUtils.convertList(" + resultStr + ".body().getList())"); 243 | } 244 | } else if (t.getKind() == ClassKind.SET) { 245 | if ("java.lang.Character".equals(((ParameterizedTypeInfo)t).getArg(0).getName())) 246 | writer.print("ProxyUtils.convertToSetChar(" + resultStr + ".body())"); 247 | else if (((ParameterizedTypeInfo)t).getArg(0).isDataObjectHolder()) { 248 | ClassTypeInfo doType = (ClassTypeInfo) ((ParameterizedTypeInfo) t).getArg(0); 249 | writer.print(resultStr + ".body().stream()\n"); 250 | writer.indent() 251 | .codeln(".map(v -> " + GeneratorUtils.generateDeserializeDataObject("v", doType) + ")") 252 | .code(".collect(Collectors.toSet())") 253 | .unindent(); 254 | } else { 255 | writer.print("ProxyUtils.convertSet(" + resultStr + ".body().getList())"); 256 | } 257 | } else if (t.getKind() == ClassKind.MAP) { 258 | if ("java.lang.Character".equals(((ParameterizedTypeInfo)t).getArg(1).getName())) 259 | writer.print("ProxyUtils.convertToMapChar(" + resultStr + ".body())"); 260 | else if (((ParameterizedTypeInfo)t).getArg(1).isDataObjectHolder()) { 261 | ClassTypeInfo doType = (ClassTypeInfo) ((ParameterizedTypeInfo) t).getArg(1); 262 | writer.print(resultStr + ".body().stream()\n"); 263 | writer.indent() 264 | .code(".collect(Collectors.toMap(Map.Entry::getKey, e -> " + GeneratorUtils.generateDeserializeDataObject("e.getValue()", doType) + "))") 265 | .unindent(); 266 | } else { 267 | writer.print("ProxyUtils.convertMap(" + resultStr + ".body().getMap())"); 268 | } 269 | } else if (t.getKind() == ClassKind.API && t instanceof ApiTypeInfo && ((ApiTypeInfo)t).isProxyGen()) { 270 | writer.print("new " + t.getSimpleName() + "VertxEBProxy(_vertx, " + resultStr + ".headers().get(\"proxyaddr\"))"); 271 | } else if (t.isDataObjectHolder()) 272 | writer.print(GeneratorUtils.generateDeserializeDataObject(resultStr + ".body()", (ClassTypeInfo) t)); 273 | else if (t.getKind() == ClassKind.ENUM) 274 | writer.print(resultStr + ".body() == null ? null : " + t.getSimpleName() + ".valueOf(" + resultStr + ".body())"); 275 | else 276 | writer.print(resultStr + ".body()"); 277 | 278 | if (promise) { 279 | writer.println(";"); 280 | } else { 281 | writer.println("));"); 282 | } 283 | 284 | if (!promise) { 285 | writer 286 | .unindent() 287 | .code("}\n"); 288 | } 289 | 290 | writer.unindent() 291 | .code("});\n"); 292 | 293 | } 294 | 295 | private String sendTypeParameter(TypeInfo t) { 296 | if (t.getKind() == ClassKind.LIST || t.getKind() == ClassKind.SET) return "JsonArray"; 297 | if (t.getKind() == ClassKind.MAP) return "JsonObject"; 298 | if (t.isDataObjectHolder()) return t.getDataObject().getJsonType().getSimpleName(); 299 | if (t.getKind() == ClassKind.ENUM) return "String"; 300 | return t.getSimpleName(); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/generator/ServiceProxyGenLoader.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.generator; 2 | 3 | import io.vertx.codegen.processor.Generator; 4 | import io.vertx.codegen.processor.GeneratorLoader; 5 | 6 | import javax.annotation.processing.ProcessingEnvironment; 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * @author Francesco Guardiani @slinkydeveloper 11 | */ 12 | public class ServiceProxyGenLoader implements GeneratorLoader { 13 | 14 | @Override 15 | public Stream> loadGenerators(ProcessingEnvironment processingEnv) { 16 | GeneratorUtils utils = new GeneratorUtils(); 17 | return Stream.of(new ServiceProxyHandlerGen(utils), new ServiceProxyGen(utils)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/generator/model/ProxyMethodInfo.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.generator.model; 2 | 3 | /* 4 | * Copyright 2014 Red Hat, Inc. 5 | * 6 | * All rights reserved. This program and the accompanying materials 7 | * are made available under the terms of the Eclipse Public License v1.0 8 | * and Apache License v2.0 which accompanies this distribution. 9 | * 10 | * The Eclipse Public License is available at 11 | * http://www.eclipse.org/legal/epl-v10.html 12 | * 13 | * The Apache License v2.0 is available at 14 | * http://www.opensource.org/licenses/apache2.0.php 15 | * 16 | * You may elect to redistribute this code under either of these licenses. 17 | */ 18 | 19 | import io.vertx.codegen.processor.MethodInfo; 20 | import io.vertx.codegen.processor.ParamInfo; 21 | import io.vertx.codegen.processor.TypeParamInfo; 22 | import io.vertx.codegen.processor.doc.Doc; 23 | import io.vertx.codegen.processor.doc.Text; 24 | import io.vertx.codegen.processor.type.ClassTypeInfo; 25 | import io.vertx.codegen.processor.type.TypeInfo; 26 | 27 | import java.util.List; 28 | import java.util.Set; 29 | 30 | /** 31 | * @author Tim Fox 32 | */ 33 | public class ProxyMethodInfo extends MethodInfo { 34 | 35 | private final boolean proxyIgnore; 36 | private final boolean proxyClose; 37 | 38 | public ProxyMethodInfo(Set ownerTypes, String name, TypeInfo returnType, Text returnDescription, boolean fluent, 39 | boolean cacheReturn, List params, String comment, Doc doc, boolean staticMethod, boolean defaultMethod, 40 | List typeParams, boolean proxyIgnore, boolean proxyClose, boolean deprecated, Text deprecatedDesc, boolean methodOverride) { 41 | 42 | 43 | super(ownerTypes, name, returnType, returnDescription, fluent, cacheReturn, params, comment, doc, staticMethod, defaultMethod, typeParams, deprecated, deprecatedDesc, methodOverride); 44 | this.proxyIgnore = proxyIgnore; 45 | this.proxyClose = proxyClose; 46 | } 47 | 48 | public boolean isProxyIgnore() { 49 | return proxyIgnore; 50 | } 51 | 52 | public boolean isProxyClose() { 53 | return proxyClose; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/generator/model/ProxyModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.generator.model; 18 | 19 | import io.vertx.codegen.processor.*; 20 | import io.vertx.codegen.annotations.ProxyClose; 21 | import io.vertx.codegen.annotations.ProxyIgnore; 22 | import io.vertx.codegen.processor.doc.Doc; 23 | import io.vertx.codegen.processor.doc.Text; 24 | import io.vertx.codegen.processor.type.*; 25 | 26 | import javax.annotation.processing.ProcessingEnvironment; 27 | import javax.lang.model.element.AnnotationMirror; 28 | import javax.lang.model.element.ExecutableElement; 29 | import javax.lang.model.element.Modifier; 30 | import javax.lang.model.element.TypeElement; 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | import java.util.Map; 34 | import java.util.Set; 35 | 36 | /** 37 | * @author Tim Fox 38 | */ 39 | public class ProxyModel extends ClassModel { 40 | 41 | public ProxyModel(ProcessingEnvironment env, TypeMirrorFactory typeFactory, TypeElement modelElt) { 42 | super(env, typeFactory, modelElt); 43 | } 44 | 45 | @Override 46 | public String getKind() { 47 | return "proxy"; 48 | } 49 | 50 | @Override 51 | protected void checkParamType(ExecutableElement elem, TypeInfo typeInfo, int pos, int numParams) { 52 | // Basic types, int, long, String etc 53 | // JsonObject or JsonArray 54 | if (typeInfo.getKind().basic || typeInfo.getKind().json) { 55 | return; 56 | } 57 | // We also allow enums as parameter types 58 | if (typeInfo.getKind() == ClassKind.ENUM) { 59 | return; 60 | } 61 | if (isLegalContainerParam(typeInfo)) { 62 | return; 63 | } 64 | // We also allow data object as parameter types if they have a complete codec 65 | if (typeInfo.isDataObjectHolder()) { 66 | if (typeInfo.getDataObject().isSerializable() && typeInfo.getDataObject().isDeserializable()){ 67 | return; 68 | } 69 | throw new GenException(elem, "Data Object " + typeInfo + " must have a valid serializer and deserializer"); 70 | } 71 | if (elem.getModifiers().contains(Modifier.STATIC)) { 72 | // Ignore static methods - we won't use them anyway 73 | return; 74 | } 75 | throw new GenException(elem, "type " + typeInfo + " is not legal for use for a parameter in proxy"); 76 | } 77 | 78 | @Override 79 | protected void checkReturnType(ExecutableElement elem, TypeInfo type) { 80 | if (elem.getModifiers().contains(Modifier.STATIC)) { 81 | // Ignore static methods - we won't use them anyway 82 | return; 83 | } 84 | if (type.isVoid() || type.getName().startsWith("io.vertx.core.Future")) { 85 | return; 86 | } 87 | throw new GenException(elem, "Proxy methods must return Future"); 88 | } 89 | 90 | @Override 91 | protected void checkMethod(MethodInfo methodInfo) { 92 | // We don't allow overloaded methods in proxies 93 | List methodsByName = methodMap.get(methodInfo.getName()); 94 | if (methodsByName != null && methodsByName.size() > 1) { 95 | throw new GenException(this.modelElt, "Overloaded methods are not allowed in ProxyGen interfaces " + methodInfo.getName()); 96 | } 97 | } 98 | 99 | @Override 100 | protected MethodInfo createMethodInfo(Set ownerTypes, String methodName, String comment, Doc doc, TypeInfo returnType, Text returnDescription, boolean isFluent, boolean isCacheReturn, List mParams, ExecutableElement methodElt, boolean isStatic, boolean isDefault, ArrayList typeParams, TypeElement declaringElt, boolean methodDeprecated, Text methodDeprecatedDesc, boolean methodOverride) { 101 | AnnotationMirror proxyIgnoreAnnotation = Helper.resolveMethodAnnotation(ProxyIgnore.class, elementUtils, typeUtils, declaringElt, methodElt); 102 | boolean isProxyIgnore = proxyIgnoreAnnotation != null; 103 | AnnotationMirror proxyCloseAnnotation = Helper.resolveMethodAnnotation(ProxyClose.class, elementUtils, typeUtils, declaringElt, methodElt); 104 | boolean isProxyClose = proxyCloseAnnotation != null; 105 | ProxyMethodInfo proxyMeth = new ProxyMethodInfo(ownerTypes, methodName, returnType, returnDescription, 106 | isFluent, isCacheReturn, mParams, comment, doc, isStatic, isDefault, typeParams, isProxyIgnore, 107 | isProxyClose, methodDeprecated, methodDeprecatedDesc, methodOverride); 108 | if (isProxyClose) { 109 | if (mParams.size() > 0) { 110 | throw new GenException(this.modelElt, "@ProxyClose methods can't have parameters"); 111 | } 112 | if (proxyMeth.getReturnType().getKind() == ClassKind.FUTURE) { 113 | TypeInfo type = proxyMeth.getReturnType(); 114 | TypeInfo arg = (((ParameterizedTypeInfo) type).getArgs().get(0)); 115 | if (arg.getKind() != ClassKind.VOID) { 116 | throw new GenException(this.modelElt, "@ProxyClose must return Future instead of " + type); 117 | } 118 | } 119 | } 120 | return proxyMeth; 121 | } 122 | 123 | private boolean isLegalAsyncResultType(TypeInfo resultType) { 124 | if (resultType.getKind().json || resultType.getKind().basic || 125 | isLegalContainerParam(resultType) || resultType.getKind() == ClassKind.VOID || 126 | resultType.getKind() == ClassKind.ENUM || resultType.isDataObjectHolder()) { 127 | return true; 128 | } 129 | if (resultType.getKind() == ClassKind.API) { 130 | ApiTypeInfo cla = (ApiTypeInfo)resultType; 131 | if (cla.isProxyGen()) { 132 | return true; 133 | } 134 | } 135 | return false; 136 | } 137 | 138 | private boolean isLegalContainerParam(TypeInfo type) { 139 | TypeInfo raw = type.getRaw(); 140 | if (raw.getName().equals(List.class.getName()) || raw.getName().equals(Set.class.getName())) { 141 | TypeInfo argument = ((ParameterizedTypeInfo) type).getArgs().get(0); 142 | if (argument.getKind().basic || argument.getKind().json || isValidDataObject(argument)) { 143 | return true; 144 | } 145 | } else if (raw.getName().equals(Map.class.getName())) { 146 | TypeInfo argument0 = ((ParameterizedTypeInfo) type).getArgs().get(0); 147 | if (!argument0.getName().equals(String.class.getName())) { 148 | return false; 149 | } 150 | TypeInfo argument1 = ((ParameterizedTypeInfo) type).getArgs().get(1); 151 | if (argument1.getKind().basic || argument1.getKind().json || isValidDataObject(argument1)) { 152 | return true; 153 | } 154 | } 155 | return false; 156 | } 157 | 158 | private boolean isValidDataObject(TypeInfo typeInfo) { 159 | return typeInfo.isDataObjectHolder() && typeInfo.getDataObject().isSerializable() && typeInfo.getDataObject().isDeserializable(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/generator/model/ProxyModelProvider.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.generator.model; 2 | 3 | import io.vertx.codegen.processor.Model; 4 | import io.vertx.codegen.processor.ModelProvider; 5 | import io.vertx.codegen.annotations.ProxyGen; 6 | import io.vertx.codegen.processor.type.TypeMirrorFactory; 7 | 8 | import javax.annotation.processing.ProcessingEnvironment; 9 | import javax.lang.model.element.TypeElement; 10 | 11 | public class ProxyModelProvider implements ModelProvider { 12 | @Override 13 | public Model getModel(ProcessingEnvironment env, TypeMirrorFactory typeFactory, TypeElement elt) { 14 | if (elt.getAnnotation(ProxyGen.class) != null) { 15 | ProxyModel model = new ProxyModel(env, typeFactory, elt); 16 | return model; 17 | } else { 18 | return null; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/impl/AuthenticationInterceptorImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy.impl; 17 | 18 | import io.vertx.core.Future; 19 | import io.vertx.core.Vertx; 20 | import io.vertx.core.eventbus.Message; 21 | import io.vertx.core.eventbus.ReplyException; 22 | import io.vertx.core.eventbus.ReplyFailure; 23 | import io.vertx.core.internal.ContextInternal; 24 | import io.vertx.core.json.JsonObject; 25 | import io.vertx.ext.auth.authentication.AuthenticationProvider; 26 | import io.vertx.ext.auth.authentication.CredentialValidationException; 27 | import io.vertx.ext.auth.authentication.TokenCredentials; 28 | import io.vertx.serviceproxy.AuthenticationInterceptor; 29 | 30 | import java.util.Map; 31 | 32 | /** 33 | * Create an event bus service interceptor that will provide an authentication check 34 | */ 35 | public class AuthenticationInterceptorImpl implements AuthenticationInterceptor { 36 | 37 | //an authentication authenticationProvider that will verify all requests before the service is invoked. 38 | final AuthenticationProvider authenticationProvider; 39 | 40 | public AuthenticationInterceptorImpl(AuthenticationProvider authenticationProvider) { 41 | this.authenticationProvider = authenticationProvider; 42 | } 43 | 44 | @Override 45 | public Future> intercept(Vertx vertx, Map interceptorContext, 46 | Message body) { 47 | final ContextInternal vertxContext = (ContextInternal) vertx.getOrCreateContext(); 48 | final TokenCredentials tokenCredentials = new TokenCredentials(body.headers().get("auth-token")); 49 | try { 50 | tokenCredentials.checkValid(null); 51 | if (authenticationProvider == null) { 52 | return vertxContext.failedFuture( 53 | new ReplyException(ReplyFailure.RECIPIENT_FAILURE, 500, "No AuthenticationProvider present")); 54 | } 55 | return authenticationProvider.authenticate(tokenCredentials) 56 | .recover(err -> vertxContext.failedFuture( 57 | new ReplyException(ReplyFailure.RECIPIENT_FAILURE, 500, err.getMessage()))) 58 | .compose(user -> { 59 | if (user == null) { 60 | return vertxContext.failedFuture(new ReplyException(ReplyFailure.RECIPIENT_FAILURE, 401, "User is null")); 61 | } 62 | //authentication succeeded 63 | interceptorContext.put("user", user); 64 | return vertxContext.succeededFuture(body); 65 | }); 66 | } catch (CredentialValidationException e) { 67 | return Future.failedFuture(new ReplyException(ReplyFailure.RECIPIENT_FAILURE, 401, e.getMessage())); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/impl/AuthorizationInterceptorImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy.impl; 17 | 18 | import io.vertx.core.Future; 19 | import io.vertx.core.Vertx; 20 | import io.vertx.core.eventbus.Message; 21 | import io.vertx.core.eventbus.ReplyException; 22 | import io.vertx.core.eventbus.ReplyFailure; 23 | import io.vertx.core.internal.ContextInternal; 24 | import io.vertx.core.json.JsonObject; 25 | import io.vertx.ext.auth.User; 26 | import io.vertx.ext.auth.authorization.Authorization; 27 | import io.vertx.ext.auth.authorization.AuthorizationContext; 28 | import io.vertx.ext.auth.authorization.AuthorizationProvider; 29 | import io.vertx.serviceproxy.AuthorizationInterceptor; 30 | 31 | import java.util.HashSet; 32 | import java.util.Map; 33 | import java.util.Set; 34 | 35 | /** 36 | * Create an event bus service interceptor that will provide an authorization check 37 | */ 38 | public class AuthorizationInterceptorImpl implements AuthorizationInterceptor { 39 | private final AuthorizationProvider authorizationProvider; 40 | 41 | private Set authorizations; 42 | 43 | public AuthorizationInterceptorImpl(AuthorizationProvider authorizationProvider) { 44 | this.authorizationProvider = authorizationProvider; 45 | } 46 | 47 | /** 48 | * Set the required authorities for the service, once a JWT is validated it will be 49 | * queried for these authorities. If authorities are missing a error 403 is returned. 50 | * 51 | * @param authorizations set of authorities 52 | * @return self 53 | */ 54 | @Override 55 | public AuthorizationInterceptorImpl setAuthorizations(Set authorizations) { 56 | this.authorizations = authorizations; 57 | return this; 58 | } 59 | 60 | /** 61 | * Add a single authority to the authorities set. 62 | * 63 | * @param authorization authority 64 | * @return self 65 | */ 66 | @Override 67 | public AuthorizationInterceptorImpl addAuthorization(Authorization authorization) { 68 | if (authorizations == null) { 69 | authorizations = new HashSet<>(); 70 | } 71 | authorizations.add(authorization); 72 | return this; 73 | } 74 | 75 | @Override 76 | public Future> intercept(Vertx vertx, Map interceptorContext, 77 | Message body) { 78 | final ContextInternal vertxContext = (ContextInternal) vertx.getOrCreateContext(); 79 | //for some reasons user hasn't been added neither by authn interceptor nor somehow else 80 | if (!interceptorContext.containsKey("user")) { 81 | return vertxContext.succeededFuture(body); 82 | } 83 | if (authorizations == null || authorizations.isEmpty()) { 84 | return vertxContext.succeededFuture(body); 85 | } 86 | User user = (User) interceptorContext.get("user"); 87 | return authorizationProvider.getAuthorizations(user) 88 | .recover(err -> vertxContext.failedFuture( 89 | new ReplyException(ReplyFailure.RECIPIENT_FAILURE, 500, err.getMessage()))) 90 | .compose(voidResult -> { 91 | AuthorizationContext userAuthorizationContext = AuthorizationContext.create(user); 92 | for (Authorization authorization : authorizations) { 93 | // authorization failed 94 | if (!authorization.match(userAuthorizationContext)) { 95 | return vertxContext.failedFuture(new ReplyException(ReplyFailure.RECIPIENT_FAILURE, 403, "Forbidden")); 96 | } 97 | } 98 | // all authorities have passed 99 | return vertxContext.succeededFuture(body); 100 | }); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/impl/InterceptorHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy.impl; 17 | 18 | import io.vertx.serviceproxy.ServiceInterceptor; 19 | 20 | public class InterceptorHolder { 21 | 22 | private final String action; 23 | 24 | private final ServiceInterceptor interceptor; 25 | 26 | public InterceptorHolder(String action, ServiceInterceptor interceptor) { 27 | this.action = action; 28 | this.interceptor = interceptor; 29 | } 30 | 31 | public InterceptorHolder(ServiceInterceptor interceptor) { 32 | this.action = null; 33 | this.interceptor = interceptor; 34 | } 35 | 36 | public String action() { 37 | return action; 38 | } 39 | 40 | public ServiceInterceptor interceptor() { 41 | return interceptor; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/impl/InterceptorPriority.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy.impl; 17 | 18 | /** 19 | * Defines an interceptor priority to apply them in right order 20 | */ 21 | public enum InterceptorPriority { 22 | 23 | AUTHENTICATION, 24 | AUTHORIZATION, 25 | USER 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/impl/utils/InterceptorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | package io.vertx.serviceproxy.impl.utils; 17 | 18 | import io.vertx.serviceproxy.AuthenticationInterceptor; 19 | import io.vertx.serviceproxy.AuthorizationInterceptor; 20 | import io.vertx.serviceproxy.impl.InterceptorHolder; 21 | import io.vertx.serviceproxy.ServiceInterceptor; 22 | import io.vertx.serviceproxy.impl.InterceptorPriority; 23 | 24 | import java.util.List; 25 | 26 | public class InterceptorUtils { 27 | 28 | private InterceptorUtils() { 29 | throw new UnsupportedOperationException(); 30 | } 31 | 32 | /** 33 | * Returns interceptor's weight according to the class instance 34 | * 35 | * @param interceptor interceptor to define 36 | * @return {@link InterceptorPriority} 37 | */ 38 | public static InterceptorPriority getWeight(ServiceInterceptor interceptor) { 39 | if (interceptor instanceof AuthenticationInterceptor) { 40 | return InterceptorPriority.AUTHENTICATION; 41 | } 42 | if (interceptor instanceof AuthorizationInterceptor) { 43 | return InterceptorPriority.AUTHORIZATION; 44 | } 45 | 46 | return InterceptorPriority.USER; 47 | } 48 | 49 | /** 50 | * Checks if interceptors are adding in the right priority (according to the {@link InterceptorPriority}). 51 | * If not, throws an {@link IllegalStateException} 52 | * 53 | * @param interceptorHolders current interceptor holders 54 | * @param interceptor interceptor to add 55 | */ 56 | public static void checkInterceptorOrder(List interceptorHolders, 57 | ServiceInterceptor interceptor) { 58 | if (interceptorHolders.isEmpty()) { 59 | return; 60 | } 61 | final InterceptorPriority weight = getWeight(interceptor); 62 | final InterceptorPriority lastWeight; 63 | lastWeight = getWeight(interceptorHolders.get(interceptorHolders.size() - 1).interceptor()); 64 | if (lastWeight.ordinal() > weight.ordinal()) { 65 | String message = String.format("Cannot add [%s] interceptor to service binder, please check adding order!", 66 | weight.name()); 67 | throw new IllegalStateException(message); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/vertx/serviceproxy/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | @ModuleGen(name = "vertx-service-proxy", groupPackage = "io.vertx") 18 | package io.vertx.serviceproxy; 19 | 20 | import io.vertx.codegen.annotations.ModuleGen; 21 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module io.vertx.serviceproxy { 2 | 3 | requires static io.vertx.auth.jwt; 4 | requires static io.vertx.docgen; 5 | 6 | requires io.vertx.codegen.api; 7 | requires io.vertx.codegen.processor; 8 | requires io.vertx.core; 9 | requires java.compiler; 10 | 11 | exports io.vertx.serviceproxy; 12 | exports io.vertx.serviceproxy.generator; 13 | exports io.vertx.serviceproxy.generator.model; 14 | exports io.vertx.serviceproxy.impl to io.vertx.serviceproxy.tests; 15 | exports io.vertx.serviceproxy.impl.utils to io.vertx.serviceproxy.tests; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/io.vertx.codegen.processor.GeneratorLoader: -------------------------------------------------------------------------------- 1 | io.vertx.serviceproxy.generator.ServiceProxyGenLoader 2 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/io.vertx.codegen.processor.ModelProvider: -------------------------------------------------------------------------------- 1 | io.vertx.serviceproxy.generator.model.ProxyModelProvider 2 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/vertx/vertx-service-proxy/class_header.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * Red Hat licenses this file to you under the Apache License, version 2.0 5 | * (the "License"); you may not use this file except in compliance with the 6 | * License. You may obtain a copy of the License at: 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/vertx/vertx-service-proxy/handler_close_accessed.txt: -------------------------------------------------------------------------------- 1 | @Override 2 | public void close() { 3 | if (timerID != -1) { 4 | vertx.cancelTimer(timerID); 5 | } 6 | super.close(); 7 | } 8 | 9 | private void accessed() { 10 | this.lastAccessed = System.nanoTime(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/vertx/vertx-service-proxy/handler_constructor_body.txt: -------------------------------------------------------------------------------- 1 | this.vertx = vertx; 2 | this.service = service; 3 | this.includeDebugInfo = includeDebugInfo; 4 | this.timeoutSeconds = timeoutSeconds; 5 | try { 6 | this.vertx.eventBus().registerDefaultCodec(ServiceException.class, 7 | new ServiceExceptionMessageCodec()); 8 | } catch (IllegalStateException ex) {} 9 | if (timeoutSeconds != -1 && !topLevel) { 10 | long period = timeoutSeconds * 1000 / 2; 11 | if (period > 10000) { 12 | period = 10000; 13 | } 14 | this.timerID = vertx.setPeriodic(period, this::checkTimedOut); 15 | } else { 16 | this.timerID = -1; 17 | } 18 | accessed(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/vertx/vertx-service-proxy/handler_gen_import.txt: -------------------------------------------------------------------------------- 1 | import io.vertx.core.Vertx; 2 | import io.vertx.core.Handler; 3 | import io.vertx.core.AsyncResult; 4 | import io.vertx.core.eventbus.EventBus; 5 | import io.vertx.core.eventbus.Message; 6 | import io.vertx.core.eventbus.MessageConsumer; 7 | import io.vertx.core.eventbus.DeliveryOptions; 8 | import io.vertx.core.eventbus.ReplyException; 9 | import io.vertx.core.json.JsonObject; 10 | import io.vertx.core.json.JsonArray; 11 | import java.util.Collection; 12 | import java.util.ArrayList; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | import java.util.Map; 16 | import java.util.Set; 17 | import java.util.UUID; 18 | import java.util.stream.Collectors; 19 | import io.vertx.serviceproxy.ProxyHandler; 20 | import io.vertx.serviceproxy.ServiceException; 21 | import io.vertx.serviceproxy.ServiceExceptionMessageCodec; 22 | import io.vertx.serviceproxy.HelperUtils; 23 | import io.vertx.serviceproxy.ServiceBinder; 24 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/vertx/vertx-service-proxy/proxy_gen_import.txt: -------------------------------------------------------------------------------- 1 | import io.vertx.core.eventbus.DeliveryOptions; 2 | import io.vertx.core.Vertx; 3 | import io.vertx.core.Future; 4 | import io.vertx.core.json.JsonObject; 5 | import io.vertx.core.json.JsonArray; 6 | import java.util.ArrayList; 7 | import java.util.HashSet; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Set; 11 | import java.util.stream.Collectors; 12 | import java.util.function.Function; 13 | import io.vertx.serviceproxy.ServiceException; 14 | import io.vertx.serviceproxy.ServiceExceptionMessageCodec; 15 | import io.vertx.serviceproxy.ProxyUtils; 16 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/vertx/vertx-service-proxy/roger.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Generated Proxy code - DO NOT EDIT 3 | @author Roger the Robot 4 | */ 5 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/FuturizedServiceProxyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests; 18 | 19 | import io.vertx.core.eventbus.MessageConsumer; 20 | import io.vertx.core.json.JsonObject; 21 | import io.vertx.serviceproxy.ServiceBinder; 22 | import io.vertx.serviceproxy.tests.testmodel2.FuturizedTestService; 23 | import io.vertx.test.core.VertxTestBase; 24 | import org.junit.Test; 25 | 26 | import java.net.URI; 27 | 28 | /** 29 | */ 30 | public class FuturizedServiceProxyTest extends VertxTestBase { 31 | 32 | public final static String SERVICE_ADDRESS = "someaddress"; 33 | public final static String SERVICE_WITH_DEBUG_ADDRESS = "someaddressdebug"; 34 | public final static String SERVICE_LOCAL_ADDRESS = "someaddress.local"; 35 | public final static String TEST_ADDRESS = "testaddress"; 36 | 37 | MessageConsumer consumer, localConsumer, consumerWithDebugEnabled; 38 | FuturizedTestService service, localService; 39 | FuturizedTestService proxy, localProxy, proxyWithDebug; 40 | URI uri1, uri2; 41 | 42 | @Override 43 | public void setUp() throws Exception { 44 | super.setUp(); 45 | uri1 = new URI("http://foo.com"); 46 | uri2 = new URI("http://bar.com"); 47 | service = FuturizedTestService.create(vertx); 48 | localService = FuturizedTestService.create(vertx); 49 | 50 | consumer = new ServiceBinder(vertx).setAddress(SERVICE_ADDRESS) 51 | .register(FuturizedTestService.class, service); 52 | consumerWithDebugEnabled = new ServiceBinder(vertx) 53 | .setAddress(SERVICE_WITH_DEBUG_ADDRESS) 54 | .setIncludeDebugInfo(true) 55 | .register(FuturizedTestService.class, service); 56 | localConsumer = new ServiceBinder(vertx).setAddress(SERVICE_LOCAL_ADDRESS) 57 | .registerLocal(FuturizedTestService.class, localService); 58 | 59 | proxy = FuturizedTestService.createProxy(vertx, SERVICE_ADDRESS); 60 | localProxy = FuturizedTestService.createProxy(vertx, SERVICE_LOCAL_ADDRESS); 61 | proxyWithDebug = FuturizedTestService.createProxy(vertx, SERVICE_WITH_DEBUG_ADDRESS); 62 | vertx.eventBus().consumer(TEST_ADDRESS).handler(msg -> { 63 | assertEquals("ok", msg.body()); 64 | testComplete(); 65 | }); 66 | } 67 | 68 | @Override 69 | public void tearDown() throws Exception { 70 | consumer.unregister(); 71 | localConsumer.unregister(); 72 | super.tearDown(); 73 | } 74 | 75 | 76 | @Test 77 | public void testStringHandler() { 78 | proxy.ok().onSuccess(res -> { 79 | assertEquals("foobar", res); 80 | testComplete(); 81 | }); 82 | await(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/SecureServiceBinderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests; 18 | 19 | import io.vertx.core.AsyncResult; 20 | import io.vertx.core.eventbus.MessageConsumer; 21 | import io.vertx.core.eventbus.ReplyException; 22 | import io.vertx.core.json.JsonObject; 23 | import io.vertx.ext.auth.KeyStoreOptions; 24 | import io.vertx.ext.auth.authorization.PermissionBasedAuthorization; 25 | import io.vertx.ext.auth.jwt.JWTAuth; 26 | import io.vertx.ext.auth.jwt.JWTAuthOptions; 27 | import io.vertx.ext.auth.jwt.authorization.JWTAuthorization; 28 | import io.vertx.serviceproxy.AuthenticationInterceptor; 29 | import io.vertx.serviceproxy.AuthorizationInterceptor; 30 | import io.vertx.serviceproxy.ServiceBinder; 31 | import io.vertx.serviceproxy.ServiceProxyBuilder; 32 | import io.vertx.serviceproxy.tests.testmodel.OKService; 33 | import io.vertx.serviceproxy.tests.testmodel.OKServiceImpl; 34 | import io.vertx.test.core.VertxTestBase; 35 | import org.junit.Test; 36 | 37 | import java.time.LocalDateTime; 38 | import java.time.ZoneOffset; 39 | 40 | public class SecureServiceBinderTest extends VertxTestBase { 41 | 42 | private final static String SERVICE_ADDRESS = "someaddress"; 43 | private final static String SERVICE_LOCAL_ADDRESS = "someaddress.local"; 44 | 45 | private static final String JWT_CLAIMS = "{\"sub\":\"Paulo\",\"exp\":1747055313,\"iat\":1431695313,\"permissions\":[\"read\",\"write\",\"execute\"],\"roles\":[\"admin\",\"developer\",\"user\"]}"; 46 | 47 | private ServiceProxyBuilder serviceProxyBuilder, localServiceProxyBuilder; 48 | private MessageConsumer consumer, localConsumer; 49 | private OKService proxy, localProxy; 50 | private final long exp = LocalDateTime.now().plusDays(1).toEpochSecond(ZoneOffset.UTC); 51 | private String jwtValidToken; 52 | 53 | private JWTAuthOptions getJWTConfig() { 54 | return new JWTAuthOptions() 55 | .setKeyStore(new KeyStoreOptions() 56 | .setPath("keystore.jceks") 57 | .setType("jceks") 58 | .setPassword("secret")); 59 | } 60 | 61 | @Override 62 | public void setUp() throws Exception { 63 | super.setUp(); 64 | 65 | JWTAuth authProvider = JWTAuth.create(vertx, getJWTConfig()); 66 | jwtValidToken = authProvider.generateToken(new JsonObject(JWT_CLAIMS).put("exp", exp)); 67 | 68 | OKService service = new OKServiceImpl(); 69 | 70 | ServiceBinder serviceBinder = new ServiceBinder(vertx) 71 | .setAddress(SERVICE_ADDRESS) 72 | .addInterceptor( 73 | AuthenticationInterceptor.create(authProvider)) 74 | .addInterceptor( 75 | AuthorizationInterceptor.create(JWTAuthorization.create("roles")) 76 | // an admin 77 | .addAuthorization(PermissionBasedAuthorization.create("admin")) 78 | ) 79 | .addInterceptor( 80 | AuthorizationInterceptor.create(JWTAuthorization.create("permissions")) 81 | // that can write 82 | .addAuthorization(PermissionBasedAuthorization.create("write")) 83 | ); 84 | 85 | ServiceBinder localServiceBinder = new ServiceBinder(vertx) 86 | .setAddress(SERVICE_LOCAL_ADDRESS) 87 | .addInterceptor( 88 | AuthenticationInterceptor.create(authProvider)) 89 | .addInterceptor( 90 | AuthorizationInterceptor.create(JWTAuthorization.create("roles")) 91 | // an admin 92 | .addAuthorization(PermissionBasedAuthorization.create("admin")) 93 | ) 94 | .addInterceptor( 95 | AuthorizationInterceptor.create(JWTAuthorization.create("permissions")) 96 | // that can write 97 | .addAuthorization(PermissionBasedAuthorization.create("write")) 98 | ); 99 | 100 | consumer = serviceBinder.register(OKService.class, service); 101 | localConsumer = localServiceBinder.registerLocal(OKService.class, service); 102 | 103 | serviceProxyBuilder = new ServiceProxyBuilder(vertx) 104 | .setAddress(SERVICE_ADDRESS); 105 | 106 | localServiceProxyBuilder = new ServiceProxyBuilder(vertx) 107 | .setAddress(SERVICE_LOCAL_ADDRESS); 108 | } 109 | 110 | @Override 111 | public void tearDown() throws Exception { 112 | consumer.unregister(); 113 | localConsumer.unregister(); 114 | super.tearDown(); 115 | } 116 | 117 | @Test 118 | public void testWithToken() { 119 | 120 | serviceProxyBuilder.setToken(jwtValidToken); 121 | 122 | proxy = serviceProxyBuilder.build(OKService.class); 123 | 124 | proxy.ok().onComplete(res -> { 125 | assertFalse(res.failed()); 126 | testComplete(); 127 | }); 128 | await(); 129 | } 130 | 131 | @Test 132 | public void testWithoutToken() { 133 | 134 | serviceProxyBuilder.setToken(null); 135 | 136 | proxy = serviceProxyBuilder.build(OKService.class); 137 | 138 | proxy.ok().onComplete(this::checkResult); 139 | await(); 140 | } 141 | 142 | @Test 143 | public void testLocalWithToken() { 144 | 145 | localServiceProxyBuilder.setToken(jwtValidToken); 146 | 147 | localProxy = localServiceProxyBuilder.build(OKService.class); 148 | 149 | localProxy.ok().onComplete(res -> { 150 | assertFalse(res.failed()); 151 | testComplete(); 152 | }); 153 | await(); 154 | } 155 | 156 | @Test 157 | public void testLocalWithoutToken() { 158 | 159 | localServiceProxyBuilder.setToken(null); 160 | 161 | localProxy = localServiceProxyBuilder.build(OKService.class); 162 | 163 | localProxy.ok().onComplete(this::checkResult); 164 | await(); 165 | } 166 | 167 | private void checkResult(AsyncResult res) { 168 | assertTrue(res.failed()); 169 | ReplyException t = (ReplyException) res.cause(); 170 | assertEquals(401, t.failureCode()); 171 | testComplete(); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/ServiceBinderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests; 18 | 19 | import io.vertx.core.eventbus.MessageConsumer; 20 | import io.vertx.core.json.JsonObject; 21 | import io.vertx.serviceproxy.ServiceBinder; 22 | import io.vertx.serviceproxy.ServiceProxyBuilder; 23 | import io.vertx.serviceproxy.tests.testmodel.OKService; 24 | import io.vertx.serviceproxy.tests.testmodel.OKServiceImpl; 25 | import io.vertx.test.core.VertxTestBase; 26 | import org.junit.Test; 27 | 28 | public class ServiceBinderTest extends VertxTestBase { 29 | 30 | private final static String SERVICE_ADDRESS = "someaddress"; 31 | private final static String SERVICE_LOCAL_ADDRESS = "someaddress.local"; 32 | 33 | private MessageConsumer consumer, localConsumer; 34 | private OKService proxy, localProxy; 35 | 36 | @Override 37 | public void setUp() throws Exception { 38 | super.setUp(); 39 | OKService service = new OKServiceImpl(); 40 | 41 | final ServiceBinder serviceBinder = new ServiceBinder(vertx).setAddress(SERVICE_ADDRESS); 42 | final ServiceBinder serviceLocalBinder = new ServiceBinder(vertx).setAddress(SERVICE_LOCAL_ADDRESS); 43 | final ServiceProxyBuilder serviceProxyBuilder = new ServiceProxyBuilder(vertx).setAddress(SERVICE_ADDRESS); 44 | final ServiceProxyBuilder serviceLocalProxyBuilder = new ServiceProxyBuilder(vertx).setAddress(SERVICE_LOCAL_ADDRESS); 45 | 46 | consumer = serviceBinder.register(OKService.class, service); 47 | localConsumer = serviceLocalBinder.registerLocal(OKService.class, service); 48 | proxy = serviceProxyBuilder.build(OKService.class); 49 | localProxy = serviceLocalProxyBuilder.build(OKService.class); 50 | } 51 | 52 | @Override 53 | public void tearDown() throws Exception { 54 | consumer.unregister(); 55 | localConsumer.unregister(); 56 | super.tearDown(); 57 | } 58 | 59 | @Test 60 | public void testFactory() { 61 | proxy.ok().onComplete(res -> { 62 | assertFalse(res.failed()); 63 | testComplete(); 64 | }); 65 | await(); 66 | } 67 | 68 | @Test 69 | public void testLocalFactory() { 70 | localProxy.ok().onComplete(res -> { 71 | assertFalse(res.failed()); 72 | testComplete(); 73 | }); 74 | await(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/clustered/ClusteredTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.clustered; 2 | 3 | import io.vertx.core.Vertx; 4 | import io.vertx.core.VertxOptions; 5 | import io.vertx.core.eventbus.ReplyException; 6 | import io.vertx.core.eventbus.ReplyFailure; 7 | import io.vertx.core.json.JsonArray; 8 | import io.vertx.core.json.JsonObject; 9 | import io.vertx.serviceproxy.ServiceException; 10 | import io.vertx.serviceproxy.tests.testmodel.*; 11 | import io.vertx.test.fakecluster.FakeClusterManager; 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | 15 | import java.util.Arrays; 16 | import java.util.List; 17 | import java.util.concurrent.TimeUnit; 18 | import java.util.concurrent.atomic.AtomicReference; 19 | 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | import static org.junit.Assert.*; 22 | 23 | /** 24 | * @author Clement Escoffier 25 | */ 26 | public class ClusteredTest { 27 | 28 | private Vertx producerNode; 29 | private Vertx consumerNode; 30 | 31 | @Before 32 | public void setUp() throws Exception { 33 | VertxOptions options = new VertxOptions(); 34 | options.getEventBusOptions().setHost("127.0.0.1"); 35 | producerNode = Vertx.builder() 36 | .with(options) 37 | .withClusterManager(new FakeClusterManager()) 38 | .buildClustered() 39 | .await(20, TimeUnit.SECONDS); 40 | producerNode.eventBus().registerDefaultCodec(MyServiceException.class, new MyServiceExceptionMessageCodec()); 41 | producerNode.deployVerticle(ServiceProviderVerticle.class.getName()); 42 | producerNode.deployVerticle(LocalServiceProviderVerticle.class.getName()); 43 | consumerNode = Vertx.builder() 44 | .with(options) 45 | .withClusterManager(new FakeClusterManager()) 46 | .buildClustered() 47 | .await(20, TimeUnit.SECONDS); 48 | consumerNode.eventBus().registerDefaultCodec(MyServiceException.class, new MyServiceExceptionMessageCodec()); 49 | } 50 | 51 | 52 | @Test 53 | public void testHello() throws Exception { 54 | Service service = Service.createProxy(consumerNode, "my.service"); 55 | String res = service.hello("vert.x").await(20, TimeUnit.SECONDS); 56 | assertEquals("hello vert.x", res); 57 | } 58 | 59 | @Test 60 | public void testEnumAsParameter() throws Exception { 61 | Service service = Service.createProxy(consumerNode, "my.service"); 62 | Boolean res = service.methodUsingEnum(SomeEnum.WIBBLE).await(20, TimeUnit.SECONDS); 63 | assertNotNull(res); 64 | assertTrue(res); 65 | } 66 | 67 | @Test 68 | public void testEnumAsResult() throws Exception { 69 | AtomicReference result = new AtomicReference<>(); 70 | Service service = Service.createProxy(consumerNode, "my.service"); 71 | SomeEnum res = service.methodReturningEnum().await(20, TimeUnit.SECONDS); 72 | assertEquals(SomeEnum.WIBBLE, res); 73 | } 74 | 75 | @Test 76 | public void testVertxEnumAsResult() throws Exception { 77 | Service service = Service.createProxy(consumerNode, "my.service"); 78 | SomeVertxEnum res = service.methodReturningVertxEnum().await(20, TimeUnit.SECONDS); 79 | assertEquals(SomeVertxEnum.BAR, res); 80 | } 81 | 82 | @Test 83 | public void testWithDataObject() throws Exception { 84 | Service service = Service.createProxy(consumerNode, "my.service"); 85 | TestDataObject data = new TestDataObject().setBool(true).setNumber(25).setString("vert.x"); 86 | TestDataObject out = service.methodWithDataObject(data).await(20, TimeUnit.SECONDS); 87 | assertThat(out.getNumber()).isEqualTo(25); 88 | assertThat(out.isBool()).isTrue(); 89 | assertThat(out.getString()).isEqualTo("vert.x"); 90 | } 91 | 92 | @Test 93 | public void testWithListOfDataObject() throws Exception { 94 | Service service = Service.createProxy(consumerNode, "my.service"); 95 | TestDataObject data = new TestDataObject().setBool(true).setNumber(25).setString("vert.x"); 96 | TestDataObject data2 = new TestDataObject().setBool(true).setNumber(26).setString("vert.x"); 97 | List out = service.methodWithListOfDataObject(Arrays.asList(data, data2)).await(20, TimeUnit.SECONDS); 98 | assertThat(out.get(0).getNumber()).isEqualTo(25); 99 | assertThat(out.get(0).isBool()).isTrue(); 100 | assertThat(out.get(0).getString()).isEqualTo("vert.x"); 101 | assertThat(out.get(1).getNumber()).isEqualTo(26); 102 | assertThat(out.get(1).isBool()).isTrue(); 103 | assertThat(out.get(1).getString()).isEqualTo("vert.x"); 104 | } 105 | 106 | @Test 107 | public void testWithStringDataObject() throws Exception { 108 | Service service = Service.createProxy(consumerNode, "my.service"); 109 | StringDataObject data = new StringDataObject().setValue("vert.x"); 110 | StringDataObject out = service.methodWithStringDataObject(data).await(20, TimeUnit.SECONDS); 111 | assertThat(out.getValue()).isEqualTo("vert.x"); 112 | } 113 | 114 | @Test 115 | public void testWithListOfStringDataObject() throws Exception { 116 | Service service = Service.createProxy(consumerNode, "my.service"); 117 | StringDataObject data = new StringDataObject().setValue("vert.x-1"); 118 | StringDataObject data2 = new StringDataObject().setValue("vert.x-2"); 119 | List out = service.methodWithListOfStringDataObject(Arrays.asList(data, data2)).await(20, TimeUnit.SECONDS); 120 | assertThat(out.get(0).getValue()).isEqualTo("vert.x-1"); 121 | assertThat(out.get(1).getValue()).isEqualTo("vert.x-2"); 122 | } 123 | 124 | @Test 125 | public void testWithListOfJsonObject() throws Exception { 126 | Service service = Service.createProxy(consumerNode, "my.service"); 127 | TestDataObject data = new TestDataObject().setBool(true).setNumber(25).setString("vert.x"); 128 | TestDataObject data2 = new TestDataObject().setBool(true).setNumber(26).setString("vert.x"); 129 | List out = service.methodWithListOfJsonObject(Arrays.asList(data.toJson(), data2.toJson())).await(20, TimeUnit.SECONDS); 130 | TestDataObject out0 = new TestDataObject(out.get(0)); 131 | TestDataObject out1 = new TestDataObject(out.get(1)); 132 | assertThat(out0.getNumber()).isEqualTo(25); 133 | assertThat(out0.isBool()).isTrue(); 134 | assertThat(out0.getString()).isEqualTo("vert.x"); 135 | assertThat(out1.getNumber()).isEqualTo(26); 136 | assertThat(out1.isBool()).isTrue(); 137 | assertThat(out1.getString()).isEqualTo("vert.x"); 138 | } 139 | 140 | @Test 141 | public void testWithJsonObject() throws Exception { 142 | Service service = Service.createProxy(consumerNode, "my.service"); 143 | TestDataObject data = new TestDataObject().setBool(true).setNumber(25).setString("vert.x"); 144 | TestDataObject out = new TestDataObject(service.methodWithJsonObject(data.toJson()).await(20, TimeUnit.SECONDS)); 145 | assertThat(out.getNumber()).isEqualTo(25); 146 | assertThat(out.isBool()).isTrue(); 147 | assertThat(out.getString()).isEqualTo("vert.x"); 148 | } 149 | 150 | @Test 151 | public void testWithJsonArray() throws Exception { 152 | Service service = Service.createProxy(consumerNode, "my.service"); 153 | TestDataObject data = new TestDataObject().setBool(true).setNumber(25).setString("vert.x"); 154 | JsonArray array = new JsonArray(); 155 | array.add("vert.x").add(data.toJson()); 156 | TestDataObject out = new TestDataObject(service.methodWithJsonArray(array).await(20, TimeUnit.SECONDS).getJsonObject(1)); 157 | assertThat(array.getString(0)).isEqualToIgnoringCase("vert.x"); 158 | assertThat(out.getNumber()).isEqualTo(25); 159 | assertThat(out.isBool()).isTrue(); 160 | assertThat(out.getString()).isEqualTo("vert.x"); 161 | } 162 | 163 | @Test 164 | public void testWithFailingResult() throws Exception { 165 | Service service = Service.createProxy(consumerNode, "my.service"); 166 | try { 167 | service.methodWthFailingResult("Fail").await(20, TimeUnit.SECONDS); 168 | fail(); 169 | } catch (ServiceException cause) { 170 | assertThat(cause.failureCode()).isEqualTo(30); 171 | assertThat(cause.getDebugInfo()).isEqualTo(new JsonObject().put("test", "val")); 172 | } 173 | } 174 | 175 | @Test 176 | public void testWithFailingResultServiceExceptionSubclass() throws Exception { 177 | Service service = Service.createProxy(consumerNode, "my.service"); 178 | try { 179 | service.methodWthFailingResult("cluster Fail").await(20, TimeUnit.SECONDS); 180 | fail(); 181 | } catch (MyServiceException cause) { 182 | assertThat(cause.failureCode()).isEqualTo(30); 183 | assertThat(cause.getExtra()).isEqualTo("some extra"); 184 | } 185 | } 186 | 187 | @Test 188 | public void testLocalServiceShouldBeUnreachable() throws Exception { 189 | Service service = Service.createProxy(consumerNode, "my.local.service"); 190 | try { 191 | service.hello("vert.x").await(20, TimeUnit.SECONDS); 192 | } catch (ReplyException cause) { 193 | assertThat(cause.failureType()).isEqualTo(ReplyFailure.NO_HANDLERS); 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/clustered/LocalServiceProviderVerticle.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.clustered; 2 | 3 | import io.vertx.core.AbstractVerticle; 4 | import io.vertx.serviceproxy.ServiceBinder; 5 | 6 | /** 7 | * @author Michal Boska 8 | */ 9 | public class LocalServiceProviderVerticle extends AbstractVerticle { 10 | 11 | @Override 12 | public void start() throws Exception { 13 | new ServiceBinder(vertx).setAddress("my.local.service").registerLocal(Service.class, new ServiceProvider()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/clustered/Service.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.clustered; 2 | 3 | 4 | import java.util.List; 5 | 6 | import io.vertx.codegen.annotations.ProxyGen; 7 | import io.vertx.codegen.annotations.VertxGen; 8 | import io.vertx.core.Future; 9 | import io.vertx.core.Vertx; 10 | import io.vertx.core.json.JsonArray; 11 | import io.vertx.core.json.JsonObject; 12 | import io.vertx.serviceproxy.tests.testmodel.SomeEnum; 13 | import io.vertx.serviceproxy.tests.testmodel.SomeEnumWithCustomConstructor; 14 | import io.vertx.serviceproxy.tests.testmodel.SomeVertxEnum; 15 | import io.vertx.serviceproxy.tests.testmodel.StringDataObject; 16 | import io.vertx.serviceproxy.tests.testmodel.TestDataObject; 17 | 18 | /** 19 | * @author Clement Escoffier 20 | */ 21 | @ProxyGen 22 | @VertxGen 23 | public interface Service { 24 | 25 | static Service createProxy(Vertx vertx, String address) { 26 | return new ServiceVertxEBProxy(vertx, address); 27 | } 28 | 29 | Future hello(String name); 30 | 31 | Future methodUsingEnum(SomeEnum e); 32 | 33 | Future methodReturningEnum(); 34 | 35 | Future methodReturningVertxEnum(); 36 | 37 | Future methodUsingCustomEnum(SomeEnumWithCustomConstructor e); 38 | 39 | Future methodReturningCustomEnum(); 40 | 41 | Future methodWithJsonObject(JsonObject json); 42 | 43 | Future methodWithJsonArray(JsonArray json); 44 | 45 | Future> methodWithList(List list); 46 | 47 | Future methodWithDataObject(TestDataObject data); 48 | 49 | Future> methodWithListOfDataObject(List list); 50 | 51 | Future methodWithStringDataObject(StringDataObject data); 52 | 53 | Future> methodWithListOfStringDataObject(List list); 54 | 55 | 56 | Future> methodWithListOfJsonObject(List list); 57 | 58 | Future methodWthFailingResult(String input); 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/clustered/ServiceProvider.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.clustered; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.json.JsonArray; 5 | import io.vertx.core.json.JsonObject; 6 | import io.vertx.serviceproxy.ServiceException; 7 | import io.vertx.serviceproxy.tests.testmodel.MyServiceException; 8 | import io.vertx.serviceproxy.tests.testmodel.SomeEnum; 9 | import io.vertx.serviceproxy.tests.testmodel.SomeEnumWithCustomConstructor; 10 | import io.vertx.serviceproxy.tests.testmodel.SomeVertxEnum; 11 | import io.vertx.serviceproxy.tests.testmodel.StringDataObject; 12 | import io.vertx.serviceproxy.tests.testmodel.TestDataObject; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * @author Clement Escoffier 18 | */ 19 | public class ServiceProvider implements Service { 20 | 21 | @Override 22 | public Future hello(String name) { 23 | return Future.succeededFuture("hello " + name); 24 | } 25 | 26 | @Override 27 | public Future methodUsingEnum(SomeEnum e) { 28 | if (e == SomeEnum.WIBBLE) { 29 | return Future.succeededFuture(true); 30 | } else { 31 | return Future.succeededFuture(false); 32 | } 33 | } 34 | 35 | @Override 36 | public Future methodReturningEnum() { 37 | return Future.succeededFuture(SomeEnum.WIBBLE); 38 | } 39 | 40 | @Override 41 | public Future methodReturningVertxEnum() { 42 | return Future.succeededFuture(SomeVertxEnum.BAR); 43 | } 44 | 45 | @Override 46 | public Future methodWithJsonObject(JsonObject json) { 47 | return Future.succeededFuture(json); 48 | } 49 | 50 | @Override 51 | public Future methodWithJsonArray(JsonArray json) { 52 | return Future.succeededFuture(json); 53 | } 54 | 55 | @Override 56 | public Future> methodWithList(List list) { 57 | return Future.succeededFuture(list); 58 | } 59 | 60 | @Override 61 | public Future methodWithDataObject(TestDataObject data) { 62 | return Future.succeededFuture(data); 63 | } 64 | 65 | @Override 66 | public Future> methodWithListOfDataObject(List list) { 67 | return Future.succeededFuture(list); 68 | } 69 | 70 | @Override 71 | public Future methodWithStringDataObject(StringDataObject data) { 72 | return Future.succeededFuture(data); 73 | } 74 | 75 | @Override 76 | public Future> methodWithListOfStringDataObject(List list) { 77 | return Future.succeededFuture(list); 78 | } 79 | 80 | @Override 81 | public Future> methodWithListOfJsonObject(List list) { 82 | return Future.succeededFuture(list); 83 | } 84 | 85 | @Override 86 | public Future methodWthFailingResult(String input) { 87 | if (input.equals("Fail")) { 88 | return ServiceException.fail(30, "failed!", new JsonObject().put("test", "val")); 89 | } else { 90 | return MyServiceException.fail(30, "failed!", "some extra"); 91 | } 92 | } 93 | 94 | @Override 95 | public Future methodUsingCustomEnum(SomeEnumWithCustomConstructor e) { 96 | if (e == SomeEnumWithCustomConstructor.ITEST) { 97 | return Future.succeededFuture(true); 98 | } else { 99 | return Future.succeededFuture(false); 100 | } 101 | } 102 | 103 | @Override 104 | public Future methodReturningCustomEnum() { 105 | return Future.succeededFuture(SomeEnumWithCustomConstructor.DEV); 106 | } 107 | 108 | /*@Override 109 | public Service methodWithMapOfJsonObject(Map map, Handler>> result) { 110 | result.handle(Future.succeededFuture(map)); 111 | return this; 112 | }*/ 113 | } 114 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/clustered/ServiceProviderVerticle.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.clustered; 2 | 3 | import io.vertx.core.AbstractVerticle; 4 | import io.vertx.serviceproxy.ServiceBinder; 5 | 6 | /** 7 | * @author Clement Escoffier 8 | */ 9 | public class ServiceProviderVerticle extends AbstractVerticle { 10 | 11 | 12 | @Override 13 | public void start() throws Exception { 14 | new ServiceBinder(vertx).setAddress("my.service").register(Service.class, new ServiceProvider()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/clustered/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Julien Viet 3 | */ 4 | @ModuleGen(name = "test", groupPackage = "io.vertx") 5 | package io.vertx.serviceproxy.tests.clustered; 6 | 7 | import io.vertx.codegen.annotations.ModuleGen; 8 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/ProxyTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen; 2 | 3 | import io.vertx.codegen.processor.*; 4 | import io.vertx.codegen.processor.type.ClassKind; 5 | import io.vertx.codegen.processor.type.ParameterizedTypeInfo; 6 | import io.vertx.codegen.processor.type.TypeInfo; 7 | import io.vertx.serviceproxy.tests.codegen.future.FuturizedProxy; 8 | import io.vertx.serviceproxy.tests.codegen.proxytestapi.*; 9 | import io.vertx.serviceproxy.generator.model.ProxyMethodInfo; 10 | import io.vertx.serviceproxy.generator.model.ProxyModel; 11 | import io.vertx.serviceproxy.tests.testmodel.Mappers; 12 | import io.vertx.test.codegen.GeneratorHelper; 13 | import org.junit.Test; 14 | 15 | import java.time.ZonedDateTime; 16 | 17 | import static org.junit.Assert.*; 18 | 19 | /** 20 | * @author Tim Fox 21 | */ 22 | public class ProxyTest { 23 | 24 | public ProxyModel generateProxyModel(Class c, Class... rest) throws Exception { 25 | return new GeneratorHelper() 26 | .registerConverter(ZonedDateTime.class, Mappers.class, "serializeZonedDateTime") 27 | .registerConverter(ZonedDateTime.class, Mappers.class, "deserializeZonedDateTime") 28 | .generateClass(codegen -> (ProxyModel) codegen.getModel(c.getCanonicalName(), "proxy"), c, rest); 29 | } 30 | 31 | 32 | // Test invalid stuff 33 | // ------------------ 34 | 35 | // Invalid classes 36 | 37 | @Test 38 | public void testInvalidOverloaded() throws Exception { 39 | try { 40 | generateProxyModel(InvalidOverloaded.class); 41 | fail("Should throw exception"); 42 | } catch (GenException e) { 43 | // OK 44 | } 45 | } 46 | 47 | @Test 48 | public void testInvalidParams1() throws Exception { 49 | try { 50 | generateProxyModel(InvalidParams1.class); 51 | fail("Should throw exception"); 52 | } catch (GenException e) { 53 | // OK 54 | } 55 | } 56 | 57 | @Test 58 | public void testInvalidParams2() throws Exception { 59 | try { 60 | generateProxyModel(InvalidParams2.class); 61 | fail("Should throw exception"); 62 | } catch (GenException e) { 63 | // OK 64 | } 65 | } 66 | 67 | @Test 68 | public void testInvalidParams3() throws Exception { 69 | try { 70 | generateProxyModel(InvalidParams3.class); 71 | fail("Should throw exception"); 72 | } catch (GenException e) { 73 | // OK 74 | } 75 | } 76 | 77 | @Test 78 | public void testInvalidParams4() throws Exception { 79 | try { 80 | generateProxyModel(InvalidParams4.class); 81 | fail("Should throw exception"); 82 | } catch (GenException e) { 83 | // OK 84 | } 85 | } 86 | 87 | @Test 88 | public void testInvalidParamsDataObject() throws Exception { 89 | try { 90 | generateProxyModel(InvalidParamsDataObject.class); 91 | fail("Should throw exception"); 92 | } catch (GenException e) { 93 | // OK 94 | } 95 | } 96 | 97 | @Test 98 | public void testInvalidReturn1() throws Exception { 99 | try { 100 | generateProxyModel(InvalidReturn1.class); 101 | fail("Should throw exception"); 102 | } catch (GenException e) { 103 | // OK 104 | } 105 | } 106 | 107 | @Test 108 | public void testInvalidReturn2() throws Exception { 109 | try { 110 | generateProxyModel(InvalidReturn2.class); 111 | fail("Should throw exception"); 112 | } catch (GenException e) { 113 | // OK 114 | } 115 | } 116 | 117 | @Test 118 | public void testInvalidReturn3() throws Exception { 119 | try { 120 | generateProxyModel(InvalidReturn3.class); 121 | fail("Should throw exception"); 122 | } catch (GenException e) { 123 | // OK 124 | } 125 | } 126 | 127 | @Test 128 | public void testValid() throws Exception { 129 | ProxyModel model = generateProxyModel(ValidProxy.class); 130 | assertEquals(ValidProxy.class.getName(), model.getIfaceFQCN()); 131 | assertEquals(ValidProxy.class.getSimpleName(), model.getIfaceSimpleName()); 132 | assertTrue(model.getSuperTypes().isEmpty()); 133 | assertEquals(52, model.getMethods().size()); 134 | 135 | // Not going to check all the types are correct as this is already tested in the VertxGen tests 136 | // but we do want to check the proxyIgnore flag is correctly set 137 | for (MethodInfo mi: model.getMethods()) { 138 | ProxyMethodInfo pmi = (ProxyMethodInfo)mi; 139 | if (pmi.getName().equals("ignored")) { 140 | assertTrue(pmi.isProxyIgnore()); 141 | } else { 142 | assertFalse(pmi.isProxyIgnore()); 143 | } 144 | if (pmi.getName().equals("closeIt")) { 145 | assertTrue(pmi.isProxyClose()); 146 | } else { 147 | assertFalse(pmi.isProxyClose()); 148 | } 149 | } 150 | } 151 | 152 | @Test 153 | public void testValidCloseWithFuture() throws Exception { 154 | ProxyModel model = generateProxyModel(ValidProxyCloseWithFuture.class); 155 | assertEquals(1, model.getMethods().size()); 156 | assertEquals(MethodKind.FUTURE, model.getMethods().get(0).getKind()); 157 | ParameterizedTypeInfo handlerType = (ParameterizedTypeInfo) model.getMethods().get(0).getReturnType(); 158 | TypeInfo asyncResultType = handlerType.getArgs().get(0); 159 | assertEquals(ClassKind.VOID, asyncResultType.getKind()); 160 | } 161 | 162 | @Test 163 | public void testInvalidClose1() throws Exception { 164 | try { 165 | generateProxyModel(InvalidClose1.class); 166 | fail("Should throw exception"); 167 | } catch (GenException e) { 168 | // OK 169 | } 170 | } 171 | 172 | @Test 173 | public void testInvalidClose2() throws Exception { 174 | try { 175 | generateProxyModel(InvalidClose2.class); 176 | fail("Should throw exception"); 177 | } catch (GenException e) { 178 | // OK 179 | } 180 | } 181 | 182 | @Test 183 | public void testInvalidClose3() throws Exception { 184 | try { 185 | generateProxyModel(InvalidClose3.class); 186 | fail("Should throw exception"); 187 | } catch (GenException e) { 188 | // OK 189 | } 190 | } 191 | 192 | @Test 193 | public void testValidFuture() throws Exception { 194 | ProxyModel model = generateProxyModel(FuturizedProxy.class); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/future/FuturizedProxy.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.future; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.core.Future; 5 | 6 | /** 7 | * @author Tim Fox 8 | */ 9 | @ProxyGen 10 | public interface FuturizedProxy { 11 | 12 | Future future0(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/future/package-info.java: -------------------------------------------------------------------------------- 1 | @ModuleGen(name = "dummy", groupPackage = "io.vertx") 2 | package io.vertx.serviceproxy.tests.codegen.future; 3 | 4 | import io.vertx.codegen.annotations.ModuleGen; 5 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/Concrete.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.DataObject; 4 | import io.vertx.core.json.JsonObject; 5 | 6 | /** 7 | * @author Julien Viet 8 | */ 9 | @DataObject 10 | public class Concrete { 11 | 12 | public Concrete() { 13 | } 14 | 15 | public Concrete(Concrete other) { 16 | } 17 | 18 | public Concrete(JsonObject json) { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidClose1.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyClose; 4 | import io.vertx.codegen.annotations.ProxyGen; 5 | import io.vertx.core.AsyncResult; 6 | import io.vertx.core.Handler; 7 | 8 | /** 9 | * @author Tim Fox 10 | */ 11 | @ProxyGen 12 | public interface InvalidClose1 { 13 | 14 | @ProxyClose 15 | void closeIt(Handler> handler); 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidClose2.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyClose; 4 | import io.vertx.codegen.annotations.ProxyGen; 5 | 6 | /** 7 | * @author Tim Fox 8 | */ 9 | @ProxyGen 10 | public interface InvalidClose2 { 11 | 12 | @ProxyClose 13 | void closeIt(String s); 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidClose3.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyClose; 4 | import io.vertx.codegen.annotations.ProxyGen; 5 | import io.vertx.core.AsyncResult; 6 | import io.vertx.core.Handler; 7 | 8 | /** 9 | * @author Tim Fox 10 | */ 11 | @ProxyGen 12 | public interface InvalidClose3 { 13 | 14 | @ProxyClose 15 | void closeIt(Handler> handler, String s); 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidOverloaded.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | 5 | /** 6 | * @author Tim Fox 7 | */ 8 | @ProxyGen 9 | public interface InvalidOverloaded { 10 | 11 | void someMethod(String str); 12 | 13 | void someMethod(String str, int i); 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidParams1.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.codegen.annotations.VertxGen; 5 | 6 | /** 7 | * @author Tim Fox 8 | */ 9 | @ProxyGen 10 | public interface InvalidParams1 { 11 | 12 | void someMethod(VertxGen vertxGen); 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidParams2.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.core.Handler; 5 | 6 | /** 7 | * @author Tim Fox 8 | */ 9 | @ProxyGen 10 | public interface InvalidParams2 { 11 | 12 | void someMethod(Handler handler); 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidParams3.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.core.AsyncResult; 5 | import io.vertx.core.Handler; 6 | 7 | /** 8 | * @author Tim Fox 9 | */ 10 | @ProxyGen 11 | public interface InvalidParams3 { 12 | 13 | void someMethod(Handler> notAtEnd, String str); 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidParams4.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.core.AsyncResult; 5 | import io.vertx.core.Handler; 6 | 7 | /** 8 | * @author Tim Fox 9 | */ 10 | @ProxyGen 11 | public interface InvalidParams4 { 12 | 13 | void someMethod(String str, Handler> wrongResultType); 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidParamsDataObject.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | 5 | /** 6 | * @author Nick Scavelli 7 | */ 8 | @ProxyGen 9 | public interface InvalidParamsDataObject { 10 | void invalidDataObject(Concrete concrete); 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidReturn1.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | 5 | /** 6 | * @author Tim Fox 7 | */ 8 | @ProxyGen 9 | public interface InvalidReturn1 { 10 | 11 | String someMethod(); 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidReturn2.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.codegen.annotations.VertxGen; 5 | 6 | /** 7 | * @author Tim Fox 8 | */ 9 | @ProxyGen 10 | public interface InvalidReturn2 { 11 | 12 | VertxGen someMethod(); 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/InvalidReturn3.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.core.json.JsonObject; 5 | 6 | /** 7 | * @author Tim Fox 8 | */ 9 | @ProxyGen 10 | public interface InvalidReturn3 { 11 | 12 | JsonObject someMethod(); 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/ProxyConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 18 | 19 | import io.vertx.codegen.annotations.ProxyGen; 20 | import io.vertx.codegen.annotations.VertxGen; 21 | 22 | /** 23 | * @author Tim Fox 24 | */ 25 | @ProxyGen 26 | @VertxGen 27 | public interface ProxyConnection { 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/ProxyDataObject.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.DataObject; 4 | import io.vertx.core.json.JsonObject; 5 | 6 | /** 7 | * @author Nick Scavelli 8 | */ 9 | @DataObject 10 | public class ProxyDataObject { 11 | 12 | public ProxyDataObject() { 13 | } 14 | 15 | public ProxyDataObject(JsonObject json) { 16 | } 17 | 18 | public JsonObject toJson() { 19 | return new JsonObject(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/ProxyDataObjectParent.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.core.json.JsonObject; 4 | 5 | /** 6 | * Created by Erwin on 25/03/16. 7 | */ 8 | public abstract class ProxyDataObjectParent { 9 | 10 | public JsonObject toJson() { 11 | return new JsonObject(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/ProxyDataObjectWithParent.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.DataObject; 4 | import io.vertx.core.json.JsonObject; 5 | 6 | /** 7 | * Created by Erwin on 25/03/16. 8 | */ 9 | @DataObject 10 | public class ProxyDataObjectWithParent extends ProxyDataObjectParent { 11 | 12 | public ProxyDataObjectWithParent() { 13 | } 14 | 15 | public ProxyDataObjectWithParent(JsonObject json) { 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/ProxyDataObjectWithParentOverride.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.DataObject; 4 | import io.vertx.core.json.JsonObject; 5 | 6 | /** 7 | * Created by Erwin on 25/03/16. 8 | */ 9 | @DataObject 10 | public class ProxyDataObjectWithParentOverride extends ProxyDataObjectParent { 11 | 12 | public ProxyDataObjectWithParentOverride() { 13 | } 14 | 15 | public ProxyDataObjectWithParentOverride(JsonObject json) { 16 | } 17 | 18 | @Override 19 | public JsonObject toJson() { 20 | return super.toJson(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/SomeEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 18 | 19 | /** 20 | * @author Tim Fox 21 | */ 22 | public enum SomeEnum { 23 | FOO, BAR, WIBBLE 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/ValidProxy.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import java.time.ZonedDateTime; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | import io.vertx.codegen.annotations.ProxyClose; 9 | import io.vertx.codegen.annotations.ProxyGen; 10 | import io.vertx.codegen.annotations.ProxyIgnore; 11 | import io.vertx.core.Future; 12 | import io.vertx.core.json.JsonArray; 13 | import io.vertx.core.json.JsonObject; 14 | import io.vertx.serviceproxy.tests.testmodel.SomeEnumWithCustomConstructor; 15 | 16 | /** 17 | * @author Tim Fox 18 | */ 19 | @ProxyGen 20 | public interface ValidProxy { 21 | 22 | void basicTypes(String str, byte b, short s, int i, long l, float f, double d, char c, boolean bool); 23 | 24 | void basicBoxedTypes(String str, Byte b, Short s, Integer i, Long l, Float f, Double d, Character c, 25 | Boolean bool); 26 | 27 | void jsonTypes(JsonObject jsonObject, JsonArray jsonArray); 28 | 29 | void methodWithListParams(List listString, List listByte, List listShort, List listInt, List listLong, List listJsonObject, List listJsonArray); 30 | 31 | void methodWithSetParams(Set setString, Set setByte, Set setShort, Set setInt, Set setLong, Set setJsonObject, Set setJsonArray); 32 | 33 | void methodWithMapParams(Map mapString, Map mapByte, Map mapShort, Map mapInt, Map mapLong, Map mapJsonObject, Map mapJsonArray); 34 | 35 | void enumType(SomeEnum someEnum); 36 | 37 | void enumWithCustomConstructorType(SomeEnumWithCustomConstructor someCustomEnum); 38 | 39 | void dataObjectType(ProxyDataObject dataObject); 40 | void methodMapper(ZonedDateTime dateTime); 41 | 42 | void dataObjectWithParentType(ProxyDataObjectWithParent dataObject); 43 | void dataObjectWithParentAndOverride(ProxyDataObjectWithParentOverride dataObject); 44 | 45 | Future handler0(); 46 | Future handler1(); 47 | Future handler2(); 48 | Future handler3(); 49 | Future handler4(); 50 | Future handler5(); 51 | Future handler6(); 52 | Future handler7(); 53 | Future handler8(); 54 | Future handler9(); 55 | Future handler10(); 56 | Future handler11(); 57 | 58 | Future> handler12(); 59 | Future> handler13(); 60 | Future> handler14(); 61 | Future> handler15(); 62 | Future> handler16(); 63 | Future> handler17(); 64 | Future> handler18(); 65 | Future> handler19(); 66 | Future> handler20(); 67 | Future> handler21(); 68 | Future> handler22(); 69 | 70 | Future> handler24(); 71 | Future> handler25(); 72 | Future> handler26(); 73 | Future> handler27(); 74 | Future> handler28(); 75 | Future> handler29(); 76 | Future> handler30(); 77 | Future> handler31(); 78 | Future> handler32(); 79 | Future> handler33(); 80 | Future> handler34(); 81 | 82 | Future handler35(); 83 | Future> handler36(); 84 | Future> handler37(); 85 | 86 | @ProxyIgnore 87 | void ignored(); 88 | 89 | @ProxyClose 90 | void closeIt(); 91 | 92 | Future connection(String foo); 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/ValidProxyCloseWithFuture.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 2 | 3 | import io.vertx.codegen.annotations.ProxyClose; 4 | import io.vertx.codegen.annotations.ProxyGen; 5 | import io.vertx.core.Future; 6 | 7 | /** 8 | * @author Tim Fox 9 | */ 10 | @ProxyGen 11 | public interface ValidProxyCloseWithFuture { 12 | 13 | @ProxyClose 14 | Future closeIt(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/codegen/proxytestapi/package-info.java: -------------------------------------------------------------------------------- 1 | @ModuleGen(name = "dummy", groupPackage = "io.vertx") 2 | package io.vertx.serviceproxy.tests.codegen.proxytestapi; 3 | 4 | import io.vertx.codegen.annotations.ModuleGen; 5 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/Mappers.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.testmodel; 2 | 3 | import java.time.ZonedDateTime; 4 | 5 | public class Mappers { 6 | 7 | public static String serializeZonedDateTime(ZonedDateTime value) throws IllegalArgumentException { 8 | return (value != null) ? value.toString() : null; 9 | } 10 | 11 | public static ZonedDateTime deserializeZonedDateTime(String value) throws IllegalArgumentException { 12 | return (value != null) ? ZonedDateTime.parse(value) : null; 13 | } 14 | 15 | public static String serializeSomeEnumWithCustomConstructor(SomeEnumWithCustomConstructor value) throws IllegalArgumentException { 16 | return (value != null) ? value.getLongName() : null; 17 | } 18 | 19 | public static SomeEnumWithCustomConstructor deserializeSomeEnumWithCustomConstructor(String value) throws IllegalArgumentException { 20 | return (value != null) ? SomeEnumWithCustomConstructor.of(value) : null; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/MyServiceException.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.testmodel; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.json.JsonObject; 5 | import io.vertx.serviceproxy.ServiceException; 6 | 7 | /** 8 | * @author Dan O'Reilly 9 | */ 10 | public class MyServiceException extends ServiceException { 11 | private final String extra; 12 | /** 13 | * Create a ServiceException. 14 | * 15 | * @param failureCode The failure code. 16 | * @param message The failure message. 17 | */ 18 | public MyServiceException(int failureCode, String message, String extra) { 19 | super(failureCode, message); 20 | this.extra = extra; 21 | } 22 | 23 | public MyServiceException(int failureCode, String message, JsonObject debugInfo, String extra) { 24 | super(failureCode, message, debugInfo); 25 | this.extra = extra; 26 | } 27 | 28 | /** 29 | * Get the extra data 30 | * 31 | * @return The extra data 32 | */ 33 | public String getExtra() { 34 | return extra; 35 | } 36 | 37 | /** 38 | * Wrap and MyServiceException in a failed Future and return it. 39 | * 40 | * @param failureCode The failure code. 41 | * @param message The failure message. 42 | * @param extra The extra data 43 | * @param The type returned if the Future succeeds. 44 | * @return The MyServiceException wrapped in a failed future. 45 | */ 46 | public static Future fail(int failureCode, String message, String extra) { 47 | return Future.failedFuture(new MyServiceException(failureCode, message, extra)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/MyServiceExceptionMessageCodec.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.testmodel; 2 | 3 | import io.netty.util.CharsetUtil; 4 | import io.vertx.core.buffer.Buffer; 5 | import io.vertx.core.eventbus.MessageCodec; 6 | import io.vertx.core.json.JsonObject; 7 | 8 | /** 9 | * @author Dan O'Reilly 10 | */ 11 | public class MyServiceExceptionMessageCodec implements 12 | MessageCodec { 13 | @Override 14 | public void encodeToWire(Buffer buffer, MyServiceException body) { 15 | buffer.appendInt(body.failureCode()); 16 | if (body.getMessage() == null) { 17 | buffer.appendByte((byte)0); 18 | } else { 19 | buffer.appendByte((byte)1); 20 | byte[] encoded = body.getMessage().getBytes(CharsetUtil.UTF_8); 21 | buffer.appendInt(encoded.length); 22 | buffer.appendBytes(encoded); 23 | } 24 | if (body.getExtra() == null) { 25 | buffer.appendByte((byte)0); 26 | } else { 27 | buffer.appendByte((byte)1); 28 | byte[] encoded = body.getExtra().getBytes(CharsetUtil.UTF_8); 29 | buffer.appendInt(encoded.length); 30 | buffer.appendBytes(encoded); 31 | } 32 | body.getDebugInfo().writeToBuffer(buffer); 33 | } 34 | 35 | @Override 36 | public MyServiceException decodeFromWire(int pos, Buffer buffer) { 37 | int failureCode = buffer.getInt(pos); 38 | pos += 4; 39 | boolean isNull = buffer.getByte(pos) == (byte)0; 40 | pos++; 41 | String message; 42 | if (!isNull) { 43 | int strLength = buffer.getInt(pos); 44 | pos += 4; 45 | byte[] bytes = buffer.getBytes(pos, pos + strLength); 46 | pos += strLength; 47 | message = new String(bytes, CharsetUtil.UTF_8); 48 | } else { 49 | message = null; 50 | } 51 | isNull = buffer.getByte(pos) == (byte)0; 52 | pos++; 53 | String extra; 54 | if (!isNull) { 55 | int strLength = buffer.getInt(pos); 56 | pos += 4; 57 | byte[] bytes = buffer.getBytes(pos, pos + strLength); 58 | extra = new String(bytes, CharsetUtil.UTF_8); 59 | pos += strLength; 60 | } else { 61 | extra = null; 62 | } 63 | JsonObject debugInfo = new JsonObject(); 64 | debugInfo.readFromBuffer(pos, buffer); 65 | return new MyServiceException(failureCode, message, debugInfo, extra); 66 | } 67 | 68 | @Override 69 | public MyServiceException transform(MyServiceException e) { 70 | return e; 71 | } 72 | 73 | @Override 74 | public String name() { 75 | return "myServiceException"; 76 | } 77 | 78 | @Override 79 | public byte systemCodecID() { 80 | return -1; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/OKService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | import io.vertx.codegen.annotations.ProxyGen; 20 | import io.vertx.codegen.annotations.VertxGen; 21 | import io.vertx.core.Future; 22 | 23 | @ProxyGen 24 | @VertxGen 25 | /** 26 | * 27 | */ 28 | public interface OKService { 29 | Future ok(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/OKServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | import io.vertx.core.Future; 20 | 21 | public class OKServiceImpl implements OKService { 22 | 23 | @Override 24 | public Future ok() { 25 | return Future.succeededFuture("ok"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/SomeEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | /** 20 | * @author Tim Fox 21 | */ 22 | public enum SomeEnum { 23 | FOO, BAR, WIBBLE 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/SomeEnumWithCustomConstructor.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.testmodel; 2 | 3 | public enum SomeEnumWithCustomConstructor { 4 | DEV("dev", "development"), ITEST("itest", "integration-test"); 5 | 6 | public static SomeEnumWithCustomConstructor of(String pName) { 7 | for (SomeEnumWithCustomConstructor item : SomeEnumWithCustomConstructor.values()) { 8 | if (item.names[0].equalsIgnoreCase(pName) || item.names[1].equalsIgnoreCase(pName) 9 | || pName.equalsIgnoreCase(item.name())) { 10 | return item; 11 | } 12 | } 13 | return DEV; 14 | } 15 | 16 | private String[] names = new String[2]; 17 | 18 | SomeEnumWithCustomConstructor(String pShortName, String pLongName) { 19 | names[0] = pShortName; 20 | names[1] = pLongName; 21 | } 22 | 23 | public String getLongName() { 24 | return names[1]; 25 | } 26 | 27 | public String getShortName() { 28 | return names[0]; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/SomeVertxEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | import io.vertx.codegen.annotations.VertxGen; 20 | 21 | /** 22 | * @author Tim Fox 23 | */ 24 | @VertxGen 25 | public enum SomeVertxEnum { 26 | FOO, BAR, WIBBLE 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/StringDataObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | import io.vertx.codegen.annotations.DataObject; 20 | 21 | /** 22 | * 23 | * The Json properties are used to reproduce https://github.com/vert-x3/vertx-service-proxy/issues/56 24 | * 25 | * @author Nick Scavelli 26 | */ 27 | @DataObject 28 | public class StringDataObject { 29 | 30 | private String value; 31 | 32 | public StringDataObject() { 33 | } 34 | 35 | 36 | public StringDataObject(String value) { 37 | this.value = value; 38 | } 39 | 40 | public String toJson() { 41 | return value; 42 | } 43 | 44 | public String getValue() { 45 | return value; 46 | } 47 | 48 | public StringDataObject setValue(String value) { 49 | this.value = value; 50 | return this; 51 | } 52 | 53 | @Override 54 | public boolean equals(Object o) { 55 | if (this == o) return true; 56 | if (o == null || getClass() != o.getClass()) return false; 57 | 58 | StringDataObject that = (StringDataObject) o; 59 | 60 | if (!value.equals(that.value)) return false; 61 | 62 | return true; 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | String v = this.value; 68 | return v != null ? v.hashCode() : 0; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/TestBaseImportsService.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.testmodel; 2 | 3 | import io.vertx.codegen.annotations.ProxyGen; 4 | import io.vertx.codegen.annotations.VertxGen; 5 | 6 | /** 7 | * Test base imports are corrects. 8 | * 9 | * @author Julien Viet 10 | */ 11 | @ProxyGen 12 | @VertxGen 13 | public interface TestBaseImportsService { 14 | 15 | void m(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/TestConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | import io.vertx.codegen.annotations.ProxyClose; 20 | import io.vertx.codegen.annotations.ProxyGen; 21 | import io.vertx.codegen.annotations.VertxGen; 22 | import io.vertx.core.Future; 23 | import io.vertx.core.json.JsonObject; 24 | 25 | /** 26 | * @author Tim Fox 27 | */ 28 | @ProxyGen 29 | @VertxGen 30 | public interface TestConnection { 31 | 32 | Future startTransaction(); 33 | 34 | Future insert(String name, JsonObject data); 35 | 36 | Future commit(); 37 | 38 | Future rollback(); 39 | 40 | @ProxyClose 41 | void close(); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/TestDataObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import io.vertx.codegen.annotations.DataObject; 21 | import io.vertx.core.json.JsonObject; 22 | 23 | /** 24 | * 25 | * The Json properties are used to reproduce https://github.com/vert-x3/vertx-service-proxy/issues/56 26 | * 27 | * @author Nick Scavelli 28 | */ 29 | @DataObject 30 | public class TestDataObject { 31 | 32 | @JsonProperty("number") 33 | private int number; 34 | 35 | @JsonProperty("string") 36 | private String string; 37 | private boolean bool; 38 | 39 | public TestDataObject() { 40 | } 41 | 42 | 43 | public TestDataObject(JsonObject json) { 44 | this.number = json.getInteger("number"); 45 | this.string = json.getString("string"); 46 | this.bool = json.getBoolean("bool"); 47 | } 48 | 49 | public JsonObject toJson() { 50 | return new JsonObject() 51 | .put("number", number) 52 | .put("string", string) 53 | .put("bool", bool); 54 | } 55 | 56 | public int getNumber() { 57 | return number; 58 | } 59 | 60 | public TestDataObject setNumber(int number) { 61 | this.number = number; 62 | return this; 63 | } 64 | 65 | public String getString() { 66 | return string; 67 | } 68 | 69 | public TestDataObject setString(String string) { 70 | this.string = string; 71 | return this; 72 | } 73 | 74 | public boolean isBool() { 75 | return bool; 76 | } 77 | 78 | public TestDataObject setBool(boolean bool) { 79 | this.bool = bool; 80 | return this; 81 | } 82 | 83 | @Override 84 | public boolean equals(Object o) { 85 | if (this == o) return true; 86 | if (o == null || getClass() != o.getClass()) return false; 87 | 88 | TestDataObject that = (TestDataObject) o; 89 | 90 | if (bool != that.bool) return false; 91 | if (number != that.number) return false; 92 | if (!string.equals(that.string)) return false; 93 | 94 | return true; 95 | } 96 | 97 | @Override 98 | public int hashCode() { 99 | int result = number; 100 | result = 31 * result + string.hashCode(); 101 | result = 31 * result + (bool ? 1 : 0); 102 | return result; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/TestService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel; 18 | 19 | import io.vertx.codegen.annotations.ProxyGen; 20 | import io.vertx.codegen.annotations.ProxyIgnore; 21 | import io.vertx.codegen.annotations.VertxGen; 22 | import io.vertx.core.Future; 23 | import io.vertx.core.Vertx; 24 | import io.vertx.core.eventbus.DeliveryOptions; 25 | import io.vertx.core.json.JsonArray; 26 | import io.vertx.core.json.JsonObject; 27 | import io.vertx.serviceproxy.ServiceProxyBuilder; 28 | import io.vertx.serviceproxy.tests.testmodel.impl.TestServiceImpl; 29 | import io.vertx.serviceproxy.tests.testmodel.sub.TestSubConnection; 30 | 31 | import java.time.ZonedDateTime; 32 | import java.util.List; 33 | import java.util.Map; 34 | import java.util.Set; 35 | 36 | /** 37 | * @author Tim Fox 38 | * @author lalitrao 39 | */ 40 | @ProxyGen 41 | @VertxGen 42 | public interface TestService { 43 | 44 | static TestService create(Vertx vertx) throws Exception { 45 | return new TestServiceImpl(vertx); 46 | } 47 | 48 | static TestService createProxy(Vertx vertx, String address) { 49 | return new ServiceProxyBuilder(vertx).setAddress(address).build(TestService.class); 50 | } 51 | 52 | static TestService createProxyLongDelivery(Vertx vertx, String address) { 53 | DeliveryOptions options = new DeliveryOptions(); 54 | options.setSendTimeout(20*1000L); 55 | return new ServiceProxyBuilder(vertx).setAddress(address).setOptions(options).build(TestService.class); 56 | } 57 | 58 | static TestService createProxyWithOptions(Vertx vertx, String address, DeliveryOptions options) { 59 | return new ServiceProxyBuilder(vertx).setAddress(address).setOptions(options).build(TestService.class); 60 | } 61 | 62 | Future longDeliverySuccess() ; 63 | 64 | Future longDeliveryFailed() ; 65 | 66 | Future createConnection(String str); 67 | 68 | Future createSubConnection(String str); 69 | 70 | void noParams(); 71 | 72 | void basicTypes(String str, byte b, short s, int i, long l, float f, double d, char c, boolean bool); 73 | 74 | void basicBoxedTypes(String str, Byte b, Short s, Integer i, Long l, Float f, Double d, Character c, 75 | Boolean bool); 76 | 77 | void basicBoxedTypesNull(String str, Byte b, Short s, Integer i, Long l, Float f, Double d, Character c, 78 | Boolean bool); 79 | 80 | void jsonTypes(JsonObject jsonObject, JsonArray jsonArray); 81 | 82 | void jsonTypesNull(JsonObject jsonObject, JsonArray jsonArray); 83 | 84 | void enumType(SomeEnum someEnum); 85 | 86 | void enumTypeNull(SomeEnum someEnum); 87 | 88 | Future enumTypeAsResult() ; 89 | 90 | Future enumTypeAsResultNull() ; 91 | 92 | void enumCustomType(SomeEnumWithCustomConstructor someEnum); 93 | 94 | void enumCustomTypeNull(SomeEnumWithCustomConstructor someEnum); 95 | 96 | Future enumCustomTypeAsResult() ; 97 | 98 | Future enumCustomTypeAsResultNull() ; 99 | 100 | void dataObjectType(TestDataObject options); 101 | 102 | void listdataObjectType(List list); 103 | 104 | void setdataObjectType(Set set); 105 | 106 | void dataObjectTypeNull(TestDataObject options); 107 | 108 | void dateTimeType(ZonedDateTime dateTime); 109 | 110 | void listDateTimeType(List list); 111 | 112 | void setDateTimeType(Set set); 113 | 114 | void mapDateTimeType(Map map); 115 | 116 | void listdataObjectTypeHavingNullValues(List list); 117 | 118 | void setdataObjectTypeHavingNullValues(Set set); 119 | 120 | void listdataObjectTypeNull(List list); 121 | 122 | void setdataObjectTypeNull(Set set); 123 | 124 | void mapDataObjectType(Map map); 125 | 126 | void listParams(List listString, List listByte, List listShort, List listInt, List listLong, List listJsonObject, List listJsonArray, List listDataObject); 127 | 128 | void setParams(Set setString, Set setByte, Set setShort, Set setInt, Set setLong, Set setJsonObject, Set setJsonArray, Set setDataObject); 129 | 130 | void mapParams(Map mapString, Map mapByte, Map mapShort, Map mapInt, Map mapLong, Map mapJsonObject, Map mapJsonArray); 131 | 132 | Future stringHandler() ; 133 | 134 | Future stringNullHandler() ; 135 | 136 | Future byteHandler() ; 137 | 138 | Future byteNullHandler() ; 139 | 140 | Future shortHandler() ; 141 | 142 | Future shortNullHandler() ; 143 | 144 | Future intHandler() ; 145 | 146 | Future intNullHandler() ; 147 | 148 | Future longHandler() ; 149 | 150 | Future longNullHandler() ; 151 | 152 | Future floatHandler() ; 153 | 154 | Future floatNullHandler() ; 155 | 156 | Future doubleHandler() ; 157 | 158 | Future doubleNullHandler() ; 159 | 160 | Future charHandler() ; 161 | 162 | Future charNullHandler() ; 163 | 164 | Future booleanHandler() ; 165 | 166 | Future booleanNullHandler() ; 167 | 168 | Future jsonObjectHandler() ; 169 | 170 | Future jsonObjectNullHandler() ; 171 | 172 | Future jsonArrayHandler() ; 173 | 174 | Future jsonArrayNullHandler() ; 175 | 176 | Future dataObjectHandler() ; 177 | 178 | Future dataObjectNullHandler() ; 179 | 180 | Future voidHandler() ; 181 | 182 | Future failingMethod() ; 183 | 184 | Future invokeWithMessage(JsonObject object, String str, int i, char chr, SomeEnum senum); 185 | 186 | Future> listStringHandler() ; 187 | 188 | Future> listByteHandler() ; 189 | 190 | Future> listShortHandler() ; 191 | 192 | Future> listIntHandler() ; 193 | 194 | Future> listLongHandler() ; 195 | 196 | Future> listFloatHandler() ; 197 | 198 | Future> listDoubleHandler() ; 199 | 200 | Future> listCharHandler() ; 201 | 202 | Future> listBoolHandler() ; 203 | 204 | Future> listJsonObjectHandler() ; 205 | 206 | Future> listJsonArrayHandler() ; 207 | 208 | Future> listDataObjectHandler() ; 209 | 210 | Future> setStringHandler() ; 211 | 212 | Future> setByteHandler() ; 213 | 214 | Future> setShortHandler() ; 215 | 216 | Future> setIntHandler() ; 217 | 218 | Future> setLongHandler() ; 219 | 220 | Future> setFloatHandler() ; 221 | 222 | Future> setDoubleHandler() ; 223 | 224 | Future> setCharHandler() ; 225 | 226 | Future> setBoolHandler() ; 227 | 228 | Future> mapStringHandler() ; 229 | 230 | Future> mapByteHandler() ; 231 | 232 | Future> mapShortHandler() ; 233 | 234 | Future> mapIntHandler() ; 235 | 236 | Future> mapLongHandler() ; 237 | 238 | Future> mapFloatHandler() ; 239 | 240 | Future> mapDoubleHandler() ; 241 | 242 | Future> mapCharHandler() ; 243 | 244 | Future> mapBoolHandler() ; 245 | 246 | Future> setJsonObjectHandler() ; 247 | 248 | Future> mapJsonObjectHandler() ; 249 | 250 | Future> setJsonArrayHandler() ; 251 | 252 | Future> mapJsonArrayHandler() ; 253 | 254 | Future> setDataObjectHandler() ; 255 | 256 | Future> mapDataObject() ; 257 | 258 | Future failingCall(String value); 259 | 260 | Future> listDataObjectContainingNullHandler() ; 261 | 262 | Future> setDataObjectContainingNullHandler() ; 263 | 264 | Future zonedDateTimeHandler() ; 265 | 266 | Future> listZonedDateTimeHandler() ; 267 | 268 | Future> setZonedDateTimeHandler() ; 269 | 270 | Future> mapZonedDateTimeHandler() ; 271 | 272 | @ProxyIgnore 273 | void ignoredMethod(); 274 | } 275 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/impl/TestConnectionImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel.impl; 18 | 19 | import io.vertx.core.Future; 20 | import io.vertx.core.Vertx; 21 | import io.vertx.core.json.JsonObject; 22 | import io.vertx.serviceproxy.tests.testmodel.TestConnection; 23 | 24 | /** 25 | * @author Tim Fox 26 | */ 27 | public class TestConnectionImpl implements TestConnection { 28 | 29 | private Vertx vertx; 30 | private String str; 31 | 32 | public TestConnectionImpl(Vertx vertx, String str) { 33 | this.vertx = vertx; 34 | this.str = str; 35 | } 36 | 37 | @Override 38 | public Future startTransaction() { 39 | return Future.succeededFuture(str); 40 | } 41 | 42 | @Override 43 | public Future insert(String name, JsonObject data) { 44 | return Future.succeededFuture(str); 45 | } 46 | 47 | @Override 48 | public Future commit() { 49 | return Future.succeededFuture(str); 50 | } 51 | 52 | @Override 53 | public Future rollback() { 54 | return Future.succeededFuture(str); 55 | } 56 | 57 | @Override 58 | public void close() { 59 | vertx.eventBus().send("closeCalled", "blah"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/impl/TestSubConnectionImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel.impl; 18 | 19 | import io.vertx.core.Vertx; 20 | import io.vertx.serviceproxy.tests.testmodel.sub.TestSubConnection; 21 | 22 | /** 23 | * @author Tim Fox 24 | */ 25 | public class TestSubConnectionImpl implements TestSubConnection { 26 | 27 | private Vertx vertx; 28 | private String str; 29 | 30 | public TestSubConnectionImpl(Vertx vertx, String str) { 31 | this.vertx = vertx; 32 | this.str = str; 33 | } 34 | @Override 35 | public void close() { 36 | vertx.eventBus().send("closeCalled", "bluh"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Julien Viet 3 | */ 4 | @ModuleGen(name = "test", groupPackage = "io.vertx") 5 | package io.vertx.serviceproxy.tests.testmodel; 6 | 7 | import io.vertx.codegen.annotations.ModuleGen; 8 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel/sub/TestSubConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel.sub; 18 | 19 | import io.vertx.codegen.annotations.ProxyClose; 20 | import io.vertx.codegen.annotations.ProxyGen; 21 | import io.vertx.codegen.annotations.VertxGen; 22 | 23 | /** 24 | * @author Tim Fox 25 | */ 26 | @ProxyGen 27 | @VertxGen 28 | public interface TestSubConnection { 29 | 30 | @ProxyClose 31 | void close(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel2/FuturizedTestService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Red Hat, Inc. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | 17 | package io.vertx.serviceproxy.tests.testmodel2; 18 | 19 | import io.vertx.codegen.annotations.ProxyGen; 20 | import io.vertx.codegen.annotations.VertxGen; 21 | import io.vertx.core.Future; 22 | import io.vertx.core.Vertx; 23 | import io.vertx.serviceproxy.ServiceProxyBuilder; 24 | import io.vertx.serviceproxy.tests.testmodel2.impl.FuturizedTestServiceImpl; 25 | 26 | @ProxyGen 27 | @VertxGen 28 | public interface FuturizedTestService { 29 | 30 | static FuturizedTestService create(Vertx vertx) throws Exception { 31 | return new FuturizedTestServiceImpl(vertx); 32 | } 33 | 34 | static FuturizedTestService createProxy(Vertx vertx, String address) { 35 | return new ServiceProxyBuilder(vertx).setAddress(address).build(FuturizedTestService.class); 36 | } 37 | 38 | Future ok(); 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel2/impl/FuturizedTestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.testmodel2.impl; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Vertx; 5 | import io.vertx.serviceproxy.tests.testmodel2.FuturizedTestService; 6 | 7 | public class FuturizedTestServiceImpl implements FuturizedTestService { 8 | 9 | private final Vertx vertx; 10 | 11 | public FuturizedTestServiceImpl(Vertx vertx) { 12 | this.vertx = vertx; 13 | } 14 | 15 | @Override 16 | public Future ok() { 17 | return Future.succeededFuture("foobar"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/testmodel2/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Julien Viet 3 | */ 4 | @ModuleGen(name = "test", groupPackage = "io.vertx") 5 | package io.vertx.serviceproxy.tests.testmodel2; 6 | 7 | import io.vertx.codegen.annotations.ModuleGen; 8 | -------------------------------------------------------------------------------- /src/test/java/io/vertx/serviceproxy/tests/utils/InterceptorUtilsTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.serviceproxy.tests.utils; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.serviceproxy.AuthenticationInterceptor; 5 | import io.vertx.serviceproxy.AuthorizationInterceptor; 6 | import io.vertx.serviceproxy.impl.InterceptorHolder; 7 | import io.vertx.serviceproxy.ServiceInterceptor; 8 | import io.vertx.serviceproxy.impl.InterceptorPriority; 9 | import io.vertx.serviceproxy.impl.utils.InterceptorUtils; 10 | import org.junit.Assert; 11 | import org.junit.Test; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertThrows; 18 | 19 | public class InterceptorUtilsTest { 20 | 21 | @Test 22 | public void testGetWeightAuthn() { 23 | ServiceInterceptor authn = AuthenticationInterceptor.create(null); 24 | Assert.assertEquals(InterceptorPriority.AUTHENTICATION, InterceptorUtils.getWeight(authn)); 25 | } 26 | 27 | @Test 28 | public void testGetWeightAuthz() { 29 | ServiceInterceptor authz = AuthorizationInterceptor.create(null); 30 | assertEquals(InterceptorPriority.AUTHORIZATION, InterceptorUtils.getWeight(authz)); 31 | } 32 | 33 | @Test 34 | public void testGetWeightUser() { 35 | ServiceInterceptor user = (vertx, context, msg) -> Future.succeededFuture(); 36 | assertEquals(InterceptorPriority.USER, InterceptorUtils.getWeight(user)); 37 | } 38 | 39 | @Test 40 | public void testCheckInterceptorOrderFromEmptyList() { 41 | List interceptorHolders = new ArrayList<>(); 42 | ServiceInterceptor authn = AuthenticationInterceptor.create(null); 43 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, authn); 44 | interceptorHolders.clear(); 45 | ServiceInterceptor authz = AuthorizationInterceptor.create(null); 46 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, authz); 47 | interceptorHolders.clear(); 48 | ServiceInterceptor user = (vertx, context, msg) -> Future.succeededFuture(); 49 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, user); 50 | } 51 | 52 | @Test 53 | public void testCheckInterceptorOrderRightPriority() { 54 | List interceptorHolders = new ArrayList<>(); 55 | ServiceInterceptor authn = AuthenticationInterceptor.create(null); 56 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, authn); 57 | interceptorHolders.add(new InterceptorHolder(authn)); 58 | ServiceInterceptor authz = AuthorizationInterceptor.create(null); 59 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, authz); 60 | interceptorHolders.add(new InterceptorHolder(authz)); 61 | ServiceInterceptor user = (vertx, context, msg) -> Future.succeededFuture(); 62 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, user); 63 | } 64 | 65 | @Test 66 | public void testCheckInterceptorOrderWrongPriority() { 67 | List interceptorHolders = new ArrayList<>(); 68 | ServiceInterceptor authz = AuthorizationInterceptor.create(null); 69 | interceptorHolders.add(new InterceptorHolder(authz)); 70 | ServiceInterceptor authn = AuthenticationInterceptor.create(null); 71 | assertThrows(IllegalStateException.class, () -> 72 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, authn)); 73 | interceptorHolders.clear(); 74 | ServiceInterceptor user = (vertx, context, msg) -> Future.succeededFuture(); 75 | interceptorHolders.add(new InterceptorHolder(user)); 76 | assertThrows(IllegalStateException.class, () -> 77 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, authn)); 78 | assertThrows(IllegalStateException.class, () -> 79 | InterceptorUtils.checkInterceptorOrder(interceptorHolders, authz)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/resources/META-INF/vertx/json-mappers.properties: -------------------------------------------------------------------------------- 1 | java.time.ZonedDateTime.serializer=io.vertx.serviceproxy.tests.testmodel.Mappers#serializeZonedDateTime 2 | java.time.ZonedDateTime.deserializer=io.vertx.serviceproxy.tests.testmodel.Mappers#deserializeZonedDateTime 3 | io.vertx.serviceproxy.tests.testmodel.SomeEnumWithCustomConstructor.serializer=io.vertx.serviceproxy.tests.testmodel.Mappers#serializeSomeEnumWithCustomConstructor 4 | io.vertx.serviceproxy.tests.testmodel.SomeEnumWithCustomConstructor.deserializer=io.vertx.serviceproxy.tests.testmodel.Mappers#deserializeSomeEnumWithCustomConstructor 5 | -------------------------------------------------------------------------------- /src/test/resources/keystore.jceks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vert-x3/vertx-service-proxy/2647134588fa3d815cea1674299fa73c5742b894/src/test/resources/keystore.jceks --------------------------------------------------------------------------------