├── .github ├── dependabot.yml └── workflows │ ├── add-to-projects.yml │ ├── test.yml │ └── triggerConversion.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.adoc ├── finish ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── openliberty │ │ │ └── guides │ │ │ ├── InventoryApplication.java │ │ │ ├── inventory │ │ │ ├── InventoryManager.java │ │ │ ├── InventoryResource.java │ │ │ ├── InventoryUtils.java │ │ │ ├── client │ │ │ │ ├── SystemClient.java │ │ │ │ ├── UnknownUrlException.java │ │ │ │ └── UnknownUrlExceptionMapper.java │ │ │ ├── filter │ │ │ │ └── InventoryOASFilter.java │ │ │ └── model │ │ │ │ ├── InventoryList.java │ │ │ │ └── SystemData.java │ │ │ └── system │ │ │ └── SystemResource.java │ ├── liberty │ │ └── config │ │ │ └── server.xml │ ├── resources │ │ └── META-INF │ │ │ ├── microprofile-config.properties │ │ │ └── openapi.yaml │ └── webapp │ │ ├── WEB-INF │ │ └── web.xml │ │ ├── favicon.ico │ │ └── index.html │ └── test │ └── java │ └── it │ └── io │ └── openliberty │ └── guides │ ├── inventory │ └── InventoryEndpointIT.java │ └── system │ └── SystemEndpointIT.java ├── scripts ├── dailyBuild.sh └── testApp.sh └── start ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── openliberty │ │ └── guides │ │ ├── InventoryApplication.java │ │ ├── inventory │ │ ├── InventoryManager.java │ │ ├── InventoryResource.java │ │ ├── InventoryUtils.java │ │ ├── client │ │ │ ├── SystemClient.java │ │ │ ├── UnknownUrlException.java │ │ │ └── UnknownUrlExceptionMapper.java │ │ ├── filter │ │ │ └── .gitkeep │ │ └── model │ │ │ ├── InventoryList.java │ │ │ └── SystemData.java │ │ └── system │ │ └── SystemResource.java ├── liberty │ └── config │ │ └── server.xml ├── resources │ └── META-INF │ │ └── .gitkeep └── webapp │ ├── WEB-INF │ └── web.xml │ ├── favicon.ico │ └── index.html └── test └── java └── it └── io └── openliberty └── guides ├── inventory └── InventoryEndpointIT.java └── system └── SystemEndpointIT.java /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/finish" 5 | schedule: 6 | interval: monthly 7 | open-pull-requests-limit: 50 8 | - package-ecosystem: maven 9 | directory: "/start" 10 | schedule: 11 | interval: monthly 12 | open-pull-requests-limit: 50 13 | -------------------------------------------------------------------------------- /.github/workflows/add-to-projects.yml: -------------------------------------------------------------------------------- 1 | name: Add issues to Liberty guides backlog project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | - transferred 8 | 9 | jobs: 10 | add-to-project: 11 | name: Add issue to backlog 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/add-to-project@v0.4.0 15 | with: 16 | project-url: https://github.com/orgs/OpenLiberty/projects/11 17 | github-token: ${{ secrets.ADMIN_BACKLOG }} 18 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test application 2 | 3 | on: 4 | pull_request: 5 | branches: [ prod, staging ] 6 | 7 | jobs: 8 | check-files: 9 | if: ${{ github.event_name == 'pull_request' }} 10 | runs-on: ubuntu-latest 11 | outputs: 12 | canSkip: ${{ steps.Checker.outputs.canSkip }} 13 | steps: 14 | - name: Get files 15 | uses: actions/checkout@v4 16 | - name: Get tools 17 | uses: actions/checkout@v4 18 | with: 19 | path: tools/ 20 | repository: openliberty/guides-common 21 | - id: Checker 22 | shell: bash 23 | run: bash ./tools/pr-checker/checker.sh ${{ github.repository }} ${{ github.event.pull_request.number }} | tee checker.log 24 | - id: Lint-Code-Base 25 | if: "! github.event.pull_request.head.repo.fork" 26 | uses: github/super-linter@latest 27 | env: 28 | VALIDATE_ALL_CODEBASE: false 29 | VALIDATE_YAML: false 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 31 | LINTER_RULES_PATH: ./tools/pr-checker/linters/ 32 | FILTER_REGEX_EXCLUDE: mvnw* 33 | DEFAULT_BRANCH: prod 34 | - name: Summary 35 | if: "! github.event.pull_request.head.repo.fork" 36 | run: | 37 | < ./checker.log tail -n +2; echo "====== Super Linter ======" 38 | < ./super-linter.log sed -n '/.*The script has completed.*/,$p' | tail -n +4 | sed 's/.*\(\[[A-Z]\+\]\)/\1/' 39 | echo "====== Examine logs in Checker and Super-Linter steps for more details ======" 40 | if [ '${{ steps.Checker.outcome }}' != 'success' ] || [ '${{ steps.Lint-Code-Base.outcome }}' != 'success' ]; then exit 1; fi 41 | test-app: 42 | runs-on: ubuntu-latest 43 | needs: [check-files] 44 | if: "!contains(needs.check-files.outputs.canSkip, 'true')" 45 | defaults: 46 | run: 47 | working-directory: finish 48 | steps: 49 | - uses: actions/checkout@v4 50 | - name: Set up JDK 11 51 | uses: actions/setup-java@v4 52 | with: 53 | distribution: 'semeru' 54 | java-version: 11 55 | - run: unset _JAVA_OPTIONS 56 | - name: Run tests 57 | run: sudo -E ../scripts/testApp.sh 58 | - name: Post tests 59 | if: always() 60 | run: | 61 | logsPath=$(sudo find . -name "console.log"); 62 | sudo cat "$logsPath" | sudo grep Launching 63 | - name: Archive server logs if failed 64 | if: failure() 65 | uses: actions/upload-artifact@v4 66 | with: 67 | name: server-logs 68 | path: finish/target/liberty/wlp/usr/servers/defaultServer/logs/ 69 | -------------------------------------------------------------------------------- /.github/workflows/triggerConversion.yml: -------------------------------------------------------------------------------- 1 | name: Rebuild cloud-hosted guide 2 | 3 | # Controls when the action will run. Triggers the workflow on push 4 | # events but only for the master branch 5 | on: 6 | push: 7 | branches: 8 | - 'prod' 9 | - 'staging' 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "post" 14 | post: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 21 | # Uses the secrets from the organisation for credentials 22 | - uses: actions/checkout@v2 23 | 24 | - name: Invoke workflow in another repo with inputs 25 | uses: benc-uk/workflow-dispatch@v1 26 | with: 27 | workflow: GuideConverter 28 | repo: OpenLiberty/cloud-hosted-guides 29 | token: ${{ secrets.GUIDECONVERSIONTOOL_PASSWORD }} 30 | inputs: '{ "branch": "${{ github.ref }}", "guide_name": "${{ github.event.repository.name }}" }' 31 | ref: "refs/heads/prod" 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven generated 2 | target/ 3 | 4 | # Eclipse generated 5 | .apt_generated/ 6 | .settings/ 7 | .project 8 | .classpath 9 | .factorypath 10 | MANIFEST.MF 11 | 12 | # MacOS system files 13 | .DS_Store 14 | 15 | # Asciidoc rendered 16 | README.html 17 | 18 | # Zip files 19 | *.zip 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Open Liberty guides 2 | 3 | Anyone can contribute to the Open Liberty guides and we welcome your contributions! 4 | 5 | There are multiple ways to contribute: report bugs, fix bugs, contribute code, improve upon documentation, etc. 6 | 7 | ## Raising issues 8 | 9 | Please raise any bug reports in this [guide repository](../../issues). For new topics, large updates to existing guides, or general suggestions and ideas, report your issue in the [Open Liberty common guides repository](https://github.com/OpenLiberty/guides-common/issues). Be sure to search the list of open issues to see if your issue has already been raised. 10 | 11 | A good bug report makes it easy for everyone to understand what you were trying to do and what went wrong. Provide as much context as possible so we can try to recreate the issue. 12 | 13 | ## Contributions 14 | 15 | Contributing to an Open Liberty guide is simple. Each guide is maintained in its own GitHub repository. To contribute, just fork from the `prod` branch for your chosen guide. Then create a branch in your forked repository to include your contribution and open a pull request to the `staging` branch for the guide. 16 | Certify the originality of your work by following the [Developer Certificate of Origin (DCO)](https://developercertificate.org) approach and adding a line to the end of the Git commit message to sign your work: 17 | 18 | ```text 19 | Signed-off-by: Jane Williams 20 | ``` 21 | 22 | The sign-off is just a line at the end of the commit message that certifies that you wrote it or otherwise have the right to pass it on as an open source patch. 23 | 24 | Use your real name when you sign. We can't accept pseudonyms or anonymous contributions. 25 | 26 | Many Git UI tools have support for adding the `Signed-off-by` line to the end of your commit message. This line can be automatically added by the `git commit` command by using the `-s` option. 27 | 28 | The team is then notified and your contribution is reviewed according to the following process: 29 | 30 | 1. The team will review your change(s). 31 | - If there are further changes to be made, the team will request changes on the pull request. 32 | - If the team does not agree with the change, the PR will be closed with an explanation and suggestion for follow-up. 33 | 2. If the team approves, the team will merge your PR. A full Open Liberty staging site build will be run. 34 | 3. Based on the results of the build: 35 | - If further review is needed, we will let you know about a pending review from our team and discuss any necessary improvements that need to be made to your change(s). 36 | - If everything is successful, the team will publish your change(s) to the `prod` branch and update the Open Liberty production site, if necessary. 37 | 38 | ## Questions and concerns 39 | 40 | If you have any questions or concerns about the guides or about Open Liberty, you can visit [Gitter for Open Liberty](https://gitter.im/OpenLiberty/) and post your questions in the relevant rooms. You can also join the Open Liberty group on [Groups.io](https://groups.io/g/openliberty) to discuss any issues you have. 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Code and build scripts are licensed under the Eclipse Public License v2 2 | 3 | Documentation files (e.g. files with an adoc file extension) are licensed under 4 | Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) 5 | 6 | Eclipse Public License - v 2.0 7 | 8 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 9 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION 10 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 11 | 12 | 1. DEFINITIONS 13 | 14 | "Contribution" means: 15 | 16 | a) in the case of the initial Contributor, the initial content 17 | Distributed under this Agreement, and 18 | 19 | b) in the case of each subsequent Contributor: 20 | i) changes to the Program, and 21 | ii) additions to the Program; 22 | where such changes and/or additions to the Program originate from 23 | and are Distributed by that particular Contributor. A Contribution 24 | "originates" from a Contributor if it was added to the Program by 25 | such Contributor itself or anyone acting on such Contributor's behalf. 26 | Contributions do not include changes or additions to the Program that 27 | are not Modified Works. 28 | 29 | "Contributor" means any person or entity that Distributes the Program. 30 | 31 | "Licensed Patents" mean patent claims licensable by a Contributor which 32 | are necessarily infringed by the use or sale of its Contribution alone 33 | or when combined with the Program. 34 | 35 | "Program" means the Contributions Distributed in accordance with this 36 | Agreement. 37 | 38 | "Recipient" means anyone who receives the Program under this Agreement 39 | or any Secondary License (as applicable), including Contributors. 40 | 41 | "Derivative Works" shall mean any work, whether in Source Code or other 42 | form, that is based on (or derived from) the Program and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. 45 | 46 | "Modified Works" shall mean any work in Source Code or other form that 47 | results from an addition to, deletion from, or modification of the 48 | contents of the Program, including, for purposes of clarity any new file 49 | in Source Code form that contains any contents of the Program. Modified 50 | Works shall not include works that contain only declarations, 51 | interfaces, types, classes, structures, or files of the Program solely 52 | in each case in order to link to, bind by name, or subclass the Program 53 | or Modified Works thereof. 54 | 55 | "Distribute" means the acts of a) distributing or b) making available 56 | in any manner that enables the transfer of a copy. 57 | 58 | "Source Code" means the form of a Program preferred for making 59 | modifications, including but not limited to software source code, 60 | documentation source, and configuration files. 61 | 62 | "Secondary License" means either the GNU General Public License, 63 | Version 2.0, or any later versions of that license, including any 64 | exceptions or additional permissions as identified by the initial 65 | Contributor. 66 | 67 | 2. GRANT OF RIGHTS 68 | 69 | a) Subject to the terms of this Agreement, each Contributor hereby 70 | grants Recipient a non-exclusive, worldwide, royalty-free copyright 71 | license to reproduce, prepare Derivative Works of, publicly display, 72 | publicly perform, Distribute and sublicense the Contribution of such 73 | Contributor, if any, and such Derivative Works. 74 | 75 | b) Subject to the terms of this Agreement, each Contributor hereby 76 | grants Recipient a non-exclusive, worldwide, royalty-free patent 77 | license under Licensed Patents to make, use, sell, offer to sell, 78 | import and otherwise transfer the Contribution of such Contributor, 79 | if any, in Source Code or other form. This patent license shall 80 | apply to the combination of the Contribution and the Program if, at 81 | the time the Contribution is added by the Contributor, such addition 82 | of the Contribution causes such combination to be covered by the 83 | Licensed Patents. The patent license shall not apply to any other 84 | combinations which include the Contribution. No hardware per se is 85 | licensed hereunder. 86 | 87 | c) Recipient understands that although each Contributor grants the 88 | licenses to its Contributions set forth herein, no assurances are 89 | provided by any Contributor that the Program does not infringe the 90 | patent or other intellectual property rights of any other entity. 91 | Each Contributor disclaims any liability to Recipient for claims 92 | brought by any other entity based on infringement of intellectual 93 | property rights or otherwise. As a condition to exercising the 94 | rights and licenses granted hereunder, each Recipient hereby 95 | assumes sole responsibility to secure any other intellectual 96 | property rights needed, if any. For example, if a third party 97 | patent license is required to allow Recipient to Distribute the 98 | Program, it is Recipient's responsibility to acquire that license 99 | before distributing the Program. 100 | 101 | d) Each Contributor represents that to its knowledge it has 102 | sufficient copyright rights in its Contribution, if any, to grant 103 | the copyright license set forth in this Agreement. 104 | 105 | e) Notwithstanding the terms of any Secondary License, no 106 | Contributor makes additional grants to any Recipient (other than 107 | those set forth in this Agreement) as a result of such Recipient's 108 | receipt of the Program under the terms of a Secondary License 109 | (if permitted under the terms of Section 3). 110 | 111 | 3. REQUIREMENTS 112 | 113 | 3.1 If a Contributor Distributes the Program in any form, then: 114 | 115 | a) the Program must also be made available as Source Code, in 116 | accordance with section 3.2, and the Contributor must accompany 117 | the Program with a statement that the Source Code for the Program 118 | is available under this Agreement, and informs Recipients how to 119 | obtain it in a reasonable manner on or through a medium customarily 120 | used for software exchange; and 121 | 122 | b) the Contributor may Distribute the Program under a license 123 | different than this Agreement, provided that such license: 124 | i) effectively disclaims on behalf of all other Contributors all 125 | warranties and conditions, express and implied, including 126 | warranties or conditions of title and non-infringement, and 127 | implied warranties or conditions of merchantability and fitness 128 | for a particular purpose; 129 | 130 | ii) effectively excludes on behalf of all other Contributors all 131 | liability for damages, including direct, indirect, special, 132 | incidental and consequential damages, such as lost profits; 133 | 134 | iii) does not attempt to limit or alter the recipients' rights 135 | in the Source Code under section 3.2; and 136 | 137 | iv) requires any subsequent distribution of the Program by any 138 | party to be under a license that satisfies the requirements 139 | of this section 3. 140 | 141 | 3.2 When the Program is Distributed as Source Code: 142 | 143 | a) it must be made available under this Agreement, or if the 144 | Program (i) is combined with other material in a separate file or 145 | files made available under a Secondary License, and (ii) the initial 146 | Contributor attached to the Source Code the notice described in 147 | Exhibit A of this Agreement, then the Program may be made available 148 | under the terms of such Secondary Licenses, and 149 | 150 | b) a copy of this Agreement must be included with each copy of 151 | the Program. 152 | 153 | 3.3 Contributors may not remove or alter any copyright, patent, 154 | trademark, attribution notices, disclaimers of warranty, or limitations 155 | of liability ("notices") contained within the Program from any copy of 156 | the Program which they Distribute, provided that Contributors may add 157 | their own appropriate notices. 158 | 159 | 4. COMMERCIAL DISTRIBUTION 160 | 161 | Commercial distributors of software may accept certain responsibilities 162 | with respect to end users, business partners and the like. While this 163 | license is intended to facilitate the commercial use of the Program, 164 | the Contributor who includes the Program in a commercial product 165 | offering should do so in a manner which does not create potential 166 | liability for other Contributors. Therefore, if a Contributor includes 167 | the Program in a commercial product offering, such Contributor 168 | ("Commercial Contributor") hereby agrees to defend and indemnify every 169 | other Contributor ("Indemnified Contributor") against any losses, 170 | damages and costs (collectively "Losses") arising from claims, lawsuits 171 | and other legal actions brought by a third party against the Indemnified 172 | Contributor to the extent caused by the acts or omissions of such 173 | Commercial Contributor in connection with its distribution of the Program 174 | in a commercial product offering. The obligations in this section do not 175 | apply to any claims or Losses relating to any actual or alleged 176 | intellectual property infringement. In order to qualify, an Indemnified 177 | Contributor must: a) promptly notify the Commercial Contributor in 178 | writing of such claim, and b) allow the Commercial Contributor to control, 179 | and cooperate with the Commercial Contributor in, the defense and any 180 | related settlement negotiations. The Indemnified Contributor may 181 | participate in any such claim at its own expense. 182 | 183 | For example, a Contributor might include the Program in a commercial 184 | product offering, Product X. That Contributor is then a Commercial 185 | Contributor. If that Commercial Contributor then makes performance 186 | claims, or offers warranties related to Product X, those performance 187 | claims and warranties are such Commercial Contributor's responsibility 188 | alone. Under this section, the Commercial Contributor would have to 189 | defend claims against the other Contributors related to those performance 190 | claims and warranties, and if a court requires any other Contributor to 191 | pay any damages as a result, the Commercial Contributor must pay 192 | those damages. 193 | 194 | 5. NO WARRANTY 195 | 196 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 197 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" 198 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 199 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF 200 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 201 | PURPOSE. Each Recipient is solely responsible for determining the 202 | appropriateness of using and distributing the Program and assumes all 203 | risks associated with its exercise of rights under this Agreement, 204 | including but not limited to the risks and costs of program errors, 205 | compliance with applicable laws, damage to or loss of data, programs 206 | or equipment, and unavailability or interruption of operations. 207 | 208 | 6. DISCLAIMER OF LIABILITY 209 | 210 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 211 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS 212 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 213 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 214 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 215 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 216 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 217 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE 218 | POSSIBILITY OF SUCH DAMAGES. 219 | 220 | 7. GENERAL 221 | 222 | If any provision of this Agreement is invalid or unenforceable under 223 | applicable law, it shall not affect the validity or enforceability of 224 | the remainder of the terms of this Agreement, and without further 225 | action by the parties hereto, such provision shall be reformed to the 226 | minimum extent necessary to make such provision valid and enforceable. 227 | 228 | If Recipient institutes patent litigation against any entity 229 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 230 | Program itself (excluding combinations of the Program with other software 231 | or hardware) infringes such Recipient's patent(s), then such Recipient's 232 | rights granted under Section 2(b) shall terminate as of the date such 233 | litigation is filed. 234 | 235 | All Recipient's rights under this Agreement shall terminate if it 236 | fails to comply with any of the material terms or conditions of this 237 | Agreement and does not cure such failure in a reasonable period of 238 | time after becoming aware of such noncompliance. If all Recipient's 239 | rights under this Agreement terminate, Recipient agrees to cease use 240 | and distribution of the Program as soon as reasonably practicable. 241 | However, Recipient's obligations under this Agreement and any licenses 242 | granted by Recipient relating to the Program shall continue and survive. 243 | 244 | Everyone is permitted to copy and distribute copies of this Agreement, 245 | but in order to avoid inconsistency the Agreement is copyrighted and 246 | may only be modified in the following manner. The Agreement Steward 247 | reserves the right to publish new versions (including revisions) of 248 | this Agreement from time to time. No one other than the Agreement 249 | Steward has the right to modify this Agreement. The Eclipse Foundation 250 | is the initial Agreement Steward. The Eclipse Foundation may assign the 251 | responsibility to serve as the Agreement Steward to a suitable separate 252 | entity. Each new version of the Agreement will be given a distinguishing 253 | version number. The Program (including Contributions) may always be 254 | Distributed subject to the version of the Agreement under which it was 255 | received. In addition, after a new version of the Agreement is published, 256 | Contributor may elect to Distribute the Program (including its 257 | Contributions) under the new version. 258 | 259 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient 260 | receives no rights or licenses to the intellectual property of any 261 | Contributor under this Agreement, whether expressly, by implication, 262 | estoppel or otherwise. All rights in the Program not expressly granted 263 | under this Agreement are reserved. Nothing in this Agreement is intended 264 | to be enforceable by any entity that is not a Contributor or Recipient. 265 | No third-party beneficiary rights are created under this Agreement. 266 | 267 | Exhibit A - Form of Secondary Licenses Notice 268 | 269 | "This Source Code may also be made available under the following 270 | Secondary Licenses when the conditions for such availability set forth 271 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), 272 | version(s), and exceptions or additional permissions here}." 273 | 274 | Simply including a copy of this Agreement, including this Exhibit A 275 | is not sufficient to license the Source Code under Secondary Licenses. 276 | 277 | If it is not possible or desirable to put the notice in a particular 278 | file, then You may include the notice in a location (such as a LICENSE 279 | file in a relevant directory) where a recipient would be likely to 280 | look for such a notice. 281 | 282 | You may add additional accurate notices of copyright ownership. 283 | 284 | -------------------------------------------------------------------------------- 285 | 286 | Attribution-NoDerivatives 4.0 International 287 | 288 | ======================================================================= 289 | 290 | Creative Commons Corporation ("Creative Commons") is not a law firm and 291 | does not provide legal services or legal advice. Distribution of 292 | Creative Commons public licenses does not create a lawyer-client or 293 | other relationship. Creative Commons makes its licenses and related 294 | information available on an "as-is" basis. Creative Commons gives no 295 | warranties regarding its licenses, any material licensed under their 296 | terms and conditions, or any related information. Creative Commons 297 | disclaims all liability for damages resulting from their use to the 298 | fullest extent possible. 299 | 300 | Using Creative Commons Public Licenses 301 | 302 | Creative Commons public licenses provide a standard set of terms and 303 | conditions that creators and other rights holders may use to share 304 | original works of authorship and other material subject to copyright 305 | and certain other rights specified in the public license below. The 306 | following considerations are for informational purposes only, are not 307 | exhaustive, and do not form part of our licenses. 308 | 309 | Considerations for licensors: Our public licenses are 310 | intended for use by those authorized to give the public 311 | permission to use material in ways otherwise restricted by 312 | copyright and certain other rights. Our licenses are 313 | irrevocable. Licensors should read and understand the terms 314 | and conditions of the license they choose before applying it. 315 | Licensors should also secure all rights necessary before 316 | applying our licenses so that the public can reuse the 317 | material as expected. Licensors should clearly mark any 318 | material not subject to the license. This includes other CC- 319 | licensed material, or material used under an exception or 320 | limitation to copyright. More considerations for licensors: 321 | wiki.creativecommons.org/Considerations_for_licensors 322 | 323 | Considerations for the public: By using one of our public 324 | licenses, a licensor grants the public permission to use the 325 | licensed material under specified terms and conditions. If 326 | the licensor's permission is not necessary for any reason--for 327 | example, because of any applicable exception or limitation to 328 | copyright--then that use is not regulated by the license. Our 329 | licenses grant only permissions under copyright and certain 330 | other rights that a licensor has authority to grant. Use of 331 | the licensed material may still be restricted for other 332 | reasons, including because others have copyright or other 333 | rights in the material. A licensor may make special requests, 334 | such as asking that all changes be marked or described. 335 | Although not required by our licenses, you are encouraged to 336 | respect those requests where reasonable. More_considerations 337 | for the public: 338 | wiki.creativecommons.org/Considerations_for_licensees 339 | 340 | 341 | ======================================================================= 342 | 343 | Creative Commons Attribution-NoDerivatives 4.0 International Public 344 | License 345 | 346 | By exercising the Licensed Rights (defined below), You accept and agree 347 | to be bound by the terms and conditions of this Creative Commons 348 | Attribution-NoDerivatives 4.0 International Public License ("Public 349 | License"). To the extent this Public License may be interpreted as a 350 | contract, You are granted the Licensed Rights in consideration of Your 351 | acceptance of these terms and conditions, and the Licensor grants You 352 | such rights in consideration of benefits the Licensor receives from 353 | making the Licensed Material available under these terms and 354 | conditions. 355 | 356 | 357 | Section 1 -- Definitions. 358 | 359 | a. Adapted Material means material subject to Copyright and Similar 360 | Rights that is derived from or based upon the Licensed Material 361 | and in which the Licensed Material is translated, altered, 362 | arranged, transformed, or otherwise modified in a manner requiring 363 | permission under the Copyright and Similar Rights held by the 364 | Licensor. For purposes of this Public License, where the Licensed 365 | Material is a musical work, performance, or sound recording, 366 | Adapted Material is always produced where the Licensed Material is 367 | synched in timed relation with a moving image. 368 | 369 | b. Copyright and Similar Rights means copyright and/or similar rights 370 | closely related to copyright including, without limitation, 371 | performance, broadcast, sound recording, and Sui Generis Database 372 | Rights, without regard to how the rights are labeled or 373 | categorized. For purposes of this Public License, the rights 374 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 375 | Rights. 376 | 377 | c. Effective Technological Measures means those measures that, in the 378 | absence of proper authority, may not be circumvented under laws 379 | fulfilling obligations under Article 11 of the WIPO Copyright 380 | Treaty adopted on December 20, 1996, and/or similar international 381 | agreements. 382 | 383 | d. Exceptions and Limitations means fair use, fair dealing, and/or 384 | any other exception or limitation to Copyright and Similar Rights 385 | that applies to Your use of the Licensed Material. 386 | 387 | e. Licensed Material means the artistic or literary work, database, 388 | or other material to which the Licensor applied this Public 389 | License. 390 | 391 | f. Licensed Rights means the rights granted to You subject to the 392 | terms and conditions of this Public License, which are limited to 393 | all Copyright and Similar Rights that apply to Your use of the 394 | Licensed Material and that the Licensor has authority to license. 395 | 396 | g. Licensor means the individual(s) or entity(ies) granting rights 397 | under this Public License. 398 | 399 | h. Share means to provide material to the public by any means or 400 | process that requires permission under the Licensed Rights, such 401 | as reproduction, public display, public performance, distribution, 402 | dissemination, communication, or importation, and to make material 403 | available to the public including in ways that members of the 404 | public may access the material from a place and at a time 405 | individually chosen by them. 406 | 407 | i. Sui Generis Database Rights means rights other than copyright 408 | resulting from Directive 96/9/EC of the European Parliament and of 409 | the Council of 11 March 1996 on the legal protection of databases, 410 | as amended and/or succeeded, as well as other essentially 411 | equivalent rights anywhere in the world. 412 | 413 | j. You means the individual or entity exercising the Licensed Rights 414 | under this Public License. Your has a corresponding meaning. 415 | 416 | 417 | Section 2 -- Scope. 418 | 419 | a. License grant. 420 | 421 | 1. Subject to the terms and conditions of this Public License, 422 | the Licensor hereby grants You a worldwide, royalty-free, 423 | non-sublicensable, non-exclusive, irrevocable license to 424 | exercise the Licensed Rights in the Licensed Material to: 425 | 426 | a. reproduce and Share the Licensed Material, in whole or 427 | in part; and 428 | 429 | b. produce and reproduce, but not Share, Adapted Material. 430 | 431 | 2. Exceptions and Limitations. For the avoidance of doubt, where 432 | Exceptions and Limitations apply to Your use, this Public 433 | License does not apply, and You do not need to comply with 434 | its terms and conditions. 435 | 436 | 3. Term. The term of this Public License is specified in Section 437 | 6(a). 438 | 439 | 4. Media and formats; technical modifications allowed. The 440 | Licensor authorizes You to exercise the Licensed Rights in 441 | all media and formats whether now known or hereafter created, 442 | and to make technical modifications necessary to do so. The 443 | Licensor waives and/or agrees not to assert any right or 444 | authority to forbid You from making technical modifications 445 | necessary to exercise the Licensed Rights, including 446 | technical modifications necessary to circumvent Effective 447 | Technological Measures. For purposes of this Public License, 448 | simply making modifications authorized by this Section 2(a) 449 | (4) never produces Adapted Material. 450 | 451 | 5. Downstream recipients. 452 | 453 | a. Offer from the Licensor -- Licensed Material. Every 454 | recipient of the Licensed Material automatically 455 | receives an offer from the Licensor to exercise the 456 | Licensed Rights under the terms and conditions of this 457 | Public License. 458 | 459 | b. No downstream restrictions. You may not offer or impose 460 | any additional or different terms or conditions on, or 461 | apply any Effective Technological Measures to, the 462 | Licensed Material if doing so restricts exercise of the 463 | Licensed Rights by any recipient of the Licensed 464 | Material. 465 | 466 | 6. No endorsement. Nothing in this Public License constitutes or 467 | may be construed as permission to assert or imply that You 468 | are, or that Your use of the Licensed Material is, connected 469 | with, or sponsored, endorsed, or granted official status by, 470 | the Licensor or others designated to receive attribution as 471 | provided in Section 3(a)(1)(A)(i). 472 | 473 | b. Other rights. 474 | 475 | 1. Moral rights, such as the right of integrity, are not 476 | licensed under this Public License, nor are publicity, 477 | privacy, and/or other similar personality rights; however, to 478 | the extent possible, the Licensor waives and/or agrees not to 479 | assert any such rights held by the Licensor to the limited 480 | extent necessary to allow You to exercise the Licensed 481 | Rights, but not otherwise. 482 | 483 | 2. Patent and trademark rights are not licensed under this 484 | Public License. 485 | 486 | 3. To the extent possible, the Licensor waives any right to 487 | collect royalties from You for the exercise of the Licensed 488 | Rights, whether directly or through a collecting society 489 | under any voluntary or waivable statutory or compulsory 490 | licensing scheme. In all other cases the Licensor expressly 491 | reserves any right to collect such royalties. 492 | 493 | 494 | Section 3 -- License Conditions. 495 | 496 | Your exercise of the Licensed Rights is expressly made subject to the 497 | following conditions. 498 | 499 | a. Attribution. 500 | 501 | 1. If You Share the Licensed Material, You must: 502 | 503 | a. retain the following if it is supplied by the Licensor 504 | with the Licensed Material: 505 | 506 | i. identification of the creator(s) of the Licensed 507 | Material and any others designated to receive 508 | attribution, in any reasonable manner requested by 509 | the Licensor (including by pseudonym if 510 | designated); 511 | 512 | ii. a copyright notice; 513 | 514 | iii. a notice that refers to this Public License; 515 | 516 | iv. a notice that refers to the disclaimer of 517 | warranties; 518 | 519 | v. a URI or hyperlink to the Licensed Material to the 520 | extent reasonably practicable; 521 | 522 | b. indicate if You modified the Licensed Material and 523 | retain an indication of any previous modifications; and 524 | 525 | c. indicate the Licensed Material is licensed under this 526 | Public License, and include the text of, or the URI or 527 | hyperlink to, this Public License. 528 | 529 | For the avoidance of doubt, You do not have permission under 530 | this Public License to Share Adapted Material. 531 | 532 | 2. You may satisfy the conditions in Section 3(a)(1) in any 533 | reasonable manner based on the medium, means, and context in 534 | which You Share the Licensed Material. For example, it may be 535 | reasonable to satisfy the conditions by providing a URI or 536 | hyperlink to a resource that includes the required 537 | information. 538 | 539 | 3. If requested by the Licensor, You must remove any of the 540 | information required by Section 3(a)(1)(A) to the extent 541 | reasonably practicable. 542 | 543 | 544 | Section 4 -- Sui Generis Database Rights. 545 | 546 | Where the Licensed Rights include Sui Generis Database Rights that 547 | apply to Your use of the Licensed Material: 548 | 549 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 550 | to extract, reuse, reproduce, and Share all or a substantial 551 | portion of the contents of the database, provided You do not Share 552 | Adapted Material; 553 | b. if You include all or a substantial portion of the database 554 | contents in a database in which You have Sui Generis Database 555 | Rights, then the database in which You have Sui Generis Database 556 | Rights (but not its individual contents) is Adapted Material; and 557 | c. You must comply with the conditions in Section 3(a) if You Share 558 | all or a substantial portion of the contents of the database. 559 | 560 | For the avoidance of doubt, this Section 4 supplements and does not 561 | replace Your obligations under this Public License where the Licensed 562 | Rights include other Copyright and Similar Rights. 563 | 564 | 565 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 566 | 567 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 568 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 569 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 570 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 571 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 572 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 573 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 574 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 575 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 576 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 577 | 578 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 579 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 580 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 581 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 582 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 583 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 584 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 585 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 586 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 587 | 588 | c. The disclaimer of warranties and limitation of liability provided 589 | above shall be interpreted in a manner that, to the extent 590 | possible, most closely approximates an absolute disclaimer and 591 | waiver of all liability. 592 | 593 | 594 | Section 6 -- Term and Termination. 595 | 596 | a. This Public License applies for the term of the Copyright and 597 | Similar Rights licensed here. However, if You fail to comply with 598 | this Public License, then Your rights under this Public License 599 | terminate automatically. 600 | 601 | b. Where Your right to use the Licensed Material has terminated under 602 | Section 6(a), it reinstates: 603 | 604 | 1. automatically as of the date the violation is cured, provided 605 | it is cured within 30 days of Your discovery of the 606 | violation; or 607 | 608 | 2. upon express reinstatement by the Licensor. 609 | 610 | For the avoidance of doubt, this Section 6(b) does not affect any 611 | right the Licensor may have to seek remedies for Your violations 612 | of this Public License. 613 | 614 | c. For the avoidance of doubt, the Licensor may also offer the 615 | Licensed Material under separate terms or conditions or stop 616 | distributing the Licensed Material at any time; however, doing so 617 | will not terminate this Public License. 618 | 619 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 620 | License. 621 | 622 | 623 | Section 7 -- Other Terms and Conditions. 624 | 625 | a. The Licensor shall not be bound by any additional or different 626 | terms or conditions communicated by You unless expressly agreed. 627 | 628 | b. Any arrangements, understandings, or agreements regarding the 629 | Licensed Material not stated herein are separate from and 630 | independent of the terms and conditions of this Public License. 631 | 632 | 633 | Section 8 -- Interpretation. 634 | 635 | a. For the avoidance of doubt, this Public License does not, and 636 | shall not be interpreted to, reduce, limit, restrict, or impose 637 | conditions on any use of the Licensed Material that could lawfully 638 | be made without permission under this Public License. 639 | 640 | b. To the extent possible, if any provision of this Public License is 641 | deemed unenforceable, it shall be automatically reformed to the 642 | minimum extent necessary to make it enforceable. If the provision 643 | cannot be reformed, it shall be severed from this Public License 644 | without affecting the enforceability of the remaining terms and 645 | conditions. 646 | 647 | c. No term or condition of this Public License will be waived and no 648 | failure to comply consented to unless expressly agreed to by the 649 | Licensor. 650 | 651 | d. Nothing in this Public License constitutes or may be interpreted 652 | as a limitation upon, or waiver of, any privileges and immunities 653 | that apply to the Licensor or You, including from the legal 654 | processes of any jurisdiction or authority. 655 | 656 | ======================================================================= 657 | 658 | Creative Commons is not a party to its public 659 | licenses. Notwithstanding, Creative Commons may elect to apply one of 660 | its public licenses to material it publishes and in those instances 661 | will be considered the “Licensor.” The text of the Creative Commons 662 | public licenses is dedicated to the public domain under the CC0 Public 663 | Domain Dedication. Except for the limited purpose of indicating that 664 | material is shared under a Creative Commons public license or as 665 | otherwise permitted by the Creative Commons policies published at 666 | creativecommons.org/policies, Creative Commons does not authorize the 667 | use of the trademark "Creative Commons" or any other trademark or logo 668 | of Creative Commons without its prior written consent including, 669 | without limitation, in connection with any unauthorized modifications 670 | to any of its public licenses or any other arrangements, 671 | understandings, or agreements concerning use of licensed material. For 672 | the avoidance of doubt, this paragraph does not form part of the 673 | public licenses. 674 | 675 | Creative Commons may be contacted at creativecommons.org. 676 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025 IBM Corporation and others. 2 | // Licensed under Creative Commons Attribution-NoDerivatives 3 | // 4.0 International (CC BY-ND 4.0) 4 | // https://creativecommons.org/licenses/by-nd/4.0/ 5 | // 6 | // Contributors: 7 | // IBM Corporation 8 | :projectid: microprofile-openapi 9 | :page-layout: guide-multipane 10 | :page-duration: 20 minutes 11 | :page-releasedate: 2018-03-16 12 | :page-guide-category: microprofile 13 | :page-essential: false 14 | :page-description: Explore how to document and filter RESTful APIs from code or static files by using MicroProfile OpenAPI. 15 | :page-tags: ['microprofile'] 16 | :page-permalink: /guides/{projectid} 17 | :page-related-guides: ['cdi-intro', 'microprofile-config'] 18 | :common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod 19 | :source-highlighter: prettify 20 | :page-seo-title: Documenting RESTful APIs using MicroProfile OpenAPI 21 | :page-seo-description: A tutorial on how to document and filter RESTful APIs by using MicroProfile OpenAPI 22 | :guide-author: Open Liberty 23 | = Documenting RESTful APIs 24 | 25 | [.hidden] 26 | NOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website]. 27 | 28 | Explore how to document and filter RESTful APIs from code or static files by using MicroProfile OpenAPI. 29 | 30 | :openapi-url: http://localhost:9080/openapi 31 | :inv-url: http://localhost:9080/inventory/systems 32 | :sys-url: http://localhost:9080/inventory/properties 33 | 34 | == What you'll learn 35 | 36 | You will learn how to document and filter RESTful APIs from annotations, POJOs, and static OpenAPI files by using MicroProfile OpenAPI. 37 | 38 | The OpenAPI specification, previously known as the Swagger specification, defines a standard interface for documenting and exposing RESTful APIs. This specification allows both humans and computers to understand or process the functionalities of services without requiring direct access to underlying source code or documentation. The MicroProfile OpenAPI specification provides a set of Java interfaces and programming models that allow Java developers to natively produce OpenAPI v3 documents from their JAX-RS applications. 39 | 40 | You will document the RESTful APIs of the provided `inventory` service, which serves two endpoints, `inventory/systems` and `inventory/properties`. These two endpoints function the same way as in the other MicroProfile guides. 41 | 42 | Before you proceed, note that the 1.0 version of the MicroProfile OpenAPI specification does not define how the `/openapi` endpoint may be partitioned in the event of multiple JAX-RS applications running on the same server. In other words, you must stick to one JAX-RS application per server instance as the behaviour for handling multiple applications is currently undefined. 43 | 44 | 45 | // ================================================================================================= 46 | // Getting Started 47 | // ================================================================================================= 48 | [role='command'] 49 | include::{common-includes}/gitclone.adoc[] 50 | 51 | // ================================================================================================= 52 | // Try what you'll build 53 | // ================================================================================================= 54 | [role='command'] 55 | include::{common-includes}/twyb-intro-mvnw.adoc[] 56 | 57 | 58 | ifndef::cloud-hosted[] 59 | Next, point your browser to the {openapi-url}[{openapi-url}^] URL and you'll see the RESTful APIs of the `inventory` service. You can also point to the {openapi-url}/ui[{openapi-url}/ui^] URL for a more interactive view of the deployed APIs. This UI is built from the https://swagger.io/tools/swagger-ui/[Open Source Swagger UI^] and renders the generated `/openapi` document into a very user friendly page. 60 | endif::[] 61 | 62 | ifdef::cloud-hosted[] 63 | To open a new command-line session, select **Terminal** > **New Terminal** from the menu of the IDE. 64 | 65 | Next, run the following curl command to see the RESTful APIs of the ***inventory*** service: 66 | ```bash 67 | curl http://localhost:9080/openapi 68 | ``` 69 | 70 | A UI is also available for a more interactive view of the deployed APIs. Click the following button to visit the UI by the ***/openapi/ui*** endpoint. 71 | ::startApplication{port="9080" display="external" name="Visit OpenAPI UI" route="/openapi/ui"} 72 | 73 | This UI is built from the [Open Source Swagger UI](https://swagger.io/tools/swagger-ui), which renders the generated **/openapi** document into a very user friendly page. 74 | endif::[] 75 | 76 | [role='command'] 77 | include::{common-includes}/twyb-end-mvnw.adoc[] 78 | 79 | // ================================================================================================= 80 | // Generating APIs 81 | // ================================================================================================= 82 | 83 | == Generating the OpenAPI document for the inventory service 84 | 85 | You can generate an OpenAPI document in various ways. First, because all Jakarta Restful Web Services annotations are processed by default, you can augment your existing Jakarta Restful Web Services annotations with OpenAPI annotations to enrich your APIs with a minimal amount of work. Second, you can use a set of predefined models to manually create all elements of the OpenAPI tree. Finally, you can filter various elements of the OpenAPI tree, changing them to your liking or removing them entirely. 86 | 87 | Navigate to the `start` directory to begin. 88 | // cloud hosted instructions 89 | ifdef::cloud-hosted[] 90 | ```bash 91 | cd /home/project/guide-microprofile-openapi/start 92 | ``` 93 | endif::[] 94 | 95 | [role='command'] 96 | include::{common-includes}/devmode-mvnw-start.adoc[] 97 | 98 | Because the Jakarta Restful Web Services framework handles basic API generation for Jakarta Restful Web Services annotations, a skeleton OpenAPI tree will be generated from the `inventory` service. You can use this tree as a starting point and augment it with annotations and code to produce a complete OpenAPI document. 99 | 100 | 101 | ifndef::cloud-hosted[] 102 | Now, visit the {openapi-url}[{openapi-url}^] URL to see the generated OpenAPI tree. You can also visit the {openapi-url}/ui[{openapi-url}/ui^] URL for a more interactive view of the APIs. 103 | endif::[] 104 | 105 | ifdef::cloud-hosted[] 106 | Now, run the following curl command to see the generated OpenAPI tree: 107 | ```bash 108 | curl http://localhost:9080/openapi 109 | ``` 110 | 111 | Click the following button to visit the UI by the ***/openapi/ui*** endpoint for a more interactive view of the APIs. 112 | ::startApplication{port="9080" display="external" name="Visit OpenAPI UI" route="/openapi/ui"} 113 | endif::[] 114 | 115 | === Augmenting the existing Jakarta Restful Web Services annotations with OpenAPI annotations 116 | 117 | Because all Jakarta Restful Web Services annotations are processed by default, you can augment the existing code with OpenAPI annotations without needing to rewrite portions of the OpenAPI document that are already covered by the Jakarta Restful Web Services framework. 118 | 119 | [role='code_command hotspot file=0', subs="quotes"] 120 | ---- 121 | #Replace the `InventoryResource` class.# 122 | `src/main/java/io/openliberty/guides/inventory/InventoryResource.java` 123 | ---- 124 | 125 | [role="edit_command_text"] 126 | Add OpenAPI [hotspot=APIResponse file=0]`@APIResponse`, [hotspot=APIResponseSchema file=0]`@APIResponseSchema`, [hotspot=Operation file=0]`@Operation`, and [hotspot=Parameter file=0]`@Parameter` annotations to the two JAX-RS endpoint methods, [hotspot=host-property hotspot=Parameter file=0]`getPropertiesForHost()` and [hotspot=listContents file=0]`listContents()`. 127 | 128 | 129 | InventoryResource.java 130 | [source, Java, linenums, role='code_column hide_tags=copyright'] 131 | ---- 132 | include::finish/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[] 133 | ---- 134 | 135 | Clearly, there are many more OpenAPI annotations now, so let’s break them down: 136 | 137 | [cols="35, 200", options="header"] 138 | |=== 139 | | *Annotation* | *Description* 140 | | [hotspot=APIResponse file=0]`@APIResponse` | Describes a single response from an API operation. 141 | | [hotspot=APIResponseSchema file=0]`@APIResponseSchema` | Convenient short-hand way to specify a simple response with a Java class that could otherwise be specified using @APIResponse. 142 | | [hotspot=Operation file=0]`@Operation` | Describes a single API operation on a path. 143 | | [hotspot=Parameter file=0]`@Parameter` | Describes a single operation parameter. 144 | |=== 145 | 146 | ifndef::cloud-hosted[] 147 | Because the Open Liberty instance was started in dev mode at the beginning of the guide, your changes were automatically picked up. Refresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree. The two endpoints at which your JAX-RS endpoint methods are served are now more meaningful: 148 | endif::[] 149 | 150 | ifdef::cloud-hosted[] 151 | Because the Open Liberty instance was started in dev mode at the beginning of the guide, your changes were automatically picked up. Run the following curl command to see the updated OpenAPI tree: 152 | ```bash 153 | curl http://localhost:9080/openapi 154 | ``` 155 | 156 | The two endpoints at which your JAX-RS endpoint methods are served are now more meaningful: 157 | endif::[] 158 | 159 | [source, YAML, role="no_copy"] 160 | ---- 161 | /inventory/systems: 162 | get: 163 | summary: List inventory contents. 164 | description: Returns the currently stored host:properties pairs in the inventory. 165 | responses: 166 | "200": 167 | description: host:properties pairs stored in the inventory. 168 | content: 169 | application/json: 170 | schema: 171 | $ref: '#/components/schemas/InventoryList' 172 | /inventory/systems/{hostname}: 173 | get: 174 | summary: Get JVM system properties for particular host 175 | description: Retrieves and returns the JVM system properties from the system 176 | service running on the particular host. 177 | parameters: 178 | - name: hostname 179 | in: path 180 | description: The host for whom to retrieve the JVM system properties for. 181 | required: true 182 | schema: 183 | type: string 184 | example: localhost 185 | responses: 186 | "404": 187 | description: Missing description 188 | content: 189 | application/json: {} 190 | "200": 191 | description: JVM system properties of a particular host. 192 | content: 193 | application/json: 194 | schema: 195 | type: object 196 | ---- 197 | 198 | 199 | OpenAPI annotations can also be added to POJOs to describe what they represent. Currently, your OpenAPI document doesn't have a very meaningful description of the [hotspot=InventoryListClass file=1]`InventoryList` POJO and hence it's very difficult to tell exactly what that POJO is used for. To describe the [hotspot=InventoryListClass file=1]`InventoryList` POJO in more detail, augment the [hotspot file=1]`src/main/java/io/openliberty/guides/inventory/model/InventoryList.java` file with some OpenAPI annotations. 200 | 201 | [role='code_command hotspot file=1', subs="quotes"] 202 | ---- 203 | #Replace the `InventoryList` class.# 204 | `src/main/java/io/openliberty/guides/inventory/model/InventoryList.java` 205 | ---- 206 | 207 | [role='edit_command_text'] 208 | Add OpenAPI [hotspot=InventoryList hotspot=Systems file=1]`@Schema` annotations to the [hotspot=InventoryList file=1]`InventoryList` class and the [hotspot=Systems file=1]`systems` variable. 209 | 210 | InventoryList.java 211 | [source, Java, linenums, role='code_column hide_tags=copyright'] 212 | ---- 213 | include::finish/src/main/java/io/openliberty/guides/inventory/model/InventoryList.java[] 214 | ---- 215 | 216 | Likewise, annotate the [hotspot file=2]`src/main/java/io/openliberty/guides/inventory/model/SystemData.java` POJO, which is referenced in the [hotspot file=1]`InventoryList` class. 217 | 218 | [role='code_command hotspot file=2', subs="quotes"] 219 | ---- 220 | #Replace the `SystemData` class.# 221 | `src/main/java/io/openliberty/guides/inventory/model/SystemData.java` 222 | ---- 223 | 224 | [role='edit_command_text'] 225 | Add OpenAPI [hotspot=SystemData hotspot=Hostname hotspot=Properties file=2]`@Schema` annotations to the [hotspot=SystemData file=2]`SystemData` class, the [hotspot=Hostname file=2]`hostname` variable and the [hotspot=Properties file=2]`properties` variable. 226 | 227 | SystemData.java 228 | [source, Java, linenums, role='code_column hide_tags=copyright'] 229 | ---- 230 | include::finish/src/main/java/io/openliberty/guides/inventory/model/SystemData.java[] 231 | ---- 232 | 233 | ifndef::cloud-hosted[] 234 | Refresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree: 235 | endif::[] 236 | 237 | ifdef::cloud-hosted[] 238 | Run the following curl command to see the updated OpenAPI tree: 239 | ```bash 240 | curl http://localhost:9080/openapi 241 | ``` 242 | endif::[] 243 | 244 | [source, YAML, role="no_copy"] 245 | ---- 246 | components: 247 | schemas: 248 | InventoryList: 249 | description: POJO that represents the inventory contents. 250 | required: 251 | - systems 252 | type: object 253 | properties: 254 | systems: 255 | type: array 256 | items: 257 | $ref: '#/components/schemas/SystemData' 258 | total: 259 | format: int32 260 | type: integer 261 | SystemData: 262 | description: POJO that represents a single inventory entry. 263 | required: 264 | - hostname 265 | - properties 266 | type: object 267 | properties: 268 | hostname: 269 | type: string 270 | properties: 271 | type: object 272 | ---- 273 | 274 | 275 | === Filtering the OpenAPI tree elements 276 | 277 | Filtering of certain elements and fields of the generated OpenAPI document can be done by using the `OASFilter` interface. 278 | 279 | [role="code_command hotspot file=0", subs="quotes"] 280 | ---- 281 | #Create the `InventoryOASFilter` class.# 282 | `src/main/java/io/openliberty/guides/inventory/filter/InventoryOASFilter.java` 283 | ---- 284 | InventoryOASFilter.java 285 | [source, Java, linenums, role='code_column hide_tags=copyright'] 286 | ---- 287 | include::finish/src/main/java/io/openliberty/guides/inventory/filter/InventoryOASFilter.java[] 288 | ---- 289 | 290 | The [hotspot=filterAPIResponse file=0]`filterAPIResponse()` method allows filtering of `APIResponse` elements. When you override this method, it will be called once for every `APIResponse` element in the OpenAPI tree. In this case, you are matching the `404` response that is returned by the `/inventory/systems/{hostname}` endpoint and setting the previously missing description. To remove an `APIResponse` element or another filterable element, simply return `null`. 291 | 292 | The [hotspot=filterOpenAPI file=0]`filterOpenAPI()` method allows filtering of the singleton [hotspot=OpenAPI file=0]`OpenAPI` element. Unlike other filter methods, when you override [hotspot=filterOpenAPI file=0]`filterOpenAPI()`, it is called only once as the last method for a particular filter. Hence, make sure that it doesn't override any other filter operations that are called before it. Your current OpenAPI document doesn't provide much information on the application itself or on what server and port it runs on. This information is usually provided in the `info` and `servers` elements, which are currently missing. Use the `OASFactory` class to manually set these and other elements of the OpenAPI tree from the `org.eclipse.microprofile.openapi.models` package. The [hotspot=OpenAPI file=0]`OpenAPI` element is the only element that cannot be removed, because that would mean removing the whole OpenAPI tree. 293 | 294 | Each filtering method is called once for each corresponding element in the model tree. You can think of each method as a callback for various key OpenAPI elements. 295 | 296 | Before you can use the filter class that you created, you need to create the [hotspot file=1]`microprofile-config.properties` file. 297 | 298 | [role="code_command hotspot file=1", subs="quotes"] 299 | ---- 300 | #Create the configuration file.# 301 | `src/main/resources/META-INF/microprofile-config.properties` 302 | ---- 303 | microprofile-config.properties 304 | [source, text, linenums, role='code_column hide_tags=Scan'] 305 | ---- 306 | include::finish/src/main/resources/META-INF/microprofile-config.properties[] 307 | ---- 308 | 309 | This configuration file is picked up automatically by MicroProfile Config and registers your filter by passing in the fully qualified name of the filter class into the [hotspot=Config file=1]`mp.openapi.filter` property. 310 | 311 | ifndef::cloud-hosted[] 312 | Refresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree: 313 | endif::[] 314 | 315 | ifdef::cloud-hosted[] 316 | Run the following curl command to see the updated OpenAPI tree: 317 | ```bash 318 | curl http://localhost:9080/openapi 319 | ``` 320 | endif::[] 321 | 322 | [source, yaml, role="no_copy"] 323 | ---- 324 | info: 325 | title: Inventory App 326 | version: "1.0" 327 | description: App for storing JVM system properties of various hosts. 328 | license: 329 | name: Eclipse Public License - v 2.0 330 | url: https://www.eclipse.org/legal/epl-2.0 331 | 332 | ... 333 | 334 | servers: 335 | - url: "http://localhost:{port}" 336 | description: Simple Open Liberty. 337 | variables: 338 | port: 339 | default: "9080" 340 | description: Server HTTP port. 341 | ---- 342 | 343 | [source, yaml, role="no_copy"] 344 | ---- 345 | responses: 346 | "404": 347 | description: Invalid hostname or the system service may not be running on 348 | the particular host. 349 | content: 350 | application/json: {} 351 | ---- 352 | 353 | For more information about which elements you can filter, see the https://openliberty.io/docs/latest/reference/javadoc/microprofile-7.0-javadoc.html[MicroProfile API documentation^]. 354 | 355 | To learn more about MicroProfile Config, visit the MicroProfile Config https://github.com/eclipse/microprofile-config[GitHub repository^] and try one of the MicroProfile Config https://openliberty.io/guides/?search=Config[guides^]. 356 | 357 | 358 | // ================================================================================================= 359 | // Pre-generated APIs 360 | // ================================================================================================= 361 | 362 | == Using pregenerated OpenAPI documents 363 | 364 | As an alternative to generating the OpenAPI model tree from code, you can provide a valid pregenerated OpenAPI document to describe your APIs. This document must be named `openapi` with a `yml`, `yaml`, or `json` extension and be placed under the `META-INF` directory. Depending on the scenario, the document might be fully or partially complete. If the document is fully complete, then you can disable annotation scanning entirely by setting the `mp.openapi.scan.disable` MicroProfile Config property to `true`. If the document is partially complete, then you can augment it with code. 365 | 366 | To use the pre-generated OpenAPI document, create the OpenAPI document YAML file. 367 | 368 | [role="code_command hotspot file=0", subs="quotes"] 369 | ---- 370 | #Create the OpenAPI document file.# 371 | `src/main/resources/META-INF/openapi.yaml` 372 | ---- 373 | 374 | 375 | openapi.yaml 376 | [source, text, linenums, role='code_column'] 377 | ---- 378 | include::finish/src/main/resources/META-INF/openapi.yaml[] 379 | ---- 380 | 381 | This document is the same as your current OpenAPI document with extra APIs for the `/inventory/properties` endpoint. This document is complete so you can also add the [hotspot=Scan file=1]`mp.openapi.scan.disable` property and set it to `true` in the [hotspot file=1]`src/main/resources/META-INF/microprofile-config.properties` file. 382 | 383 | [role="code_command hotspot file=1", subs="quotes"] 384 | ---- 385 | #Replace the configuration file.# 386 | `src/main/resources/META-INF/microprofile-config.properties` 387 | ---- 388 | 389 | [role="edit_command_text"] 390 | Add and set the [hotspot=Scan file=1]`mp.openapi.scan.disable` property to `true`. 391 | 392 | microprofile-config.properties 393 | [source, text, linenums, role='code_column'] 394 | ---- 395 | include::finish/src/main/resources/META-INF/microprofile-config.properties[] 396 | ---- 397 | 398 | ifndef::cloud-hosted[] 399 | Refresh the {openapi-url}[{openapi-url}^] URL to see the updated OpenAPI tree: 400 | endif::[] 401 | 402 | ifdef::cloud-hosted[] 403 | Run the following curl command to see the updated OpenAPI tree: 404 | ```bash 405 | curl http://localhost:9080/openapi 406 | ``` 407 | endif::[] 408 | 409 | [source, yml, role="no_copy"] 410 | ---- 411 | /inventory/properties: 412 | get: 413 | operationId: getProperties 414 | responses: 415 | "200": 416 | description: JVM system properties of the host running this service. 417 | content: 418 | application/json: 419 | schema: 420 | type: object 421 | additionalProperties: 422 | type: string 423 | ---- 424 | 425 | 426 | // ================================================================================================= 427 | // Testing the services 428 | // ================================================================================================= 429 | 430 | == Testing the service 431 | 432 | // static guide instructions: 433 | ifndef::cloud-hosted[] 434 | No automated tests are provided to verify the correctness of the generated OpenAPI document. Manually verify the document by visiting the {openapi-url}[{openapi-url}^] or the {openapi-url}/ui[{openapi-url}/ui^] URL. 435 | endif::[] 436 | 437 | // cloud-hosted guide instructions: 438 | ifdef::cloud-hosted[] 439 | No automated tests are provided to verify the correctness of the generated OpenAPI document. Manually verify the document by visiting the ***http://localhost:9080/openapi*** or the ***http://localhost:9080/openapi/ui*** URL. 440 | endif::[] 441 | 442 | A few tests are included for you to test the basic functionality of the `inventory` service. If a test failure occurs, then you might have introduced a bug into the code. These tests will run automatically as a part of the integration test suite. 443 | 444 | [role='command'] 445 | include::{common-includes}/devmode-test.adoc[] 446 | 447 | You will see the following output: 448 | 449 | [source, role="no_copy"] 450 | ---- 451 | ------------------------------------------------------- 452 | T E S T S 453 | ------------------------------------------------------- 454 | Running it.io.openliberty.guides.system.SystemEndpointIT 455 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.4 sec - in it.io.openliberty.guides.system.SystemEndpointIT 456 | Running it.io.openliberty.guides.inventory.InventoryEndpointIT 457 | [WARNING ] Interceptor for {http://client.inventory.guides.openliberty.io/}SystemClient has thrown exception, unwinding now 458 | Could not send Message. 459 | [err] The specified host is unknown: java.net.UnknownHostException: UnknownHostException invoking http://badhostname:9080/inventory/properties: badhostname 460 | Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.264 sec - in it.io.openliberty.guides.inventory.InventoryEndpointIT 461 | 462 | Results : 463 | 464 | Tests run: 4, Failures: 0, Errors: 0, Skipped: 0 465 | ---- 466 | 467 | The warning and error messages are expected and result from a request to a bad or an unknown hostname. This request is made in the `testUnknownHost()` test from the `InventoryEndpointIT` integration test. 468 | 469 | [role='command'] 470 | include::{common-includes}/devmode-quit-ctrlc.adoc[] 471 | 472 | 473 | // ================================================================================================= 474 | // Great work! You're done! 475 | // ================================================================================================= 476 | 477 | == Great work! You're done! 478 | 479 | You have just documented and filtered the APIs of the `inventory` service from both the code and a static file by using MicroProfile OpenAPI in Open Liberty. 480 | 481 | Feel free to try one of the related MicroProfile guides. They demonstrate additional technologies that you can learn and expand on top of what you built here. 482 | 483 | For more in-depth examples of MicroProfile OpenAPI, try one of the demo applications available in the MicroProfile OpenAPI https://github.com/eclipse/microprofile-open-api/tree/master/tck/src/main/java/org/eclipse/microprofile/openapi/apps[GitHub repository^]. 484 | 485 | 486 | include::{common-includes}/attribution.adoc[subs="attributes"] 487 | -------------------------------------------------------------------------------- /finish/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-openapi/b913ea17410d1cda3e4e70f3cee61b0ba99f734b/finish/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /finish/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar 3 | -------------------------------------------------------------------------------- /finish/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Apache Maven Wrapper startup batch script, version 3.3.2 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | # e.g. to debug Maven itself, use 32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | # ---------------------------------------------------------------------------- 35 | 36 | if [ -z "$MAVEN_SKIP_RC" ]; then 37 | 38 | if [ -f /usr/local/etc/mavenrc ]; then 39 | . /usr/local/etc/mavenrc 40 | fi 41 | 42 | if [ -f /etc/mavenrc ]; then 43 | . /etc/mavenrc 44 | fi 45 | 46 | if [ -f "$HOME/.mavenrc" ]; then 47 | . "$HOME/.mavenrc" 48 | fi 49 | 50 | fi 51 | 52 | # OS specific support. $var _must_ be set to either true or false. 53 | cygwin=false 54 | darwin=false 55 | mingw=false 56 | case "$(uname)" in 57 | CYGWIN*) cygwin=true ;; 58 | MINGW*) mingw=true ;; 59 | Darwin*) 60 | darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | JAVA_HOME="$(/usr/libexec/java_home)" 66 | export JAVA_HOME 67 | else 68 | JAVA_HOME="/Library/Java/Home" 69 | export JAVA_HOME 70 | fi 71 | fi 72 | ;; 73 | esac 74 | 75 | if [ -z "$JAVA_HOME" ]; then 76 | if [ -r /etc/gentoo-release ]; then 77 | JAVA_HOME=$(java-config --jre-home) 78 | fi 79 | fi 80 | 81 | # For Cygwin, ensure paths are in UNIX format before anything is touched 82 | if $cygwin; then 83 | [ -n "$JAVA_HOME" ] \ 84 | && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 85 | [ -n "$CLASSPATH" ] \ 86 | && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 87 | fi 88 | 89 | # For Mingw, ensure paths are in UNIX format before anything is touched 90 | if $mingw; then 91 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ 92 | && JAVA_HOME="$( 93 | cd "$JAVA_HOME" || ( 94 | echo "cannot cd into $JAVA_HOME." >&2 95 | exit 1 96 | ) 97 | pwd 98 | )" 99 | fi 100 | 101 | if [ -z "$JAVA_HOME" ]; then 102 | javaExecutable="$(which javac)" 103 | if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then 104 | # readlink(1) is not available as standard on Solaris 10. 105 | readLink=$(which readlink) 106 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then 107 | if $darwin; then 108 | javaHome="$(dirname "$javaExecutable")" 109 | javaExecutable="$(cd "$javaHome" && pwd -P)/javac" 110 | else 111 | javaExecutable="$(readlink -f "$javaExecutable")" 112 | fi 113 | javaHome="$(dirname "$javaExecutable")" 114 | javaHome=$(expr "$javaHome" : '\(.*\)/bin') 115 | JAVA_HOME="$javaHome" 116 | export JAVA_HOME 117 | fi 118 | fi 119 | fi 120 | 121 | if [ -z "$JAVACMD" ]; then 122 | if [ -n "$JAVA_HOME" ]; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ]; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD="$JAVA_HOME/jre/sh/java" 126 | else 127 | JAVACMD="$JAVA_HOME/bin/java" 128 | fi 129 | else 130 | JAVACMD="$( 131 | \unset -f command 2>/dev/null 132 | \command -v java 133 | )" 134 | fi 135 | fi 136 | 137 | if [ ! -x "$JAVACMD" ]; then 138 | echo "Error: JAVA_HOME is not defined correctly." >&2 139 | echo " We cannot execute $JAVACMD" >&2 140 | exit 1 141 | fi 142 | 143 | if [ -z "$JAVA_HOME" ]; then 144 | echo "Warning: JAVA_HOME environment variable is not set." >&2 145 | fi 146 | 147 | # traverses directory structure from process work directory to filesystem root 148 | # first directory with .mvn subdirectory is considered project base directory 149 | find_maven_basedir() { 150 | if [ -z "$1" ]; then 151 | echo "Path not specified to find_maven_basedir" >&2 152 | return 1 153 | fi 154 | 155 | basedir="$1" 156 | wdir="$1" 157 | while [ "$wdir" != '/' ]; do 158 | if [ -d "$wdir"/.mvn ]; then 159 | basedir=$wdir 160 | break 161 | fi 162 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 163 | if [ -d "${wdir}" ]; then 164 | wdir=$( 165 | cd "$wdir/.." || exit 1 166 | pwd 167 | ) 168 | fi 169 | # end of workaround 170 | done 171 | printf '%s' "$( 172 | cd "$basedir" || exit 1 173 | pwd 174 | )" 175 | } 176 | 177 | # concatenates all lines of a file 178 | concat_lines() { 179 | if [ -f "$1" ]; then 180 | # Remove \r in case we run on Windows within Git Bash 181 | # and check out the repository with auto CRLF management 182 | # enabled. Otherwise, we may read lines that are delimited with 183 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word 184 | # splitting rules. 185 | tr -s '\r\n' ' ' <"$1" 186 | fi 187 | } 188 | 189 | log() { 190 | if [ "$MVNW_VERBOSE" = true ]; then 191 | printf '%s\n' "$1" 192 | fi 193 | } 194 | 195 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")") 196 | if [ -z "$BASE_DIR" ]; then 197 | exit 1 198 | fi 199 | 200 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 201 | export MAVEN_PROJECTBASEDIR 202 | log "$MAVEN_PROJECTBASEDIR" 203 | 204 | ########################################################################################## 205 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 206 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 207 | ########################################################################################## 208 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" 209 | if [ -r "$wrapperJarPath" ]; then 210 | log "Found $wrapperJarPath" 211 | else 212 | log "Couldn't find $wrapperJarPath, downloading it ..." 213 | 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 216 | else 217 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 218 | fi 219 | while IFS="=" read -r key value; do 220 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) 221 | safeValue=$(echo "$value" | tr -d '\r') 222 | case "$key" in wrapperUrl) 223 | wrapperUrl="$safeValue" 224 | break 225 | ;; 226 | esac 227 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 228 | log "Downloading from: $wrapperUrl" 229 | 230 | if $cygwin; then 231 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 232 | fi 233 | 234 | if command -v wget >/dev/null; then 235 | log "Found wget ... using wget" 236 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" 237 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 238 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 239 | else 240 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | fi 242 | elif command -v curl >/dev/null; then 243 | log "Found curl ... using curl" 244 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" 245 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 246 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 247 | else 248 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 249 | fi 250 | else 251 | log "Falling back to using Java to download" 252 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" 253 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" 254 | # For Cygwin, switch paths to Windows format before running javac 255 | if $cygwin; then 256 | javaSource=$(cygpath --path --windows "$javaSource") 257 | javaClass=$(cygpath --path --windows "$javaClass") 258 | fi 259 | if [ -e "$javaSource" ]; then 260 | if [ ! -e "$javaClass" ]; then 261 | log " - Compiling MavenWrapperDownloader.java ..." 262 | ("$JAVA_HOME/bin/javac" "$javaSource") 263 | fi 264 | if [ -e "$javaClass" ]; then 265 | log " - Running MavenWrapperDownloader.java ..." 266 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" 267 | fi 268 | fi 269 | fi 270 | fi 271 | ########################################################################################## 272 | # End of extension 273 | ########################################################################################## 274 | 275 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file 276 | wrapperSha256Sum="" 277 | while IFS="=" read -r key value; do 278 | case "$key" in wrapperSha256Sum) 279 | wrapperSha256Sum=$value 280 | break 281 | ;; 282 | esac 283 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 284 | if [ -n "$wrapperSha256Sum" ]; then 285 | wrapperSha256Result=false 286 | if command -v sha256sum >/dev/null; then 287 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then 288 | wrapperSha256Result=true 289 | fi 290 | elif command -v shasum >/dev/null; then 291 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then 292 | wrapperSha256Result=true 293 | fi 294 | else 295 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 296 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 297 | exit 1 298 | fi 299 | if [ $wrapperSha256Result = false ]; then 300 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 301 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 302 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 303 | exit 1 304 | fi 305 | fi 306 | 307 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 308 | 309 | # For Cygwin, switch paths to Windows format before running java 310 | if $cygwin; then 311 | [ -n "$JAVA_HOME" ] \ 312 | && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 313 | [ -n "$CLASSPATH" ] \ 314 | && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 315 | [ -n "$MAVEN_PROJECTBASEDIR" ] \ 316 | && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 317 | fi 318 | 319 | # Provide a "standardized" way to retrieve the CLI args that will 320 | # work with both Windows and non-Windows executions. 321 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" 322 | export MAVEN_CMD_LINE_ARGS 323 | 324 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 325 | 326 | # shellcheck disable=SC2086 # safe args 327 | exec "$JAVACMD" \ 328 | $MAVEN_OPTS \ 329 | $MAVEN_DEBUG_OPTS \ 330 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 331 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 332 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 333 | -------------------------------------------------------------------------------- /finish/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Apache Maven Wrapper startup batch script, version 3.3.2 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 30 | @REM e.g. to debug Maven itself, use 31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 33 | @REM ---------------------------------------------------------------------------- 34 | 35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 36 | @echo off 37 | @REM set title of command window 38 | title %0 39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 41 | 42 | @REM set %HOME% to equivalent of $HOME 43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 44 | 45 | @REM Execute a user defined script before this one 46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 50 | :skipRcPre 51 | 52 | @setlocal 53 | 54 | set ERROR_CODE=0 55 | 56 | @REM To isolate internal variables from possible post scripts, we use another setlocal 57 | @setlocal 58 | 59 | @REM ==== START VALIDATION ==== 60 | if not "%JAVA_HOME%" == "" goto OkJHome 61 | 62 | echo. >&2 63 | echo Error: JAVA_HOME not found in your environment. >&2 64 | echo Please set the JAVA_HOME variable in your environment to match the >&2 65 | echo location of your Java installation. >&2 66 | echo. >&2 67 | goto error 68 | 69 | :OkJHome 70 | if exist "%JAVA_HOME%\bin\java.exe" goto init 71 | 72 | echo. >&2 73 | echo Error: JAVA_HOME is set to an invalid directory. >&2 74 | echo JAVA_HOME = "%JAVA_HOME%" >&2 75 | echo Please set the JAVA_HOME variable in your environment to match the >&2 76 | echo location of your Java installation. >&2 77 | echo. >&2 78 | goto error 79 | 80 | @REM ==== END VALIDATION ==== 81 | 82 | :init 83 | 84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 85 | @REM Fallback to current working directory if not found. 86 | 87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 89 | 90 | set EXEC_DIR=%CD% 91 | set WDIR=%EXEC_DIR% 92 | :findBaseDir 93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 94 | cd .. 95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 96 | set WDIR=%CD% 97 | goto findBaseDir 98 | 99 | :baseDirFound 100 | set MAVEN_PROJECTBASEDIR=%WDIR% 101 | cd "%EXEC_DIR%" 102 | goto endDetectBaseDir 103 | 104 | :baseDirNotFound 105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 106 | cd "%EXEC_DIR%" 107 | 108 | :endDetectBaseDir 109 | 110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 111 | 112 | @setlocal EnableExtensions EnableDelayedExpansion 113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 115 | 116 | :endReadAdditionalConfig 117 | 118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 123 | 124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | if "%MVNW_VERBOSE%" == "true" ( 132 | echo Found %WRAPPER_JAR% 133 | ) 134 | ) else ( 135 | if not "%MVNW_REPOURL%" == "" ( 136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 137 | ) 138 | if "%MVNW_VERBOSE%" == "true" ( 139 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 140 | echo Downloading from: %WRAPPER_URL% 141 | ) 142 | 143 | powershell -Command "&{"^ 144 | "$webclient = new-object System.Net.WebClient;"^ 145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 147 | "}"^ 148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ 149 | "}" 150 | if "%MVNW_VERBOSE%" == "true" ( 151 | echo Finished downloading %WRAPPER_JAR% 152 | ) 153 | ) 154 | @REM End of extension 155 | 156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file 157 | SET WRAPPER_SHA_256_SUM="" 158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B 160 | ) 161 | IF NOT %WRAPPER_SHA_256_SUM%=="" ( 162 | powershell -Command "&{"^ 163 | "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ 164 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ 165 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ 166 | " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ 167 | " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ 168 | " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ 169 | " exit 1;"^ 170 | "}"^ 171 | "}" 172 | if ERRORLEVEL 1 goto error 173 | ) 174 | 175 | @REM Provide a "standardized" way to retrieve the CLI args that will 176 | @REM work with both Windows and non-Windows executions. 177 | set MAVEN_CMD_LINE_ARGS=%* 178 | 179 | %MAVEN_JAVA_EXE% ^ 180 | %JVM_CONFIG_MAVEN_PROPS% ^ 181 | %MAVEN_OPTS% ^ 182 | %MAVEN_DEBUG_OPTS% ^ 183 | -classpath %WRAPPER_JAR% ^ 184 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 185 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 186 | if ERRORLEVEL 1 goto error 187 | goto end 188 | 189 | :error 190 | set ERROR_CODE=1 191 | 192 | :end 193 | @endlocal & set ERROR_CODE=%ERROR_CODE% 194 | 195 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 196 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 197 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 198 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 199 | :skipRcPost 200 | 201 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 202 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 203 | 204 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 205 | 206 | cmd /C exit /B %ERROR_CODE% 207 | -------------------------------------------------------------------------------- /finish/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.openliberty.guides 6 | guide-microprofile-openapi 7 | 1.0-SNAPSHOT 8 | war 9 | 10 | 11 | UTF-8 12 | UTF-8 13 | 11 14 | 11 15 | 16 | 9080 17 | 9443 18 | 19 | 20 | 21 | 22 | 23 | jakarta.platform 24 | jakarta.jakartaee-api 25 | 10.0.0 26 | provided 27 | 28 | 29 | org.eclipse.microprofile 30 | microprofile 31 | 7.0 32 | pom 33 | provided 34 | 35 | 36 | 37 | org.junit.jupiter 38 | junit-jupiter 39 | 5.13.2 40 | test 41 | 42 | 43 | org.jboss.resteasy 44 | resteasy-client 45 | 6.2.12.Final 46 | test 47 | 48 | 49 | org.jboss.resteasy 50 | resteasy-json-binding-provider 51 | 6.2.12.Final 52 | test 53 | 54 | 55 | org.glassfish 56 | jakarta.json 57 | 2.0.1 58 | test 59 | 60 | 61 | 62 | org.apache.commons 63 | commons-lang3 64 | 3.17.0 65 | 66 | 67 | 68 | 69 | ${project.artifactId} 70 | 71 | 72 | org.apache.maven.plugins 73 | maven-war-plugin 74 | 3.4.0 75 | 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-surefire-plugin 80 | 3.5.3 81 | 82 | 83 | io.openliberty.tools 84 | liberty-maven-plugin 85 | 3.11.4 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-failsafe-plugin 91 | 3.5.3 92 | 93 | 94 | ${liberty.var.http.port} 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/InventoryApplication.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides; 13 | 14 | // JAX-RS 15 | import jakarta.ws.rs.ApplicationPath; 16 | import jakarta.ws.rs.core.Application; 17 | 18 | @ApplicationPath("inventory") 19 | public class InventoryApplication extends Application { 20 | 21 | } 22 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/InventoryManager.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory; 13 | 14 | import java.util.List; 15 | import java.util.ArrayList; 16 | import java.util.Collections; 17 | import java.util.Properties; 18 | import jakarta.enterprise.context.ApplicationScoped; 19 | import io.openliberty.guides.inventory.model.InventoryList; 20 | import io.openliberty.guides.inventory.model.SystemData; 21 | 22 | @ApplicationScoped 23 | public class InventoryManager { 24 | 25 | private List systems = Collections.synchronizedList(new ArrayList<>()); 26 | private InventoryUtils invUtils = new InventoryUtils(); 27 | 28 | public Properties get(String hostname) { 29 | return invUtils.getProperties(hostname); 30 | } 31 | 32 | public void add(String hostname, Properties systemProps) { 33 | Properties props = new Properties(); 34 | props.setProperty("os.name", systemProps.getProperty("os.name")); 35 | props.setProperty("user.name", systemProps.getProperty("user.name")); 36 | 37 | SystemData system = new SystemData(hostname, props); 38 | if (!systems.contains(system)) { 39 | systems.add(system); 40 | } 41 | } 42 | 43 | public InventoryList list() { 44 | return new InventoryList(systems); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/InventoryResource.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory; 13 | 14 | import java.util.Properties; 15 | import jakarta.enterprise.context.RequestScoped; 16 | import jakarta.inject.Inject; 17 | import jakarta.ws.rs.GET; 18 | import jakarta.ws.rs.Path; 19 | import jakarta.ws.rs.PathParam; 20 | import jakarta.ws.rs.Produces; 21 | import jakarta.ws.rs.core.MediaType; 22 | import jakarta.ws.rs.core.Response; 23 | 24 | import org.eclipse.microprofile.openapi.annotations.Operation; 25 | import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; 26 | import org.eclipse.microprofile.openapi.annotations.media.Content; 27 | import org.eclipse.microprofile.openapi.annotations.media.Schema; 28 | import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; 29 | import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; 30 | import org.eclipse.microprofile.openapi.annotations.responses.APIResponseSchema; 31 | import io.openliberty.guides.inventory.model.InventoryList; 32 | 33 | @RequestScoped 34 | @Path("/systems") 35 | public class InventoryResource { 36 | 37 | @Inject 38 | InventoryManager manager; 39 | 40 | @GET 41 | @Path("/{hostname}") 42 | @Produces(MediaType.APPLICATION_JSON) 43 | // tag::host-property[] 44 | // tag::APIResponse[] 45 | @APIResponse( 46 | responseCode = "404", 47 | description = "Missing description", 48 | content = @Content(mediaType = "application/json")) 49 | // end::APIResponse[] 50 | //tag::APIResponseSchema[] 51 | @APIResponseSchema(value = Properties.class, 52 | responseDescription = "JVM system properties of a particular host.", 53 | responseCode = "200") 54 | // end::APIResponseSchema[] 55 | // tag::Operation[] 56 | @Operation( 57 | summary = "Get JVM system properties for particular host", 58 | description = "Retrieves and returns the JVM system properties from the system " 59 | + "service running on the particular host.") 60 | // end::Operation[] 61 | // end::host-property[] 62 | public Response getPropertiesForHost( 63 | // tag::Parameter[] 64 | @Parameter( 65 | description = "The host for whom to retrieve " 66 | + "the JVM system properties for.", 67 | required = true, 68 | example = "localhost", 69 | schema = @Schema(type = SchemaType.STRING)) 70 | // end::Parameter[] 71 | @PathParam("hostname") String hostname) { 72 | // Get properties for host 73 | Properties props = manager.get(hostname); 74 | if (props == null) { 75 | return Response.status(Response.Status.NOT_FOUND) 76 | .entity("{ \"error\" : " 77 | + "\"Unknown hostname " + hostname 78 | + " or the resource may not be " 79 | + "running on the host machine\" }") 80 | .build(); 81 | } 82 | 83 | //Add to inventory to host 84 | manager.add(hostname, props); 85 | return Response.ok(props).build(); 86 | } 87 | 88 | @GET 89 | @Produces(MediaType.APPLICATION_JSON) 90 | // tag::listContents[] 91 | @APIResponseSchema(value = InventoryList.class, 92 | responseDescription = "host:properties pairs stored in the inventory.", 93 | responseCode = "200") 94 | @Operation( 95 | summary = "List inventory contents.", 96 | description = "Returns the currently stored host:properties pairs in the " 97 | + "inventory.") 98 | // end::listContents[] 99 | public InventoryList listContents() { 100 | return manager.list(); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/InventoryUtils.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2024 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory; 13 | 14 | import java.net.URL; 15 | import java.net.UnknownHostException; 16 | import java.net.MalformedURLException; 17 | import jakarta.ws.rs.ProcessingException; 18 | import java.util.Properties; 19 | import org.apache.commons.lang3.exception.ExceptionUtils; 20 | import org.eclipse.microprofile.rest.client.RestClientBuilder; 21 | import io.openliberty.guides.inventory.client.SystemClient; 22 | import io.openliberty.guides.inventory.client.UnknownUrlException; 23 | import io.openliberty.guides.inventory.client.UnknownUrlExceptionMapper; 24 | 25 | public class InventoryUtils { 26 | 27 | private final String SYSTEM_PORT = System.getProperty("http.port", "9080"); 28 | 29 | public Properties getProperties(String hostname) { 30 | try { 31 | String customUrlString = "http://" 32 | + hostname + ":" + SYSTEM_PORT + "/inventory"; 33 | URL customURL = new URL(customUrlString); 34 | SystemClient customRestClient = RestClientBuilder.newBuilder() 35 | .baseUrl(customURL) 36 | .register(UnknownUrlExceptionMapper.class) 37 | .build(SystemClient.class); 38 | return customRestClient.getProperties(); 39 | } catch (ProcessingException ex) { 40 | handleProcessingException(ex); 41 | } catch (UnknownUrlException ex) { 42 | System.err.println("The given URL is unreachable."); 43 | } catch (MalformedURLException ex) { 44 | System.err.println("The given URL is not formatted correctly: " 45 | + ex.getMessage()); 46 | } 47 | return null; 48 | } 49 | 50 | public void handleProcessingException(ProcessingException ex) { 51 | Throwable rootEx = ExceptionUtils.getRootCause(ex); 52 | if (rootEx != null && rootEx instanceof UnknownHostException) { 53 | System.err.println("The specified host is unknown: " + ex.getMessage()); 54 | } else { 55 | throw ex; 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/client/SystemClient.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.client; 13 | 14 | import java.util.Properties; 15 | import jakarta.ws.rs.ProcessingException; 16 | import jakarta.ws.rs.GET; 17 | import jakarta.ws.rs.Path; 18 | import jakarta.ws.rs.Produces; 19 | import jakarta.ws.rs.core.MediaType; 20 | import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; 21 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 22 | 23 | @RegisterRestClient 24 | @RegisterProvider(UnknownUrlExceptionMapper.class) 25 | @Path("/properties") 26 | public interface SystemClient { 27 | 28 | @GET 29 | @Produces(MediaType.APPLICATION_JSON) 30 | Properties getProperties() throws UnknownUrlException, ProcessingException; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/client/UnknownUrlException.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.client; 13 | 14 | public class UnknownUrlException extends Exception { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | public UnknownUrlException() { 19 | super(); 20 | } 21 | 22 | public UnknownUrlException(String message) { 23 | super(message); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/client/UnknownUrlExceptionMapper.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.client; 13 | 14 | import java.util.logging.Logger; 15 | import jakarta.ws.rs.core.MultivaluedMap; 16 | import jakarta.ws.rs.core.Response; 17 | import jakarta.ws.rs.ext.Provider; 18 | import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; 19 | 20 | @Provider 21 | public class UnknownUrlExceptionMapper implements 22 | ResponseExceptionMapper { 23 | 24 | Logger LOG = Logger.getLogger(UnknownUrlExceptionMapper.class.getName()); 25 | 26 | @Override 27 | public boolean handles(int status, MultivaluedMap headers) { 28 | LOG.info("status = " + status); 29 | return status == 404; 30 | } 31 | 32 | @Override 33 | public UnknownUrlException toThrowable(Response response) { 34 | return new UnknownUrlException(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/filter/InventoryOASFilter.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2018, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.filter; 13 | 14 | import java.util.Arrays; 15 | import java.util.Collections; 16 | 17 | import org.eclipse.microprofile.openapi.OASFactory; 18 | import org.eclipse.microprofile.openapi.OASFilter; 19 | import org.eclipse.microprofile.openapi.models.OpenAPI; 20 | import org.eclipse.microprofile.openapi.models.info.License; 21 | import org.eclipse.microprofile.openapi.models.info.Info; 22 | import org.eclipse.microprofile.openapi.models.responses.APIResponse; 23 | import org.eclipse.microprofile.openapi.models.servers.Server; 24 | import org.eclipse.microprofile.openapi.models.servers.ServerVariable; 25 | 26 | public class InventoryOASFilter implements OASFilter { 27 | 28 | @Override 29 | // tag::filterAPIResponse[] 30 | public APIResponse filterAPIResponse(APIResponse apiResponse) { 31 | if ("Missing description".equals(apiResponse.getDescription())) { 32 | apiResponse.setDescription("Invalid hostname or the system service may not " 33 | + "be running on the particular host."); 34 | } 35 | return apiResponse; 36 | } 37 | // end::filterAPIResponse[] 38 | 39 | @Override 40 | // tag::filterOpenAPI[] 41 | // tag::OpenAPI[] 42 | public void filterOpenAPI(OpenAPI openAPI) { 43 | // end::OpenAPI[] 44 | // tag::oasfactory[] 45 | openAPI.setInfo( 46 | OASFactory.createObject(Info.class).title("Inventory App").version("1.0") 47 | .description( 48 | "App for storing JVM system properties of various hosts.") 49 | .license( 50 | OASFactory.createObject(License.class) 51 | .name("Eclipse Public License - v 2.0").url( 52 | "https://www.eclipse.org/legal/epl-2.0"))); 53 | 54 | openAPI.addServer( 55 | OASFactory.createServer() 56 | .url("http://localhost:{port}") 57 | .description("Simple Open Liberty.") 58 | .variables(Collections.singletonMap("port", 59 | OASFactory.createServerVariable() 60 | .defaultValue("9080") 61 | .description("Server HTTP port.")))); 62 | // end::oasfactory[] 63 | } 64 | // end::filterOpenAPI[] 65 | 66 | } 67 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/model/InventoryList.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.model; 13 | 14 | import java.util.List; 15 | import org.eclipse.microprofile.openapi.annotations.media.Schema; 16 | 17 | // tag::InventoryList[] 18 | @Schema(name = "InventoryList", 19 | description = "POJO that represents the inventory contents.") 20 | // end::InventoryList[] 21 | // tag::InventoryListClass[] 22 | public class InventoryList { 23 | 24 | // tag::Systems[] 25 | @Schema(required = true) 26 | // end::Systems[] 27 | private List systems; 28 | 29 | public InventoryList(List systems) { 30 | this.systems = systems; 31 | } 32 | 33 | public List getSystems() { 34 | return systems; 35 | } 36 | 37 | public int getTotal() { 38 | return systems.size(); 39 | } 40 | } 41 | // end::InventoryListClass[] 42 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/inventory/model/SystemData.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.model; 13 | 14 | import java.util.Properties; 15 | import org.eclipse.microprofile.openapi.annotations.media.Schema; 16 | 17 | // tag::SystemData[] 18 | @Schema(name = "SystemData", 19 | description = "POJO that represents a single inventory entry.") 20 | // end::SystemData[] 21 | public class SystemData { 22 | 23 | // tag::Hostname[] 24 | @Schema(required = true) 25 | // end::Hostname[] 26 | private final String hostname; 27 | 28 | // tag::Properties[] 29 | @Schema(required = true) 30 | // end::Properties[] 31 | private final Properties properties; 32 | 33 | public SystemData(String hostname, Properties properties) { 34 | this.hostname = hostname; 35 | this.properties = properties; 36 | } 37 | 38 | public String getHostname() { 39 | return hostname; 40 | } 41 | 42 | public Properties getProperties() { 43 | return properties; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object host) { 48 | if (host instanceof SystemData) { 49 | return hostname.equals(((SystemData) host).getHostname()); 50 | } 51 | return false; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /finish/src/main/java/io/openliberty/guides/system/SystemResource.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.system; 13 | 14 | import java.util.Properties; 15 | 16 | import jakarta.enterprise.context.RequestScoped; 17 | import jakarta.ws.rs.GET; 18 | 19 | import jakarta.ws.rs.Path; 20 | import jakarta.ws.rs.Produces; 21 | import jakarta.ws.rs.core.MediaType; 22 | 23 | @RequestScoped 24 | @Path("/properties") 25 | public class SystemResource { 26 | 27 | @GET 28 | @Produces(MediaType.APPLICATION_JSON) 29 | public Properties getProperties() { 30 | return System.getProperties(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /finish/src/main/liberty/config/server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jakartaee-10.0 5 | microprofile-7.0 6 | restfulWS 7 | jsonp 8 | jsonb 9 | cdi 10 | mpConfig 11 | mpRestClient 12 | mpOpenAPI 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /finish/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | # tag::Scan[] 2 | mp.openapi.scan.disable = true 3 | # end::Scan[] 4 | # tag::Config[] 5 | mp.openapi.filter = io.openliberty.guides.inventory.filter.InventoryOASFilter 6 | # end::Config[] 7 | -------------------------------------------------------------------------------- /finish/src/main/resources/META-INF/openapi.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: 3.0.3 3 | info: 4 | title: Inventory App 5 | description: App for storing JVM system properties of various hosts. 6 | license: 7 | name: Eclipse Public License - v 2.0 8 | url: https://www.eclipse.org/legal/epl-2.0 9 | version: "1.0" 10 | paths: 11 | /inventory/properties: 12 | get: 13 | operationId: getProperties 14 | responses: 15 | "200": 16 | description: JVM system properties of the host running this service. 17 | content: 18 | application/json: 19 | schema: 20 | type: object 21 | additionalProperties: 22 | type: string 23 | /inventory/systems: 24 | get: 25 | summary: List inventory contents. 26 | description: Returns the currently stored host:properties pairs in the inventory. 27 | responses: 28 | "200": 29 | description: host:properties pairs stored in the inventory. 30 | content: 31 | application/json: 32 | schema: 33 | $ref: '#/components/schemas/InventoryList' 34 | /inventory/systems/{hostname}: 35 | get: 36 | summary: Get JVM system properties for particular host 37 | description: Retrieves and returns the JVM system properties from the system 38 | service running on the particular host. 39 | parameters: 40 | - name: hostname 41 | in: path 42 | description: The host for whom to retrieve the JVM system properties for. 43 | required: true 44 | schema: 45 | type: string 46 | example: localhost 47 | responses: 48 | "404": 49 | description: Invalid hostname or the system service may not be running on 50 | the particular host. 51 | content: 52 | application/json: {} 53 | "200": 54 | description: JVM system properties of a particular host. 55 | content: 56 | application/json: 57 | schema: 58 | type: object 59 | components: 60 | schemas: 61 | InventoryList: 62 | description: POJO that represents the inventory contents. 63 | required: 64 | - systems 65 | type: object 66 | properties: 67 | systems: 68 | type: array 69 | items: 70 | $ref: '#/components/schemas/SystemData' 71 | total: 72 | format: int32 73 | type: integer 74 | SystemData: 75 | description: POJO that represents a single inventory entry. 76 | required: 77 | - hostname 78 | - properties 79 | type: object 80 | properties: 81 | hostname: 82 | type: string 83 | properties: 84 | type: object 85 | -------------------------------------------------------------------------------- /finish/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Liberty Project 6 | 7 | 8 | index.html 9 | 10 | -------------------------------------------------------------------------------- /finish/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-openapi/b913ea17410d1cda3e4e70f3cee61b0ba99f734b/finish/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /finish/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 |

Welcome to your Open Liberty application

19 |

Open Liberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. Find out more at openliberty.io.

20 |

Check out the interactive UI made with Swagger UI

21 |
22 |

Eclipse MicroProfile

23 |

24 | The Eclipse MicroProfile project is an open community with the aim of optimizing enterprise Java for a microservices architecture. 25 | MicroProfile evolves with guidance from the community. 26 |

27 |

28 | If you want to share your thoughts, you can post straight to the 29 | MicroProfile Google group. 30 |

31 |

32 | For more information about the features used in this application, see the Open Liberty documentation: 33 |

43 |

44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /finish/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package it.io.openliberty.guides.inventory; 13 | 14 | import static org.junit.jupiter.api.Assertions.assertEquals; 15 | import static org.junit.jupiter.api.Assertions.assertTrue; 16 | 17 | import jakarta.json.JsonArray; 18 | import jakarta.json.JsonObject; 19 | import jakarta.ws.rs.client.Client; 20 | import jakarta.ws.rs.client.ClientBuilder; 21 | import jakarta.ws.rs.core.MediaType; 22 | import jakarta.ws.rs.core.Response; 23 | 24 | import org.junit.jupiter.api.AfterEach; 25 | import org.junit.jupiter.api.BeforeEach; 26 | import org.junit.jupiter.api.BeforeAll; 27 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 28 | import org.junit.jupiter.api.Order; 29 | import org.junit.jupiter.api.Test; 30 | import org.junit.jupiter.api.TestMethodOrder; 31 | 32 | @TestMethodOrder(OrderAnnotation.class) 33 | public class InventoryEndpointIT { 34 | 35 | private static String port; 36 | private static String baseUrl; 37 | 38 | private Client client; 39 | 40 | private final String INVENTORY_PROPERTIES = "inventory/properties"; 41 | private final String INVENTORY_SYSTEMS = "inventory/systems"; 42 | 43 | @BeforeAll 44 | public static void oneTimeSetup() { 45 | port = System.getProperty("http.port"); 46 | baseUrl = "http://localhost:" + port + "/"; 47 | } 48 | 49 | @BeforeEach 50 | public void setup() { 51 | client = ClientBuilder.newClient(); 52 | } 53 | 54 | @AfterEach 55 | public void teardown() { 56 | client.close(); 57 | } 58 | 59 | @Test 60 | @Order(1) 61 | public void testHostRegistration() { 62 | this.visitLocalhost(); 63 | 64 | Response response = this.getResponse(baseUrl + INVENTORY_SYSTEMS); 65 | this.assertResponse(baseUrl, response); 66 | 67 | JsonObject obj = response.readEntity(JsonObject.class); 68 | 69 | JsonArray systems = obj.getJsonArray("systems"); 70 | 71 | boolean localhostExists = false; 72 | for (int n = 0; n < systems.size(); n++) { 73 | localhostExists = systems.getJsonObject(n) 74 | .get("hostname").toString() 75 | .contains("localhost"); 76 | if (localhostExists) { 77 | break; 78 | } 79 | } 80 | assertTrue(localhostExists, "A host was registered, but it was not localhost"); 81 | 82 | response.close(); 83 | } 84 | 85 | @Test 86 | @Order(2) 87 | public void testSystemPropertiesMatch() { 88 | Response invResponse = this.getResponse(baseUrl + INVENTORY_SYSTEMS); 89 | Response sysResponse = this.getResponse(baseUrl + INVENTORY_PROPERTIES); 90 | 91 | this.assertResponse(baseUrl, invResponse); 92 | this.assertResponse(baseUrl, sysResponse); 93 | 94 | JsonObject jsonFromInventory = (JsonObject) 95 | invResponse.readEntity(JsonObject.class) 96 | .getJsonArray("systems") 97 | .getJsonObject(0) 98 | .get("properties"); 99 | 100 | JsonObject jsonFromSystem = sysResponse.readEntity(JsonObject.class); 101 | 102 | String osNameFromInventory = jsonFromInventory.getString("os.name"); 103 | String osNameFromSystem = jsonFromSystem.getString("os.name"); 104 | this.assertProperty("os.name", "localhost", 105 | osNameFromSystem, osNameFromInventory); 106 | 107 | String userNameFromInventory = jsonFromInventory.getString("user.name"); 108 | String userNameFromSystem = jsonFromSystem.getString("user.name"); 109 | this.assertProperty("user.name", "localhost", 110 | userNameFromSystem, userNameFromInventory); 111 | 112 | invResponse.close(); 113 | sysResponse.close(); 114 | } 115 | // tag::testUnknownHost[] 116 | @Test 117 | @Order(3) 118 | public void testUnknownHost() { 119 | Response response = this.getResponse(baseUrl + INVENTORY_SYSTEMS); 120 | this.assertResponse(baseUrl, response); 121 | 122 | Response badResponse = client.target(baseUrl 123 | + INVENTORY_SYSTEMS + "/" 124 | + "badhostname") 125 | .request(MediaType.APPLICATION_JSON) 126 | .get(); 127 | 128 | assertEquals(404, badResponse.getStatus(), 129 | "BadResponse expected status: 404." 130 | + " Response code not as expected."); 131 | 132 | String stringObj = badResponse.readEntity(String.class); 133 | boolean isError = stringObj.contains("error"); 134 | assertTrue(isError, "badhostname is not a valid host" 135 | + "but it didn't raise an error"); 136 | 137 | response.close(); 138 | badResponse.close(); 139 | } 140 | // end::testUnknownHost[] 141 | /** 142 | *

143 | * Returns response information from the specified URL. 144 | *

145 | * 146 | * @param url 147 | * - target URL. 148 | * @return Response object with the response from the specified URL. 149 | */ 150 | private Response getResponse(String url) { 151 | return client.target(url).request().get(); 152 | } 153 | 154 | /** 155 | *

156 | * Asserts that the given URL has the correct response code of 200. 157 | *

158 | * 159 | * @param url 160 | * - target URL. 161 | * @param response 162 | * - response received from the target URL. 163 | */ 164 | private void assertResponse(String url, Response response) { 165 | assertEquals(200, response.getStatus(), "Incorrect response code from " + url); 166 | } 167 | 168 | /** 169 | * Asserts that the specified JVM system property is equivalent in both the 170 | * system and inventory services. 171 | * 172 | * @param propertyName 173 | * - name of the system property to check. 174 | * @param hostname 175 | * - name of JVM's host. 176 | * @param expected 177 | * - expected name. 178 | * @param actual 179 | * - actual name. 180 | */ 181 | private void assertProperty(String propertyName, String hostname, 182 | String expected, String actual) { 183 | assertEquals(expected, actual, "JVM system property [" + propertyName + "] " 184 | + "in the system service does not match the one stored in " 185 | + "the inventory service for " + hostname); 186 | } 187 | 188 | /** 189 | * Makes a simple GET request to inventory/localhost. 190 | */ 191 | private void visitLocalhost() { 192 | Response response = this.getResponse(baseUrl + INVENTORY_PROPERTIES); 193 | this.assertResponse(baseUrl, response); 194 | response.close(); 195 | 196 | Response targetResponse = client.target(baseUrl 197 | + INVENTORY_SYSTEMS + "/localhost") 198 | .request() 199 | .get(); 200 | targetResponse.close(); 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /finish/src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package it.io.openliberty.guides.system; 13 | 14 | import static org.junit.jupiter.api.Assertions.assertEquals; 15 | 16 | import org.junit.jupiter.api.Test; 17 | 18 | import jakarta.json.JsonObject; 19 | 20 | import jakarta.ws.rs.client.Client; 21 | import jakarta.ws.rs.client.ClientBuilder; 22 | import jakarta.ws.rs.client.WebTarget; 23 | import jakarta.ws.rs.core.Response; 24 | 25 | public class SystemEndpointIT { 26 | 27 | @Test 28 | public void testGetProperties() { 29 | String port = System.getProperty("http.port"); 30 | String url = "http://localhost:" + port + "/"; 31 | 32 | Client client = ClientBuilder.newClient(); 33 | 34 | WebTarget target = client.target(url + "inventory/properties"); 35 | Response response = target.request().get(); 36 | 37 | assertEquals(200, response.getStatus(), "Incorrect response code from " + url); 38 | 39 | JsonObject obj = response.readEntity(JsonObject.class); 40 | 41 | assertEquals(System.getProperty("os.name"), 42 | obj.getString("os.name"), 43 | "The system property for the local and remote JVM should match"); 44 | 45 | response.close(); 46 | client.close(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /scripts/dailyBuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | while getopts t:d: flag; do 3 | case "${flag}" in 4 | t) DATE="${OPTARG}" ;; 5 | d) DRIVER="${OPTARG}" ;; 6 | *) echo "Invalid option";; 7 | esac 8 | done 9 | 10 | sed -i "\#liberty-maven-plugin#ahttps://public.dhe.ibm.com/ibmdl/export/pub/software/openliberty/runtime/nightly/$DATE/$DRIVER" pom.xml 11 | cat pom.xml 12 | 13 | ../scripts/testApp.sh 14 | -------------------------------------------------------------------------------- /scripts/testApp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | ./mvnw -version 5 | 6 | ############################################################################## 7 | ## 8 | ## GH actions CI test script 9 | ## 10 | ############################################################################## 11 | 12 | # LMP 3.0+ goals are listed here: https://github.com/OpenLiberty/ci.maven#goals 13 | 14 | ## Rebuild the application 15 | # package - Take the compiled code and package it in its distributable format. 16 | # liberty:create - Create a Liberty server. 17 | # liberty:install-feature - Install a feature packaged as a Subsystem Archive (esa) to the Liberty runtime. 18 | # liberty:deploy - Copy applications to the Liberty server's dropins or apps directory. 19 | ./mvnw -ntp -Dhttp.keepAlive=false \ 20 | -Dmaven.wagon.http.pool=false \ 21 | -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 \ 22 | -q clean package liberty:create liberty:install-feature liberty:deploy 23 | 24 | ## Run the tests 25 | # These commands are separated because if one of the commands fail, the test script will fail and exit. 26 | # e.g if liberty:start fails, then there is no need to run the failsafe commands. 27 | # liberty:start - Start a Liberty server in the background. 28 | # failsafe:integration-test - Runs the integration tests of an application. 29 | # liberty:stop - Stop a Liberty server. 30 | # failsafe:verify - Verifies that the integration tests of an application passed. 31 | ./mvnw -ntp liberty:start 32 | ./mvnw -ntp -Dhttp.keepAlive=false \ 33 | -Dmaven.wagon.http.pool=false \ 34 | -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 \ 35 | failsafe:integration-test liberty:stop 36 | ./mvnw -ntp failsafe:verify 37 | -------------------------------------------------------------------------------- /start/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-openapi/b913ea17410d1cda3e4e70f3cee61b0ba99f734b/start/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /start/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar 3 | -------------------------------------------------------------------------------- /start/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Apache Maven Wrapper startup batch script, version 3.3.2 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | # e.g. to debug Maven itself, use 32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | # ---------------------------------------------------------------------------- 35 | 36 | if [ -z "$MAVEN_SKIP_RC" ]; then 37 | 38 | if [ -f /usr/local/etc/mavenrc ]; then 39 | . /usr/local/etc/mavenrc 40 | fi 41 | 42 | if [ -f /etc/mavenrc ]; then 43 | . /etc/mavenrc 44 | fi 45 | 46 | if [ -f "$HOME/.mavenrc" ]; then 47 | . "$HOME/.mavenrc" 48 | fi 49 | 50 | fi 51 | 52 | # OS specific support. $var _must_ be set to either true or false. 53 | cygwin=false 54 | darwin=false 55 | mingw=false 56 | case "$(uname)" in 57 | CYGWIN*) cygwin=true ;; 58 | MINGW*) mingw=true ;; 59 | Darwin*) 60 | darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | JAVA_HOME="$(/usr/libexec/java_home)" 66 | export JAVA_HOME 67 | else 68 | JAVA_HOME="/Library/Java/Home" 69 | export JAVA_HOME 70 | fi 71 | fi 72 | ;; 73 | esac 74 | 75 | if [ -z "$JAVA_HOME" ]; then 76 | if [ -r /etc/gentoo-release ]; then 77 | JAVA_HOME=$(java-config --jre-home) 78 | fi 79 | fi 80 | 81 | # For Cygwin, ensure paths are in UNIX format before anything is touched 82 | if $cygwin; then 83 | [ -n "$JAVA_HOME" ] \ 84 | && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 85 | [ -n "$CLASSPATH" ] \ 86 | && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 87 | fi 88 | 89 | # For Mingw, ensure paths are in UNIX format before anything is touched 90 | if $mingw; then 91 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ 92 | && JAVA_HOME="$( 93 | cd "$JAVA_HOME" || ( 94 | echo "cannot cd into $JAVA_HOME." >&2 95 | exit 1 96 | ) 97 | pwd 98 | )" 99 | fi 100 | 101 | if [ -z "$JAVA_HOME" ]; then 102 | javaExecutable="$(which javac)" 103 | if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then 104 | # readlink(1) is not available as standard on Solaris 10. 105 | readLink=$(which readlink) 106 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then 107 | if $darwin; then 108 | javaHome="$(dirname "$javaExecutable")" 109 | javaExecutable="$(cd "$javaHome" && pwd -P)/javac" 110 | else 111 | javaExecutable="$(readlink -f "$javaExecutable")" 112 | fi 113 | javaHome="$(dirname "$javaExecutable")" 114 | javaHome=$(expr "$javaHome" : '\(.*\)/bin') 115 | JAVA_HOME="$javaHome" 116 | export JAVA_HOME 117 | fi 118 | fi 119 | fi 120 | 121 | if [ -z "$JAVACMD" ]; then 122 | if [ -n "$JAVA_HOME" ]; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ]; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD="$JAVA_HOME/jre/sh/java" 126 | else 127 | JAVACMD="$JAVA_HOME/bin/java" 128 | fi 129 | else 130 | JAVACMD="$( 131 | \unset -f command 2>/dev/null 132 | \command -v java 133 | )" 134 | fi 135 | fi 136 | 137 | if [ ! -x "$JAVACMD" ]; then 138 | echo "Error: JAVA_HOME is not defined correctly." >&2 139 | echo " We cannot execute $JAVACMD" >&2 140 | exit 1 141 | fi 142 | 143 | if [ -z "$JAVA_HOME" ]; then 144 | echo "Warning: JAVA_HOME environment variable is not set." >&2 145 | fi 146 | 147 | # traverses directory structure from process work directory to filesystem root 148 | # first directory with .mvn subdirectory is considered project base directory 149 | find_maven_basedir() { 150 | if [ -z "$1" ]; then 151 | echo "Path not specified to find_maven_basedir" >&2 152 | return 1 153 | fi 154 | 155 | basedir="$1" 156 | wdir="$1" 157 | while [ "$wdir" != '/' ]; do 158 | if [ -d "$wdir"/.mvn ]; then 159 | basedir=$wdir 160 | break 161 | fi 162 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 163 | if [ -d "${wdir}" ]; then 164 | wdir=$( 165 | cd "$wdir/.." || exit 1 166 | pwd 167 | ) 168 | fi 169 | # end of workaround 170 | done 171 | printf '%s' "$( 172 | cd "$basedir" || exit 1 173 | pwd 174 | )" 175 | } 176 | 177 | # concatenates all lines of a file 178 | concat_lines() { 179 | if [ -f "$1" ]; then 180 | # Remove \r in case we run on Windows within Git Bash 181 | # and check out the repository with auto CRLF management 182 | # enabled. Otherwise, we may read lines that are delimited with 183 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word 184 | # splitting rules. 185 | tr -s '\r\n' ' ' <"$1" 186 | fi 187 | } 188 | 189 | log() { 190 | if [ "$MVNW_VERBOSE" = true ]; then 191 | printf '%s\n' "$1" 192 | fi 193 | } 194 | 195 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")") 196 | if [ -z "$BASE_DIR" ]; then 197 | exit 1 198 | fi 199 | 200 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 201 | export MAVEN_PROJECTBASEDIR 202 | log "$MAVEN_PROJECTBASEDIR" 203 | 204 | ########################################################################################## 205 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 206 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 207 | ########################################################################################## 208 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" 209 | if [ -r "$wrapperJarPath" ]; then 210 | log "Found $wrapperJarPath" 211 | else 212 | log "Couldn't find $wrapperJarPath, downloading it ..." 213 | 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 216 | else 217 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 218 | fi 219 | while IFS="=" read -r key value; do 220 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) 221 | safeValue=$(echo "$value" | tr -d '\r') 222 | case "$key" in wrapperUrl) 223 | wrapperUrl="$safeValue" 224 | break 225 | ;; 226 | esac 227 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 228 | log "Downloading from: $wrapperUrl" 229 | 230 | if $cygwin; then 231 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 232 | fi 233 | 234 | if command -v wget >/dev/null; then 235 | log "Found wget ... using wget" 236 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" 237 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 238 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 239 | else 240 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | fi 242 | elif command -v curl >/dev/null; then 243 | log "Found curl ... using curl" 244 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" 245 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 246 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 247 | else 248 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 249 | fi 250 | else 251 | log "Falling back to using Java to download" 252 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" 253 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" 254 | # For Cygwin, switch paths to Windows format before running javac 255 | if $cygwin; then 256 | javaSource=$(cygpath --path --windows "$javaSource") 257 | javaClass=$(cygpath --path --windows "$javaClass") 258 | fi 259 | if [ -e "$javaSource" ]; then 260 | if [ ! -e "$javaClass" ]; then 261 | log " - Compiling MavenWrapperDownloader.java ..." 262 | ("$JAVA_HOME/bin/javac" "$javaSource") 263 | fi 264 | if [ -e "$javaClass" ]; then 265 | log " - Running MavenWrapperDownloader.java ..." 266 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" 267 | fi 268 | fi 269 | fi 270 | fi 271 | ########################################################################################## 272 | # End of extension 273 | ########################################################################################## 274 | 275 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file 276 | wrapperSha256Sum="" 277 | while IFS="=" read -r key value; do 278 | case "$key" in wrapperSha256Sum) 279 | wrapperSha256Sum=$value 280 | break 281 | ;; 282 | esac 283 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 284 | if [ -n "$wrapperSha256Sum" ]; then 285 | wrapperSha256Result=false 286 | if command -v sha256sum >/dev/null; then 287 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then 288 | wrapperSha256Result=true 289 | fi 290 | elif command -v shasum >/dev/null; then 291 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then 292 | wrapperSha256Result=true 293 | fi 294 | else 295 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 296 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 297 | exit 1 298 | fi 299 | if [ $wrapperSha256Result = false ]; then 300 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 301 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 302 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 303 | exit 1 304 | fi 305 | fi 306 | 307 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 308 | 309 | # For Cygwin, switch paths to Windows format before running java 310 | if $cygwin; then 311 | [ -n "$JAVA_HOME" ] \ 312 | && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 313 | [ -n "$CLASSPATH" ] \ 314 | && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 315 | [ -n "$MAVEN_PROJECTBASEDIR" ] \ 316 | && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 317 | fi 318 | 319 | # Provide a "standardized" way to retrieve the CLI args that will 320 | # work with both Windows and non-Windows executions. 321 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" 322 | export MAVEN_CMD_LINE_ARGS 323 | 324 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 325 | 326 | # shellcheck disable=SC2086 # safe args 327 | exec "$JAVACMD" \ 328 | $MAVEN_OPTS \ 329 | $MAVEN_DEBUG_OPTS \ 330 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 331 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 332 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 333 | -------------------------------------------------------------------------------- /start/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Apache Maven Wrapper startup batch script, version 3.3.2 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 30 | @REM e.g. to debug Maven itself, use 31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 33 | @REM ---------------------------------------------------------------------------- 34 | 35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 36 | @echo off 37 | @REM set title of command window 38 | title %0 39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 41 | 42 | @REM set %HOME% to equivalent of $HOME 43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 44 | 45 | @REM Execute a user defined script before this one 46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 50 | :skipRcPre 51 | 52 | @setlocal 53 | 54 | set ERROR_CODE=0 55 | 56 | @REM To isolate internal variables from possible post scripts, we use another setlocal 57 | @setlocal 58 | 59 | @REM ==== START VALIDATION ==== 60 | if not "%JAVA_HOME%" == "" goto OkJHome 61 | 62 | echo. >&2 63 | echo Error: JAVA_HOME not found in your environment. >&2 64 | echo Please set the JAVA_HOME variable in your environment to match the >&2 65 | echo location of your Java installation. >&2 66 | echo. >&2 67 | goto error 68 | 69 | :OkJHome 70 | if exist "%JAVA_HOME%\bin\java.exe" goto init 71 | 72 | echo. >&2 73 | echo Error: JAVA_HOME is set to an invalid directory. >&2 74 | echo JAVA_HOME = "%JAVA_HOME%" >&2 75 | echo Please set the JAVA_HOME variable in your environment to match the >&2 76 | echo location of your Java installation. >&2 77 | echo. >&2 78 | goto error 79 | 80 | @REM ==== END VALIDATION ==== 81 | 82 | :init 83 | 84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 85 | @REM Fallback to current working directory if not found. 86 | 87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 89 | 90 | set EXEC_DIR=%CD% 91 | set WDIR=%EXEC_DIR% 92 | :findBaseDir 93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 94 | cd .. 95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 96 | set WDIR=%CD% 97 | goto findBaseDir 98 | 99 | :baseDirFound 100 | set MAVEN_PROJECTBASEDIR=%WDIR% 101 | cd "%EXEC_DIR%" 102 | goto endDetectBaseDir 103 | 104 | :baseDirNotFound 105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 106 | cd "%EXEC_DIR%" 107 | 108 | :endDetectBaseDir 109 | 110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 111 | 112 | @setlocal EnableExtensions EnableDelayedExpansion 113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 115 | 116 | :endReadAdditionalConfig 117 | 118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 123 | 124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | if "%MVNW_VERBOSE%" == "true" ( 132 | echo Found %WRAPPER_JAR% 133 | ) 134 | ) else ( 135 | if not "%MVNW_REPOURL%" == "" ( 136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 137 | ) 138 | if "%MVNW_VERBOSE%" == "true" ( 139 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 140 | echo Downloading from: %WRAPPER_URL% 141 | ) 142 | 143 | powershell -Command "&{"^ 144 | "$webclient = new-object System.Net.WebClient;"^ 145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 147 | "}"^ 148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ 149 | "}" 150 | if "%MVNW_VERBOSE%" == "true" ( 151 | echo Finished downloading %WRAPPER_JAR% 152 | ) 153 | ) 154 | @REM End of extension 155 | 156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file 157 | SET WRAPPER_SHA_256_SUM="" 158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B 160 | ) 161 | IF NOT %WRAPPER_SHA_256_SUM%=="" ( 162 | powershell -Command "&{"^ 163 | "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ 164 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ 165 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ 166 | " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ 167 | " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ 168 | " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ 169 | " exit 1;"^ 170 | "}"^ 171 | "}" 172 | if ERRORLEVEL 1 goto error 173 | ) 174 | 175 | @REM Provide a "standardized" way to retrieve the CLI args that will 176 | @REM work with both Windows and non-Windows executions. 177 | set MAVEN_CMD_LINE_ARGS=%* 178 | 179 | %MAVEN_JAVA_EXE% ^ 180 | %JVM_CONFIG_MAVEN_PROPS% ^ 181 | %MAVEN_OPTS% ^ 182 | %MAVEN_DEBUG_OPTS% ^ 183 | -classpath %WRAPPER_JAR% ^ 184 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 185 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 186 | if ERRORLEVEL 1 goto error 187 | goto end 188 | 189 | :error 190 | set ERROR_CODE=1 191 | 192 | :end 193 | @endlocal & set ERROR_CODE=%ERROR_CODE% 194 | 195 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 196 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 197 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 198 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 199 | :skipRcPost 200 | 201 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 202 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 203 | 204 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 205 | 206 | cmd /C exit /B %ERROR_CODE% 207 | -------------------------------------------------------------------------------- /start/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.openliberty.guides 6 | guide-microprofile-openapi 7 | 1.0-SNAPSHOT 8 | war 9 | 10 | 11 | UTF-8 12 | UTF-8 13 | 11 14 | 11 15 | 16 | 9080 17 | 9443 18 | 19 | 20 | 21 | 22 | 23 | jakarta.platform 24 | jakarta.jakartaee-api 25 | 10.0.0 26 | provided 27 | 28 | 29 | org.eclipse.microprofile 30 | microprofile 31 | 7.0 32 | pom 33 | provided 34 | 35 | 36 | 37 | org.junit.jupiter 38 | junit-jupiter 39 | 5.13.2 40 | test 41 | 42 | 43 | org.jboss.resteasy 44 | resteasy-client 45 | 6.2.12.Final 46 | test 47 | 48 | 49 | org.jboss.resteasy 50 | resteasy-json-binding-provider 51 | 6.2.12.Final 52 | test 53 | 54 | 55 | org.glassfish 56 | jakarta.json 57 | 2.0.1 58 | test 59 | 60 | 61 | 62 | org.apache.commons 63 | commons-lang3 64 | 3.17.0 65 | 66 | 67 | 68 | 69 | ${project.artifactId} 70 | 71 | 72 | org.apache.maven.plugins 73 | maven-war-plugin 74 | 3.4.0 75 | 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-surefire-plugin 80 | 3.5.3 81 | 82 | 83 | io.openliberty.tools 84 | liberty-maven-plugin 85 | 3.11.4 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-failsafe-plugin 91 | 3.5.3 92 | 93 | 94 | ${liberty.var.http.port} 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/InventoryApplication.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides; 13 | 14 | // JAX-RS 15 | import jakarta.ws.rs.ApplicationPath; 16 | import jakarta.ws.rs.core.Application; 17 | 18 | @ApplicationPath("inventory") 19 | public class InventoryApplication extends Application { 20 | 21 | } 22 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/InventoryManager.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory; 13 | 14 | import java.util.List; 15 | import java.util.ArrayList; 16 | import java.util.Collections; 17 | import java.util.Properties; 18 | import jakarta.enterprise.context.ApplicationScoped; 19 | import io.openliberty.guides.inventory.model.InventoryList; 20 | import io.openliberty.guides.inventory.model.SystemData; 21 | 22 | @ApplicationScoped 23 | public class InventoryManager { 24 | 25 | private List systems = Collections.synchronizedList(new ArrayList<>()); 26 | private InventoryUtils invUtils = new InventoryUtils(); 27 | 28 | public Properties get(String hostname) { 29 | return invUtils.getProperties(hostname); 30 | } 31 | 32 | public void add(String hostname, Properties systemProps) { 33 | Properties props = new Properties(); 34 | props.setProperty("os.name", systemProps.getProperty("os.name")); 35 | props.setProperty("user.name", systemProps.getProperty("user.name")); 36 | 37 | SystemData system = new SystemData(hostname, props); 38 | if (!systems.contains(system)) { 39 | systems.add(system); 40 | } 41 | } 42 | 43 | public InventoryList list() { 44 | return new InventoryList(systems); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/InventoryResource.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory; 13 | 14 | import java.util.Properties; 15 | import jakarta.enterprise.context.RequestScoped; 16 | import jakarta.inject.Inject; 17 | import jakarta.ws.rs.GET; 18 | import jakarta.ws.rs.Path; 19 | import jakarta.ws.rs.PathParam; 20 | import jakarta.ws.rs.Produces; 21 | import jakarta.ws.rs.core.MediaType; 22 | import jakarta.ws.rs.core.Response; 23 | 24 | import org.eclipse.microprofile.openapi.annotations.Operation; 25 | import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; 26 | import org.eclipse.microprofile.openapi.annotations.media.Content; 27 | import org.eclipse.microprofile.openapi.annotations.media.Schema; 28 | import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; 29 | import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; 30 | import org.eclipse.microprofile.openapi.annotations.responses.APIResponseSchema; 31 | import io.openliberty.guides.inventory.model.InventoryList; 32 | 33 | @RequestScoped 34 | @Path("/systems") 35 | public class InventoryResource { 36 | 37 | @Inject 38 | InventoryManager manager; 39 | 40 | @GET 41 | @Path("/{hostname}") 42 | @Produces(MediaType.APPLICATION_JSON) 43 | public Response getPropertiesForHost( 44 | @PathParam("hostname") String hostname) { 45 | // Get properties for host 46 | Properties props = manager.get(hostname); 47 | if (props == null) { 48 | return Response.status(Response.Status.NOT_FOUND) 49 | .entity("{ \"error\" : " 50 | + "\"Unknown hostname " + hostname 51 | + " or the resource may not be " 52 | + "running on the host machine\" }") 53 | .build(); 54 | } 55 | 56 | //Add to inventory to host 57 | manager.add(hostname, props); 58 | return Response.ok(props).build(); 59 | } 60 | 61 | @GET 62 | @Produces(MediaType.APPLICATION_JSON) 63 | public InventoryList listContents() { 64 | return manager.list(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/InventoryUtils.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2024 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory; 13 | 14 | import java.net.URL; 15 | import java.net.UnknownHostException; 16 | import java.net.MalformedURLException; 17 | import jakarta.ws.rs.ProcessingException; 18 | import java.util.Properties; 19 | import org.apache.commons.lang3.exception.ExceptionUtils; 20 | import org.eclipse.microprofile.rest.client.RestClientBuilder; 21 | import io.openliberty.guides.inventory.client.SystemClient; 22 | import io.openliberty.guides.inventory.client.UnknownUrlException; 23 | import io.openliberty.guides.inventory.client.UnknownUrlExceptionMapper; 24 | 25 | public class InventoryUtils { 26 | 27 | private final String SYSTEM_PORT = System.getProperty("http.port", "9080"); 28 | 29 | public Properties getProperties(String hostname) { 30 | try { 31 | String customUrlString = "http://" + hostname + ":" 32 | + SYSTEM_PORT + "/inventory"; 33 | URL customURL = new URL(customUrlString); 34 | SystemClient customRestClient = 35 | RestClientBuilder.newBuilder() 36 | .baseUrl(customURL) 37 | .register(UnknownUrlExceptionMapper.class) 38 | .build(SystemClient.class); 39 | return customRestClient.getProperties(); 40 | } catch (ProcessingException ex) { 41 | handleProcessingException(ex); 42 | } catch (UnknownUrlException ex) { 43 | System.err.println("The given URL is unreachable."); 44 | } catch (MalformedURLException ex) { 45 | System.err.println("The given URL is not formatted correctly: " 46 | + ex.getMessage()); 47 | } 48 | return null; 49 | } 50 | 51 | public void handleProcessingException(ProcessingException ex) { 52 | Throwable rootEx = ExceptionUtils.getRootCause(ex); 53 | if (rootEx != null && rootEx instanceof UnknownHostException) { 54 | System.err.println("The specified host is unknown: " + ex.getMessage()); 55 | } else { 56 | throw ex; 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/client/SystemClient.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.client; 13 | 14 | import java.util.Properties; 15 | import jakarta.ws.rs.ProcessingException; 16 | import jakarta.ws.rs.GET; 17 | import jakarta.ws.rs.Path; 18 | import jakarta.ws.rs.Produces; 19 | import jakarta.ws.rs.core.MediaType; 20 | import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; 21 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 22 | 23 | @RegisterRestClient 24 | @RegisterProvider(UnknownUrlExceptionMapper.class) 25 | @Path("/properties") 26 | public interface SystemClient { 27 | 28 | @GET 29 | @Produces(MediaType.APPLICATION_JSON) 30 | Properties getProperties() throws UnknownUrlException, ProcessingException; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/client/UnknownUrlException.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.client; 13 | 14 | public class UnknownUrlException extends Exception { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | public UnknownUrlException() { 19 | super(); 20 | } 21 | 22 | public UnknownUrlException(String message) { 23 | super(message); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/client/UnknownUrlExceptionMapper.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.client; 13 | 14 | import java.util.logging.Logger; 15 | import jakarta.ws.rs.core.MultivaluedMap; 16 | import jakarta.ws.rs.core.Response; 17 | import jakarta.ws.rs.ext.Provider; 18 | import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; 19 | 20 | @Provider 21 | public class UnknownUrlExceptionMapper 22 | implements ResponseExceptionMapper { 23 | 24 | Logger LOG = Logger.getLogger(UnknownUrlExceptionMapper.class.getName()); 25 | 26 | @Override 27 | public boolean handles(int status, MultivaluedMap headers) { 28 | LOG.info("status = " + status); 29 | return status == 404; 30 | } 31 | 32 | @Override 33 | public UnknownUrlException toThrowable(Response response) { 34 | return new UnknownUrlException(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/filter/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-openapi/b913ea17410d1cda3e4e70f3cee61b0ba99f734b/start/src/main/java/io/openliberty/guides/inventory/filter/.gitkeep -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/model/InventoryList.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.model; 13 | 14 | import java.util.List; 15 | 16 | import org.eclipse.microprofile.openapi.annotations.media.Schema; 17 | 18 | public class InventoryList { 19 | 20 | private List systems; 21 | 22 | public InventoryList(List systems) { 23 | this.systems = systems; 24 | } 25 | 26 | public List getSystems() { 27 | return systems; 28 | } 29 | 30 | public int getTotal() { 31 | return systems.size(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/inventory/model/SystemData.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.inventory.model; 13 | 14 | import java.util.Properties; 15 | import org.eclipse.microprofile.openapi.annotations.media.Schema; 16 | 17 | public class SystemData { 18 | 19 | private final String hostname; 20 | 21 | private final Properties properties; 22 | 23 | public SystemData(String hostname, Properties properties) { 24 | this.hostname = hostname; 25 | this.properties = properties; 26 | } 27 | 28 | public String getHostname() { 29 | return hostname; 30 | } 31 | 32 | public Properties getProperties() { 33 | return properties; 34 | } 35 | 36 | @Override 37 | public boolean equals(Object host) { 38 | if (host instanceof SystemData) { 39 | return hostname.equals(((SystemData) host).getHostname()); 40 | } 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /start/src/main/java/io/openliberty/guides/system/SystemResource.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.system; 13 | 14 | import java.util.Properties; 15 | 16 | import jakarta.enterprise.context.RequestScoped; 17 | import jakarta.ws.rs.GET; 18 | 19 | import jakarta.ws.rs.Path; 20 | import jakarta.ws.rs.Produces; 21 | import jakarta.ws.rs.core.MediaType; 22 | 23 | @RequestScoped 24 | @Path("/properties") 25 | public class SystemResource { 26 | 27 | @GET 28 | @Produces(MediaType.APPLICATION_JSON) 29 | public Properties getProperties() { 30 | return System.getProperties(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /start/src/main/liberty/config/server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jakartaee-10.0 5 | microprofile-7.0 6 | restfulWS 7 | jsonp 8 | jsonb 9 | cdi 10 | mpConfig 11 | mpRestClient 12 | mpOpenAPI 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /start/src/main/resources/META-INF/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-openapi/b913ea17410d1cda3e4e70f3cee61b0ba99f734b/start/src/main/resources/META-INF/.gitkeep -------------------------------------------------------------------------------- /start/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Liberty Project 6 | 7 | 8 | index.html 9 | 10 | -------------------------------------------------------------------------------- /start/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-openapi/b913ea17410d1cda3e4e70f3cee61b0ba99f734b/start/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /start/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 |

Welcome to your Open Liberty application

19 |

Open Liberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. Find out more at openliberty.io.

20 |

Check out the interactive UI made with Swagger UI

21 |
22 |

Eclipse MicroProfile

23 |

24 | The Eclipse MicroProfile project is an open community with the aim of optimizing enterprise Java for a microservices architecture. 25 | MicroProfile evolves with guidance from the community. 26 |

27 |

28 | If you want to share your thoughts, you can post straight to the 29 | MicroProfile Google group. 30 |

31 |

32 | For more information about the features used in this application, see the Open Liberty documentation: 33 |

43 |

44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /start/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | // tag::testClass[] 13 | package it.io.openliberty.guides.inventory; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | import static org.junit.jupiter.api.Assertions.assertTrue; 17 | 18 | import jakarta.json.JsonArray; 19 | import jakarta.json.JsonObject; 20 | import jakarta.ws.rs.client.Client; 21 | import jakarta.ws.rs.client.ClientBuilder; 22 | import jakarta.ws.rs.core.MediaType; 23 | import jakarta.ws.rs.core.Response; 24 | 25 | import org.junit.jupiter.api.AfterEach; 26 | import org.junit.jupiter.api.BeforeEach; 27 | import org.junit.jupiter.api.BeforeAll; 28 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 29 | import org.junit.jupiter.api.Order; 30 | import org.junit.jupiter.api.Test; 31 | import org.junit.jupiter.api.TestMethodOrder; 32 | 33 | @TestMethodOrder(OrderAnnotation.class) 34 | public class InventoryEndpointIT { 35 | 36 | private static String port; 37 | private static String baseUrl; 38 | 39 | private Client client; 40 | 41 | private final String INVENTORY_PROPERTIES = "inventory/properties"; 42 | private final String INVENTORY_SYSTEMS = "inventory/systems"; 43 | 44 | @BeforeAll 45 | public static void oneTimeSetup() { 46 | port = System.getProperty("http.port"); 47 | baseUrl = "http://localhost:" + port + "/"; 48 | } 49 | 50 | @BeforeEach 51 | public void setup() { 52 | client = ClientBuilder.newClient(); 53 | } 54 | 55 | @AfterEach 56 | public void teardown() { 57 | client.close(); 58 | } 59 | 60 | @Test 61 | @Order(1) 62 | public void testHostRegistration() { 63 | this.visitLocalhost(); 64 | 65 | Response response = this.getResponse(baseUrl + INVENTORY_SYSTEMS); 66 | this.assertResponse(baseUrl, response); 67 | 68 | JsonObject obj = response.readEntity(JsonObject.class); 69 | 70 | JsonArray systems = obj.getJsonArray("systems"); 71 | 72 | boolean localhostExists = false; 73 | for (int n = 0; n < systems.size(); n++) { 74 | localhostExists = systems.getJsonObject(n) 75 | .get("hostname").toString() 76 | .contains("localhost"); 77 | if (localhostExists) { 78 | break; 79 | } 80 | } 81 | assertTrue(localhostExists, "A host was registered, but it was not localhost"); 82 | 83 | response.close(); 84 | } 85 | 86 | @Test 87 | @Order(2) 88 | public void testSystemPropertiesMatch() { 89 | Response invResponse = this.getResponse(baseUrl + INVENTORY_SYSTEMS); 90 | Response sysResponse = this.getResponse(baseUrl + INVENTORY_PROPERTIES); 91 | 92 | this.assertResponse(baseUrl, invResponse); 93 | this.assertResponse(baseUrl, sysResponse); 94 | 95 | JsonObject jsonFromInventory = (JsonObject) 96 | invResponse.readEntity(JsonObject.class) 97 | .getJsonArray("systems") 98 | .getJsonObject(0) 99 | .get("properties"); 100 | 101 | JsonObject jsonFromSystem = sysResponse.readEntity(JsonObject.class); 102 | 103 | String osNameFromInventory = jsonFromInventory.getString("os.name"); 104 | String osNameFromSystem = jsonFromSystem.getString("os.name"); 105 | this.assertProperty("os.name", "localhost", 106 | osNameFromSystem, osNameFromInventory); 107 | 108 | String userNameFromInventory = jsonFromInventory.getString("user.name"); 109 | String userNameFromSystem = jsonFromSystem.getString("user.name"); 110 | this.assertProperty("user.name", "localhost", 111 | userNameFromSystem, userNameFromInventory); 112 | 113 | invResponse.close(); 114 | sysResponse.close(); 115 | } 116 | 117 | @Test 118 | @Order(3) 119 | public void testUnknownHost() { 120 | Response response = this.getResponse(baseUrl + INVENTORY_SYSTEMS); 121 | this.assertResponse(baseUrl, response); 122 | 123 | Response badResponse = client.target(baseUrl + INVENTORY_SYSTEMS + "/" 124 | + "badhostname") 125 | .request(MediaType.APPLICATION_JSON) 126 | .get(); 127 | 128 | assertEquals(404, badResponse.getStatus(), 129 | "BadResponse expected status: 404." 130 | + " Response code not as expected."); 131 | 132 | String stringObj = badResponse.readEntity(String.class); 133 | boolean isError = stringObj.contains("error"); 134 | assertTrue(isError, "badhostname is not a valid host" 135 | + "but it didn't raise an error"); 136 | 137 | response.close(); 138 | badResponse.close(); 139 | } 140 | 141 | /** 142 | *

143 | * Returns response information from the specified URL. 144 | *

145 | * 146 | * @param url 147 | * - target URL. 148 | * @return Response object with the response from the specified URL. 149 | */ 150 | private Response getResponse(String url) { 151 | return client.target(url).request().get(); 152 | } 153 | 154 | /** 155 | *

156 | * Asserts that the given URL has the correct response code of 200. 157 | *

158 | * 159 | * @param url 160 | * - target URL. 161 | * @param response 162 | * - response received from the target URL. 163 | */ 164 | private void assertResponse(String url, Response response) { 165 | assertEquals(200, response.getStatus(), "Incorrect response code from " + url); 166 | } 167 | 168 | /** 169 | * Asserts that the specified JVM system property is equivalent in both the 170 | * system and inventory services. 171 | * 172 | * @param propertyName 173 | * - name of the system property to check. 174 | * @param hostname 175 | * - name of JVM's host. 176 | * @param expected 177 | * - expected name. 178 | * @param actual 179 | * - actual name. 180 | */ 181 | private void assertProperty(String propertyName, String hostname, 182 | String expected, String actual) { 183 | assertEquals(expected, actual, "JVM system property [" + propertyName + "] " 184 | + "in the system service does not match the one stored in " 185 | + "the inventory service for " + hostname); 186 | } 187 | 188 | /** 189 | * Makes a simple GET request to inventory/localhost. 190 | */ 191 | private void visitLocalhost() { 192 | Response response = this.getResponse(baseUrl + INVENTORY_PROPERTIES); 193 | this.assertResponse(baseUrl, response); 194 | response.close(); 195 | 196 | Response targetResponse = client.target(baseUrl + INVENTORY_SYSTEMS 197 | + "/localhost") 198 | .request() 199 | .get(); 200 | targetResponse.close(); 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /start/src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package it.io.openliberty.guides.system; 13 | 14 | import static org.junit.jupiter.api.Assertions.assertEquals; 15 | 16 | import org.junit.jupiter.api.Test; 17 | 18 | import jakarta.json.JsonObject; 19 | 20 | import jakarta.ws.rs.client.Client; 21 | import jakarta.ws.rs.client.ClientBuilder; 22 | import jakarta.ws.rs.client.WebTarget; 23 | import jakarta.ws.rs.core.Response; 24 | 25 | public class SystemEndpointIT { 26 | 27 | @Test 28 | public void testGetProperties() { 29 | String port = System.getProperty("http.port"); 30 | String url = "http://localhost:" + port + "/"; 31 | 32 | Client client = ClientBuilder.newClient(); 33 | 34 | WebTarget target = client.target(url + "inventory/properties"); 35 | Response response = target.request().get(); 36 | 37 | assertEquals(200, response.getStatus(), "Incorrect response code from " + url); 38 | 39 | JsonObject obj = response.readEntity(JsonObject.class); 40 | 41 | assertEquals(System.getProperty("os.name"), 42 | obj.getString("os.name"), 43 | "The system property for the local and remote JVM should match"); 44 | 45 | response.close(); 46 | client.close(); 47 | } 48 | 49 | } 50 | --------------------------------------------------------------------------------