├── .github
└── dependabot.yml
├── .gitignore
├── .maven.xml
├── .travis.yml
├── LICENSE
├── README.md
├── nbactions.xml
├── openapi-examples
├── basic-example
│ ├── README.md
│ ├── nb-configuration.xml
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── microprofileext
│ │ │ └── openapi
│ │ │ └── example
│ │ │ ├── ApplicationConfig.java
│ │ │ ├── Gender.java
│ │ │ ├── Person.java
│ │ │ ├── PersonProducer.java
│ │ │ └── PersonService.java
│ │ ├── openliberty
│ │ └── config
│ │ │ └── server.xml
│ │ ├── resources
│ │ ├── examples
│ │ │ └── data.json
│ │ ├── project-defaults.yml
│ │ └── project-dev.yml
│ │ └── webapp
│ │ └── WEB-INF
│ │ └── beans.xml
├── helidon-basic-example
│ ├── README.md
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── microprofileext
│ │ │ └── openapi
│ │ │ └── helidon
│ │ │ └── basic
│ │ │ └── example
│ │ │ ├── GreetResource.java
│ │ │ ├── GreetingProvider.java
│ │ │ ├── internal
│ │ │ ├── SimpleAPIFilter.java
│ │ │ ├── SimpleAPIModelReader.java
│ │ │ └── package-info.java
│ │ │ └── package-info.java
│ │ └── resources
│ │ ├── META-INF
│ │ ├── beans.xml
│ │ └── microprofile-config.properties
│ │ └── logging.properties
├── helidon-features-example
│ ├── README.md
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── microprofileext
│ │ │ └── openapi
│ │ │ └── features
│ │ │ └── example
│ │ │ ├── GreetResource.java
│ │ │ ├── GreetingProvider.java
│ │ │ ├── MyApplication.java
│ │ │ ├── UiApplication.java
│ │ │ └── package-info.java
│ │ └── resources
│ │ ├── META-INF
│ │ ├── beans.xml
│ │ ├── microprofile-config.properties
│ │ └── openapi.yaml
│ │ └── logging.properties
└── pom.xml
├── openapi-ui
├── README.md
├── configured1.png
├── configured2.png
├── configured3.png
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── microprofileext
│ │ │ │ └── openapi
│ │ │ │ └── swaggerui
│ │ │ │ ├── OpenApiUiService.java
│ │ │ │ ├── RequestInfo.java
│ │ │ │ ├── StaticResourcesService.java
│ │ │ │ ├── Templates.java
│ │ │ │ └── WhiteLabel.java
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ ├── beans.xml
│ │ │ │ └── web-fragment.xml
│ │ └── webapp
│ │ │ └── templates
│ │ │ ├── logo.png
│ │ │ ├── style.css
│ │ │ └── template.html
│ └── test
│ │ └── java
│ │ └── org
│ │ └── microprofileext
│ │ └── openapi
│ │ └── swaggerui
│ │ └── RequestInfoTest.java
└── vanilla.png
└── pom.xml
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 | /swagger-ui/target/
25 | /openapi-example/target/
26 | /openapi-ui/target/
27 | /openapi-ui/nbproject/
28 | /openapi-examples/helidon-features-example/target/
29 | /openapi-examples/helidon-basic-example/target/
30 | /target/
31 | /openapi-examples/target/
32 |
--------------------------------------------------------------------------------
/.maven.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 | ossrh
7 | ${env.SONATYPE_USERNAME}
8 | ${env.SONATYPE_PASSWORD}
9 |
10 |
11 |
12 |
13 |
14 | ossrh
15 |
16 | true
17 |
18 |
19 | ${env.GPG_EXECUTABLE}
20 | ${env.GPG_PASSPHRASE}
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | before_deploy:
4 | - mvn help:evaluate -N -Dexpression=project.version|grep -v '\['
5 | - export project_version=$(mvn help:evaluate -N -Dexpression=project.version|grep -v '\[')
6 |
7 | ## export GPG details
8 | before_install:
9 | - echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import
10 | - echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust
11 |
12 | install:
13 | mvn --settings .maven.xml install -DskipTests=true -Dgpg.skip -Dmaven.javadoc.skip=true -B -V
14 |
15 | ## Build and release to maven central
16 | script:
17 | mvn clean deploy --settings .maven.xml -DskipTests=true -B -U -Prelease
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenApi Extensions
2 |
3 | [](https://app.travis-ci.com/github/microprofile-extensions/openapi-ext) [](https://github.com/microprofile-extensions/openapi-ext/blob/main/LICENSE)
4 | ___________
5 | Here you will find some extra tools for Open API
6 |
7 | * [OpenApi UI](https://github.com/microprofile-extensions/openapi-ext/blob/main/openapi-ui/README.md)
8 |
9 | ## Examples
10 |
11 | Also look at the [example application](https://github.com/microprofile-extensions/openapi-ext/blob/main/openapi-examples/basic-example/README.md) to see how this is used.
12 | [Helidon example](https://github.com/microprofile-extensions/openapi-ext/blob/main/openapi-examples/helidon-basic-example/README.md) demonstrate OpenApi usage with Helidon MicroProfile.
13 |
--------------------------------------------------------------------------------
/nbactions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CUSTOM-release
5 | release
6 |
7 | clean
8 | deploy
9 |
10 |
11 | release
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/README.md:
--------------------------------------------------------------------------------
1 | [Back to openapi-ext](https://github.com/microprofile-extensions/openapi-ext/blob/main/README.md)
2 |
3 | # Example Application
4 |
5 | This is a very basic example application to demonstrate the OpenApi extensions.
6 |
7 | ## Running the example.
8 |
9 | Using maven, you can start this application using Payara or OpenLiberty:
10 |
11 | ```
12 | mvn -Ppayara clean install
13 | ```
14 | or
15 | ```
16 | mvn -Popenliberty clean install
17 | ```
18 |
19 | You can then go to http://localhost:8080/openapi-example/api/openapi-ui/
20 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/nb-configuration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
16 | ide
17 |
18 |
19 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.microprofile-ext.examples
6 | openapi-examples
7 | 2.1.2-SNAPSHOT
8 |
9 |
10 | org.microprofile-ext.openapi-ext
11 | openapi-example
12 | war
13 |
14 | Microprofile OpenApi Extensions :: Example
15 | A example application to demonstrate the extension
16 |
17 |
18 | false
19 |
20 |
21 |
22 |
23 | ${project.groupId}
24 | openapi-ui
25 | ${project.version}
26 | runtime
27 |
28 |
29 |
30 |
31 | ${project.artifactId}
32 |
33 |
34 |
35 |
36 |
37 |
38 | payara
39 |
40 |
41 | payara
42 |
43 |
44 |
45 |
46 |
47 | 1.4.0
48 | 5.2022.3
49 | ${java.io.tmpdir}${file.separator}${project.artifactId}${file.separator}payara-micro
50 | ${basedir}${file.separator}src${file.separator}main${file.separator}payara-micro${file.separator}config
51 | ${payara-micro.installDir}${file.separator}logs
52 | ${payara-micro.logsDir}${file.separator}server.log
53 |
54 |
55 |
56 |
57 |
58 | fish.payara.extras
59 | payara-micro
60 | ${payara-micro.version}
61 | provided
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | fish.payara.extras
70 | payara-micro
71 | provided
72 |
73 |
74 |
75 |
76 |
77 |
78 | fish.payara.maven.plugins
79 | payara-micro-maven-plugin
80 | ${payara-micro.maven.version}
81 |
82 |
83 |
84 | fish.payara.extras
85 | payara-micro
86 | ${payara-micro.version}
87 |
88 | ${payara-micro.version}
89 |
90 |
91 |
92 |
95 |
96 |
97 |
101 |
102 |
103 |
104 | ${project.groupId}
105 | ${project.artifactId}
106 | ${project.version}
107 | ${project.packaging}
108 |
109 |
110 |
111 |
112 | false
113 | false
114 | true
115 |
116 |
117 |
118 | 1
119 | pre-integration-test
120 |
121 | start
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | openliberty
134 |
135 |
136 | openliberty
137 |
138 |
139 |
140 |
141 | org.microprofileext.config
142 | FINEST
143 | 22.0.0.10
144 | 8080
145 | 8443
146 | ${java.io.tmpdir}${file.separator}${project.artifactId}${file.separator}openliberty
147 | ${basedir}${file.separator}src${file.separator}main${file.separator}openliberty${file.separator}config
148 | ${openliberty.installDir}${file.separator}wlp${file.separator}usr${file.separator}servers${file.separator}defaultServer${file.separator}logs
149 | 3.0.M1
150 |
151 |
152 |
153 |
154 |
155 |
156 | org.codehaus.mojo
157 | build-helper-maven-plugin
158 | 3.0.0
159 |
160 |
161 | add-resource
162 | generate-resources
163 |
164 | add-resource
165 |
166 |
167 |
168 |
169 |
170 |
171 | ${openliberty.configDir}
172 | ${project.build.directory}
173 | true
174 |
175 | server.xml
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | net.wasdev.wlp.maven.plugins
189 | liberty-maven-plugin
190 | ${openliberty.maven.version}
191 |
192 |
193 |
194 | io.openliberty
195 | openliberty-runtime
196 | ${openliberty.version}
197 | zip
198 |
199 | ${project.build.directory}${file.separator}server.xml
200 |
201 |
202 |
203 |
204 | 1
205 | install
206 |
207 | install-server
208 | create-server
209 |
210 |
211 |
212 | ${project.build.directory}${file.separator}server.xml
213 | defaultServer
214 |
215 | ${openliberty.http.port}
216 | ${openliberty.https.port}
217 |
218 |
219 |
220 |
221 |
222 | 2
223 | install
224 |
225 | install-apps
226 |
227 |
228 |
229 | apps
230 | true
231 | project
232 | true
233 | ${project.build.directory}${file.separator}liberty${file.separator}wlp
234 | defaultServer
235 |
236 |
237 |
238 |
239 | 3
240 | install
241 |
242 | run-server
243 |
244 |
245 |
246 | ${project.build.directory}${file.separator}server.xml
247 | ${project.build.directory}${file.separator}liberty${file.separator}wlp
248 | defaultServer
249 |
250 | ${openliberty.http.port}
251 | ${openliberty.https.port}
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 | wildfly
267 |
268 |
269 | wildfly
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 | org.wildfly.plugins
278 | wildfly-maven-plugin
279 | 2.0.2.Final
280 |
281 | 19.0.0.Final
282 | standalone-microprofile.xml
283 |
284 | 1
285 |
286 |
287 |
288 |
289 |
290 | admin
291 | admin
292 |
293 | admin
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 | install
302 |
303 | run
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 | jdk11plus
315 |
316 | [11,)
317 |
318 |
319 | --add-modules java.se
320 |
321 |
322 |
323 |
324 |
325 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/java/org/microprofileext/openapi/example/ApplicationConfig.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.example;
2 |
3 | import jakarta.ws.rs.ApplicationPath;
4 | import jakarta.ws.rs.core.Application;
5 | import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
6 | import org.eclipse.microprofile.openapi.annotations.info.Contact;
7 | import org.eclipse.microprofile.openapi.annotations.info.Info;
8 | import org.eclipse.microprofile.openapi.annotations.servers.Server;
9 |
10 | /**
11 | * Activate JAX-RS.
12 | * All REST Endpoints available under /api
13 | *
14 | * @author Phillip Kruger
15 | */
16 | @ApplicationPath("/api")
17 | //@ApplicationPath("/")
18 | @OpenAPIDefinition(info = @Info(
19 | title = "Person service",
20 | version = "1.0.0",
21 | contact = @Contact(
22 | name = "Phillip Kruger",
23 | email = "phillip.kruger@phillip-kruger.com",
24 | url = "http://www.phillip-kruger.com")
25 | ),
26 | servers = {
27 | // @Server(url = "/",description = "localhost no context"),
28 | @Server(url = "/openapi-example",description = "localhost")
29 | }
30 | )
31 | public class ApplicationConfig extends Application {
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/java/org/microprofileext/openapi/example/Gender.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.example;
2 |
3 | /**
4 | * Gender Enum
5 | * @author Phillip Kruger (phillip.kruger@phillip-kruger.com)
6 | */
7 | public enum Gender {
8 | Male,Female
9 | }
10 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/java/org/microprofileext/openapi/example/Person.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.example;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | /**
8 | * Person POJO
9 | * @author Phillip Kruger (phillip.kruger@phillip-kruger.com)
10 | */
11 | @Data @AllArgsConstructor @NoArgsConstructor
12 | public class Person {
13 | private Integer id;
14 | private String firstName;
15 | private String lastName;
16 | private String email;
17 | private Gender gender;
18 | private String IPAddress;
19 | }
20 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/java/org/microprofileext/openapi/example/PersonProducer.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.example;
2 |
3 | import jakarta.enterprise.context.ApplicationScoped;
4 | import jakarta.enterprise.inject.Produces;
5 | import jakarta.json.Json;
6 | import jakarta.json.JsonArray;
7 | import jakarta.json.JsonObject;
8 | import jakarta.json.JsonReader;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.util.Map;
12 | import java.util.stream.Collectors;
13 |
14 | /**
15 | * Creating some test data
16 | *
17 | * @author Phillip Kruger (phillip.kruger@phillip-kruger.com)
18 | */
19 |
20 | @ApplicationScoped
21 | public class PersonProducer {
22 |
23 | @Produces
24 | public Map produceAllPeople() {
25 | return getJsonData().stream()
26 | .map(e -> toPerson((JsonObject) e))
27 | .collect(Collectors.toMap(Person::getId, p -> p));
28 | }
29 |
30 | private Person toPerson(JsonObject jsonObject) {
31 | Person p = new Person();
32 | p.setId(jsonObject.getInt("id"));
33 | p.setFirstName(jsonObject.getString("first_name"));
34 | p.setLastName(jsonObject.getString("last_name"));
35 | p.setEmail(jsonObject.getString("email"));
36 | p.setGender(Gender.valueOf(jsonObject.getString("gender")));
37 | p.setIPAddress(jsonObject.getString("ip_address"));
38 | return p;
39 | }
40 |
41 | private JsonArray getJsonData() {
42 | try (InputStream is = readSampleData()) {
43 | JsonReader reader = Json.createReader(is);
44 | return reader.readArray();
45 | } catch (IOException ex) {
46 | throw new RuntimeException(ex);
47 | }
48 | }
49 |
50 | private InputStream readSampleData() {
51 | ClassLoader classLoader = getClass().getClassLoader();
52 | return classLoader.getResourceAsStream("examples/data.json");
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/java/org/microprofileext/openapi/example/PersonService.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.example;
2 |
3 | import jakarta.enterprise.context.RequestScoped;
4 | import jakarta.inject.Inject;
5 | import jakarta.ws.rs.Consumes;
6 | import jakarta.ws.rs.GET;
7 | import jakarta.ws.rs.Path;
8 | import jakarta.ws.rs.PathParam;
9 | import jakarta.ws.rs.Produces;
10 | import jakarta.ws.rs.core.MediaType;
11 | import jakarta.ws.rs.core.Response;
12 | import java.util.Map;
13 | import lombok.extern.java.Log;
14 | import org.eclipse.microprofile.openapi.annotations.Operation;
15 | import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
16 | import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
17 | import org.eclipse.microprofile.openapi.annotations.tags.Tag;
18 |
19 | /**
20 | * Person Service. JAX-RS
21 | * @author Phillip Kruger
22 | */
23 | @Log
24 | @RequestScoped
25 | @Path("/")
26 | @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
27 | @Tag(name = "Person service",description = "Just some example")
28 | public class PersonService {
29 |
30 | @Inject
31 | private Map people;
32 |
33 | @GET
34 | @Path("/all")
35 | @Produces(MediaType.APPLICATION_JSON)
36 | @Operation(operationId = "all", description = "Getting all people")
37 | @APIResponse(responseCode = "200", description = "Successful, returning the map in JSON format")
38 | public Response getAll(){
39 |
40 | return Response.ok(people).build();
41 | }
42 |
43 | @GET
44 | @Path("/id/{id}")
45 | @Operation(operationId = "value", description = "Getting the person by id")
46 | @APIResponse(responseCode = "200", description = "Successful, returning the person")
47 | @Produces(MediaType.APPLICATION_JSON)
48 | public Response getPerson(@Parameter(name = "id", description = "The id for the person", required = true, allowEmptyValue = false, example = "1")
49 | @PathParam("id") Integer id) {
50 |
51 | if(people.containsKey(id)){
52 | Person p = people.get(id);
53 | return Response.ok(p).build();
54 | }else{
55 | return Response.noContent().build();
56 | }
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/openliberty/config/server.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | microProfile-5.0
7 |
8 |
9 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/resources/project-defaults.yml:
--------------------------------------------------------------------------------
1 | none:
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/resources/project-dev.yml:
--------------------------------------------------------------------------------
1 | thorntail:
2 | logging:
3 | loggers:
4 | org.microprofileext.openapi:
5 | level: FINEST
--------------------------------------------------------------------------------
/openapi-examples/basic-example/src/main/webapp/WEB-INF/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/README.md:
--------------------------------------------------------------------------------
1 | [Back to openapi-ext](https://github.com/microprofile-extensions/openapi-ext/blob/main/README.md)
2 |
3 | # Helidon Basic Application
4 |
5 | This is a very basic helidon application to demonstrate the OpenApi extensions.
6 |
7 | ## Requirement
8 |
9 | To build the example, you need JDK 11 and Maven 3.8.4.
10 |
11 |
12 | ## Running the example
13 |
14 | Using maven, you can start this application this way:
15 |
16 | ```
17 | mvn -Prun-example clean install
18 | ```
19 |
20 | You can then go to http://localhost:8080/openapi-ui/
21 |
22 | Press `ctrl+C` to stop the application.
23 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.microprofile-ext.examples
9 | openapi-examples
10 | 2.1.2-SNAPSHOT
11 |
12 |
13 | openapi-helidon-se-example
14 | jar
15 |
16 | Microprofile OpenApi Extensions :: Helidon Basic Example
17 | Simple example using Helidon MP
18 |
19 |
20 | io.helidon.microprofile.cdi.Main
21 | 11
22 | 11
23 |
24 |
25 |
26 |
27 | io.helidon.applications
28 | helidon-mp
29 | ${helidon.version}
30 | pom
31 |
32 |
33 | org.microprofile-ext.openapi-ext
34 | openapi-ui
35 | ${project.version}
36 |
37 |
38 | com.fasterxml.jackson.core
39 | jackson-databind
40 | ${jackson.databind.version}
41 |
42 |
43 | io.helidon.microprofile.openapi
44 | helidon-microprofile-openapi
45 | ${helidon.version}
46 |
47 |
48 | org.junit.jupiter
49 | junit-jupiter-api
50 | ${lib.junit.version}
51 | test
52 |
53 |
54 |
55 |
56 | ${project.artifactId}
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-dependency-plugin
61 | ${dependency.plugin.version}
62 |
63 |
64 | copy-libs
65 | prepare-package
66 |
67 | copy-dependencies
68 |
69 |
70 | ${project.build.directory}/libs
71 | false
72 | false
73 | true
74 | true
75 | runtime
76 | test
77 |
78 |
79 |
80 |
81 |
82 | org.jboss.jandex
83 | jandex-maven-plugin
84 | ${jandex.plugin.version}
85 |
86 |
87 | make-index
88 |
89 | jandex
90 |
91 | process-classes
92 |
93 |
94 |
95 |
96 | io.helidon.build-tools
97 | helidon-maven-plugin
98 | ${helidon.plugin.version}
99 |
100 |
101 | io.helidon.licensing
102 | helidon-licensing
103 | ${helidon.version}
104 |
105 |
106 |
107 |
108 | third-party-license-report
109 |
110 | report
111 |
112 |
113 |
114 |
115 |
116 | org.apache.maven.plugins
117 | maven-jar-plugin
118 | ${jar.plugin.version}
119 |
120 |
121 |
122 | true
123 | libs
124 |
125 | ${mainClass}
126 | false
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | run-example
137 |
138 |
139 | run-example
140 |
141 |
142 |
143 |
144 |
145 | org.codehaus.mojo
146 | exec-maven-plugin
147 | ${maven.exec.plugin.version}
148 |
149 |
150 | run-greeting-application
151 | post-integration-test
152 |
153 | exec
154 |
155 |
156 | java
157 |
158 | -jar
159 | ${project.build.directory}${file.separator}${project.build.finalName}.jar
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/java/org/microprofileext/openapi/helidon/basic/example/GreetResource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.microprofileext.openapi.helidon.basic.example;
18 |
19 | import jakarta.enterprise.context.RequestScoped;
20 | import jakarta.inject.Inject;
21 | import jakarta.json.Json;
22 | import jakarta.json.JsonBuilderFactory;
23 | import jakarta.json.JsonObject;
24 | import jakarta.ws.rs.Consumes;
25 | import jakarta.ws.rs.GET;
26 | import jakarta.ws.rs.PUT;
27 | import jakarta.ws.rs.Path;
28 | import jakarta.ws.rs.PathParam;
29 | import jakarta.ws.rs.Produces;
30 | import jakarta.ws.rs.core.MediaType;
31 | import jakarta.ws.rs.core.Response;
32 | import org.eclipse.microprofile.openapi.annotations.Operation;
33 | import org.eclipse.microprofile.openapi.annotations.media.Content;
34 | import org.eclipse.microprofile.openapi.annotations.media.ExampleObject;
35 | import org.eclipse.microprofile.openapi.annotations.media.Schema;
36 | import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
37 | import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
38 | import org.microprofileext.openapi.helidon.basic.example.internal.SimpleAPIModelReader;
39 |
40 | import java.util.Collections;
41 |
42 | /**
43 | * A simple JAX-RS resource with OpenAPI annotations to greet you. Examples:
44 | *
45 | * Get default greeting message:
46 | * curl -X GET http://localhost:8080/greet
47 | *
48 | * Get greeting message for Joe:
49 | * curl -X GET http://localhost:8080/greet/Joe
50 | *
51 | * Change greeting
52 | * curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Howdy"}' http://localhost:8080/greet/greeting
53 | *
54 | * Get OpenAPI document for the endpoints
55 | * curl -X GET http://localhost:8080/openapi
56 | *
57 | * Note that the output will include not only the annotated endpoints from this
58 | * class but also an endpoint added by the
59 | * {@link SimpleAPIModelReader}.
60 | *
61 | * The message is returned as a JSON object.
62 | */
63 | @Path("/greet")
64 | @RequestScoped
65 | public class GreetResource {
66 |
67 | private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap());
68 |
69 | /**
70 | * The greeting message provider.
71 | */
72 | private final GreetingProvider greetingProvider;
73 |
74 | /**
75 | * Using constructor injection to get a configuration property.
76 | * By default this gets the value from META-INF/microprofile-config
77 | *
78 | * @param greetingConfig the configured greeting message
79 | */
80 | @Inject
81 | public GreetResource(GreetingProvider greetingConfig) {
82 | this.greetingProvider = greetingConfig;
83 | }
84 |
85 | /**
86 | * Return a worldly greeting message.
87 | *
88 | * @return {@link JsonObject}
89 | */
90 | @GET
91 | @Operation(summary = "Returns a generic greeting",
92 | description = "Greets the user generically")
93 | @APIResponse(description = "Simple JSON containing the greeting",
94 | content = @Content(mediaType = "application/json",
95 | schema = @Schema(implementation = GreetingMessage.class)))
96 | @Produces(MediaType.APPLICATION_JSON)
97 | public JsonObject getDefaultMessage() {
98 | return createResponse("World");
99 | }
100 |
101 | /**
102 | * Return a greeting message using the name that was provided.
103 | *
104 | * @param name the name to greet
105 | * @return {@link JsonObject}
106 | */
107 | @Path("/{name}")
108 | @GET
109 | @Operation(summary = "Returns a personalized greeting")
110 | @APIResponse(description = "Simple JSON containing the greeting",
111 | content = @Content(mediaType = "application/json",
112 | schema = @Schema(implementation = GreetingMessage.class)))
113 | @Produces(MediaType.APPLICATION_JSON)
114 | public JsonObject getMessage(@PathParam("name") String name) {
115 | return createResponse(name);
116 | }
117 |
118 | /**
119 | * Set the greeting to use in future messages.
120 | *
121 | * @param jsonObject JSON containing the new greeting
122 | * @return {@link Response}
123 | */
124 | @Path("/greeting")
125 | @PUT
126 | @Operation(summary = "Set the greeting prefix",
127 | description = "Permits the client to set the prefix part of the greeting (\"Hello\")")
128 | @RequestBody(
129 | name = "greeting",
130 | description = "Conveys the new greeting prefix to use in building greetings",
131 | content = @Content(
132 | mediaType = "application/json",
133 | schema = @Schema(implementation = GreetingMessage.class),
134 | examples = @ExampleObject(
135 | name = "greeting",
136 | summary = "Example greeting message to update",
137 | value = "New greeting message")))
138 | @Consumes(MediaType.APPLICATION_JSON)
139 | @Produces(MediaType.APPLICATION_JSON)
140 | public Response updateGreeting(JsonObject jsonObject) {
141 |
142 | if (!jsonObject.containsKey("greeting")) {
143 | JsonObject entity = JSON.createObjectBuilder()
144 | .add("error", "No greeting provided")
145 | .build();
146 | return Response.status(Response.Status.BAD_REQUEST).entity(entity).build();
147 | }
148 |
149 | String newGreeting = jsonObject.getString("greeting");
150 |
151 | greetingProvider.setMessage(newGreeting);
152 | return Response.status(Response.Status.NO_CONTENT).build();
153 | }
154 |
155 | private JsonObject createResponse(String who) {
156 | String msg = String.format("%s %s!", greetingProvider.getMessage(), who);
157 |
158 | return JSON.createObjectBuilder()
159 | .add("message", msg)
160 | .build();
161 | }
162 |
163 | /**
164 | * POJO defining the greeting message content exchanged with clients.
165 | */
166 | public static class GreetingMessage {
167 |
168 | private String message;
169 |
170 | /**
171 | * Gets the message value.
172 | *
173 | * @return message value
174 | */
175 | public String getMessage() {
176 | return message;
177 | }
178 |
179 | /**
180 | * Sets the message value.
181 | *
182 | * @param message message value to set
183 | */
184 | public void setMessage(String message) {
185 | this.message = message;
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/java/org/microprofileext/openapi/helidon/basic/example/GreetingProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.microprofileext.openapi.helidon.basic.example;
17 |
18 | import jakarta.enterprise.context.ApplicationScoped;
19 | import jakarta.inject.Inject;
20 | import org.eclipse.microprofile.config.inject.ConfigProperty;
21 |
22 | import java.util.concurrent.atomic.AtomicReference;
23 |
24 | /**
25 | * Provider for greeting message.
26 | */
27 | @ApplicationScoped
28 | public class GreetingProvider {
29 | private final AtomicReference message = new AtomicReference<>();
30 |
31 | /**
32 | * Create a new greeting provider, reading the message from configuration.
33 | *
34 | * @param message greeting to use
35 | */
36 | @Inject
37 | public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {
38 | this.message.set(message);
39 | }
40 |
41 | String getMessage() {
42 | return message.get();
43 | }
44 |
45 | void setMessage(String message) {
46 | this.message.set(message);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/java/org/microprofileext/openapi/helidon/basic/example/internal/SimpleAPIFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.microprofileext.openapi.helidon.basic.example.internal;
17 |
18 | import org.eclipse.microprofile.openapi.OASFilter;
19 | import org.eclipse.microprofile.openapi.models.Operation;
20 | import org.eclipse.microprofile.openapi.models.PathItem;
21 |
22 | import java.util.Map;
23 |
24 | /**
25 | * Example OpenAPI filter which hides a single endpoint from the OpenAPI document.
26 | */
27 | public class SimpleAPIFilter implements OASFilter {
28 |
29 | @Override
30 | public PathItem filterPathItem(PathItem pathItem) {
31 | for (Map.Entry methodOp
32 | : pathItem.getOperations().entrySet()) {
33 | if (SimpleAPIModelReader.DOOMED_OPERATION_ID
34 | .equals(methodOp.getValue().getOperationId())) {
35 | return null;
36 | }
37 | }
38 | return OASFilter.super.filterPathItem(pathItem);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/java/org/microprofileext/openapi/helidon/basic/example/internal/SimpleAPIModelReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.microprofileext.openapi.helidon.basic.example.internal;
17 |
18 | import org.eclipse.microprofile.openapi.OASFactory;
19 | import org.eclipse.microprofile.openapi.OASModelReader;
20 | import org.eclipse.microprofile.openapi.models.OpenAPI;
21 | import org.eclipse.microprofile.openapi.models.PathItem;
22 | import org.eclipse.microprofile.openapi.models.Paths;
23 |
24 | /**
25 | * Defines two paths using the OpenAPI model reader mechanism, one that should
26 | * be suppressed by the filter class and one that should appear in the published
27 | * OpenAPI document.
28 | */
29 | public class SimpleAPIModelReader implements OASModelReader {
30 |
31 | /**
32 | * Path for the example endpoint added by this model reader that should be visible.
33 | */
34 | public static final String MODEL_READER_PATH = "/test/newpath";
35 |
36 | /**
37 | * Path for an endpoint that the filter should hide.
38 | */
39 | public static final String DOOMED_PATH = "/test/doomed";
40 |
41 | /**
42 | * ID for an endpoint that the filter should hide.
43 | */
44 | public static final String DOOMED_OPERATION_ID = "doomedPath";
45 |
46 | /**
47 | * Summary text for the endpoint.
48 | */
49 | public static final String SUMMARY = "A sample test endpoint from ModelReader";
50 |
51 | @Override
52 | public OpenAPI buildModel() {
53 | /*
54 | * Add two path items, one of which we expect to be removed by
55 | * the filter and a very simple one that will appear in the
56 | * published OpenAPI document.
57 | */
58 | PathItem newPathItem = OASFactory.createPathItem()
59 | .GET(OASFactory.createOperation()
60 | .operationId("newPath")
61 | .summary(SUMMARY));
62 | PathItem doomedPathItem = OASFactory.createPathItem()
63 | .GET(OASFactory.createOperation()
64 | .operationId(DOOMED_OPERATION_ID)
65 | .summary("This should become invisible"));
66 | OpenAPI openAPI = OASFactory.createOpenAPI();
67 | Paths paths = OASFactory.createPaths()
68 | .addPathItem(MODEL_READER_PATH, newPathItem)
69 | .addPathItem(DOOMED_PATH, doomedPathItem);
70 | openAPI.paths(paths);
71 |
72 | return openAPI;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/java/org/microprofileext/openapi/helidon/basic/example/internal/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | /**
18 | * Internal classes supporting Helidon MP OpenAPI.
19 | */
20 | package org.microprofileext.openapi.helidon.basic.example.internal;
21 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/java/org/microprofileext/openapi/helidon/basic/example/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | /**
18 | * Helidon MicroProfile OpenAPI basic example.
19 | */
20 | package org.microprofileext.openapi.helidon.basic.example;
21 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/resources/META-INF/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
26 |
27 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/resources/META-INF/microprofile-config.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | # Application properties. This is the default greeting
18 | app.greeting=Hello
19 |
20 | # Microprofile server properties
21 | server.port=8080
22 | server.host=0.0.0.0
23 |
24 | mp.openapi.filter=org.microprofileext.openapi.helidon.basic.example.internal.SimpleAPIFilter
25 | mp.openapi.model.reader=org.microprofileext.openapi.helidon.basic.example.internal.SimpleAPIModelReader
26 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-basic-example/src/main/resources/logging.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2019, 2021 Oracle and/or its affiliates.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | # Example Logging Configuration File
18 | # For more information see $JAVA_HOME/jre/lib/logging.properties
19 |
20 | # Send messages to the console
21 | handlers=io.helidon.common.HelidonConsoleHandler
22 |
23 | # HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
24 | java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
25 |
26 | # Global logging level. Can be overridden by specific loggers
27 | .level=INFO
28 |
29 | # Component specific log levels
30 | #io.helidon.webserver.level=INFO
31 | #io.helidon.config.level=INFO
32 | #io.helidon.security.level=INFO
33 | #io.helidon.microprofile.level=INFO
34 | #io.helidon.common.level=INFO
35 | #io.netty.level=INFO
36 | #org.glassfish.jersey.level=INFO
37 | #org.jboss.weld=INFO
38 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/README.md:
--------------------------------------------------------------------------------
1 | [Back to openapi-ext](https://github.com/microprofile-extensions/openapi-ext/blob/main/README.md)
2 |
3 | # Helidon Features Application
4 |
5 | This is a basic helidon application to demonstrate several features of the OpenApi extensions with Helidon.
6 |
7 | ## Requirement
8 |
9 | To build the example, you need JDK 11 and Maven 3.8.4.
10 |
11 | ## Presentation
12 |
13 | Based on Helidon MP quickstart application, this example uses Openapi UI extension features. It exposes the greeting
14 | application at `/myapp/greet`. The user interface is accessible at `/myopenapi/openapi-ui`. From
15 | `microprofile-config.properties`, the OpenApi document endpoint is modified by `openapi.web-context` property for Helidon
16 | and `openapi.ui.yamlUrl` for OpenApi, so they point at each other.
17 |
18 | ## Running the example
19 |
20 | Using maven, you can start this application this way:
21 |
22 | ```
23 | mvn -Prun-example clean install
24 | ```
25 |
26 | You can then go to http://localhost:8080/myopenapi/openapi-ui/
27 |
28 | Press `ctrl+C` to stop the application.
29 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.microprofile-ext.examples
9 | openapi-examples
10 | 2.1.2-SNAPSHOT
11 |
12 |
13 | openapi-helidon-features-example
14 | jar
15 |
16 | Microprofile OpenApi Extensions :: Features Example
17 | Simple example using Openapi features
18 |
19 |
20 | io.helidon.microprofile.cdi.Main
21 | 11
22 | 11
23 |
24 |
25 |
26 |
27 | io.helidon.applications
28 | helidon-mp
29 | ${helidon.version}
30 | pom
31 |
32 |
33 | org.microprofile-ext.openapi-ext
34 | openapi-ui
35 | ${project.version}
36 |
37 |
38 | io.helidon.microprofile.openapi
39 | helidon-microprofile-openapi
40 | ${helidon.version}
41 |
42 |
43 | org.junit.jupiter
44 | junit-jupiter-api
45 | ${lib.junit.version}
46 | test
47 |
48 |
49 | com.fasterxml.jackson.core
50 | jackson-databind
51 | ${jackson.databind.version}
52 |
53 |
54 |
55 |
56 | ${project.artifactId}
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-dependency-plugin
61 | ${dependency.plugin.version}
62 |
63 |
64 | copy-libs
65 | prepare-package
66 |
67 | copy-dependencies
68 |
69 |
70 | ${project.build.directory}/libs
71 | false
72 | false
73 | true
74 | true
75 | runtime
76 | test
77 |
78 |
79 |
80 |
81 |
82 | org.jboss.jandex
83 | jandex-maven-plugin
84 | ${jandex.plugin.version}
85 |
86 |
87 | make-index
88 |
89 | jandex
90 |
91 | process-classes
92 |
93 |
94 |
95 |
96 | io.helidon.build-tools
97 | helidon-maven-plugin
98 | ${helidon.plugin.version}
99 |
100 |
101 | io.helidon.licensing
102 | helidon-licensing
103 | ${helidon.version}
104 |
105 |
106 |
107 |
108 | third-party-license-report
109 |
110 | report
111 |
112 |
113 |
114 |
115 |
116 | org.apache.maven.plugins
117 | maven-jar-plugin
118 | ${jar.plugin.version}
119 |
120 |
121 |
122 | true
123 | libs
124 |
125 | ${mainClass}
126 | false
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | run-example
137 |
138 |
139 | run-example
140 |
141 |
142 |
143 |
144 |
145 | org.codehaus.mojo
146 | exec-maven-plugin
147 | ${maven.exec.plugin.version}
148 |
149 |
150 | run-greeting-application
151 | post-integration-test
152 |
153 | exec
154 |
155 |
156 | java
157 |
158 | -jar
159 | ${project.build.directory}${file.separator}${project.build.finalName}.jar
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/java/org/microprofileext/openapi/features/example/GreetResource.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.features.example;
2 |
3 | import jakarta.enterprise.context.RequestScoped;
4 | import jakarta.inject.Inject;
5 | import jakarta.json.Json;
6 | import jakarta.json.JsonBuilderFactory;
7 | import jakarta.json.JsonObject;
8 | import jakarta.ws.rs.Consumes;
9 | import jakarta.ws.rs.GET;
10 | import jakarta.ws.rs.PUT;
11 | import jakarta.ws.rs.Path;
12 | import jakarta.ws.rs.PathParam;
13 | import jakarta.ws.rs.Produces;
14 | import jakarta.ws.rs.core.MediaType;
15 | import jakarta.ws.rs.core.Response;
16 | import java.util.Collections;
17 |
18 |
19 | import org.eclipse.microprofile.openapi.annotations.Operation;
20 | import org.eclipse.microprofile.openapi.annotations.media.Content;
21 | import org.eclipse.microprofile.openapi.annotations.media.ExampleObject;
22 | import org.eclipse.microprofile.openapi.annotations.media.Schema;
23 | import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
24 | import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
25 |
26 | /**
27 | * A simple JAX-RS resource to greet you. Examples:
28 | *
29 | * Get default greeting message:
30 | * curl -X GET http://localhost:8080/greet
31 | *
32 | * The message is returned as a JSON object.
33 | */
34 | @Path("/greet")
35 | @RequestScoped
36 | public class GreetResource {
37 |
38 | private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap());
39 |
40 | /**
41 | * The greeting message provider.
42 | */
43 | private final GreetingProvider greetingProvider;
44 |
45 | /**
46 | * Using constructor injection to get a configuration property.
47 | * By default this gets the value from META-INF/microprofile-config
48 | *
49 | * @param greetingConfig the configured greeting message
50 | */
51 | @Inject
52 | public GreetResource(GreetingProvider greetingConfig) {
53 | this.greetingProvider = greetingConfig;
54 | }
55 |
56 | /**
57 | * Return a worldly greeting message.
58 | *
59 | * @return {@link JsonObject}
60 | */
61 | @GET
62 | @Operation(summary = "Returns a generic greeting",
63 | description = "Greets the user generically")
64 | @APIResponse(description = "Simple JSON containing the greeting",
65 | content = @Content(mediaType = "application/json",
66 | schema = @Schema(implementation = GreetingMessage.class)))
67 | @Produces(MediaType.APPLICATION_JSON)
68 | public JsonObject getDefaultMessage() {
69 | return createResponse("World");
70 | }
71 |
72 | /**
73 | * Return a greeting message using the name that was provided.
74 | *
75 | * @param name the name to greet
76 | * @return {@link JsonObject}
77 | */
78 | @Path("/{name}")
79 | @GET
80 | @Operation(summary = "Returns a personalized greeting")
81 | @APIResponse(description = "Simple JSON containing the greeting",
82 | content = @Content(mediaType = "application/json",
83 | schema = @Schema(implementation = GreetingMessage.class)))
84 | @Produces(MediaType.APPLICATION_JSON)
85 | public JsonObject getMessage(@PathParam("name") String name) {
86 | return createResponse(name);
87 | }
88 |
89 | /**
90 | * Set the greeting to use in future messages.
91 | *
92 | * @param jsonObject JSON containing the new greeting
93 | * @return {@link Response}
94 | */
95 | @Path("/greeting")
96 | @PUT
97 | @Operation(summary = "Set the greeting prefix",
98 | description = "Permits the client to set the prefix part of the greeting (\"Hello\")")
99 | @RequestBody(
100 | name = "greeting",
101 | description = "Conveys the new greeting prefix to use in building greetings",
102 | content = @Content(
103 | mediaType = "application/json",
104 | schema = @Schema(implementation = GreetingMessage.class),
105 | examples = @ExampleObject(
106 | name = "greeting",
107 | summary = "Example greeting message to update",
108 | value = "New greeting message")))
109 | @Consumes(MediaType.APPLICATION_JSON)
110 | @Produces(MediaType.APPLICATION_JSON)
111 | public Response updateGreeting(JsonObject jsonObject) {
112 |
113 | if (!jsonObject.containsKey("greeting")) {
114 | JsonObject entity = JSON.createObjectBuilder()
115 | .add("error", "No greeting provided")
116 | .build();
117 | return Response.status(Response.Status.BAD_REQUEST).entity(entity).build();
118 | }
119 |
120 | String newGreeting = jsonObject.getString("greeting");
121 |
122 | greetingProvider.setMessage(newGreeting);
123 | return Response.status(Response.Status.NO_CONTENT).build();
124 | }
125 |
126 | private JsonObject createResponse(String who) {
127 | String msg = String.format("%s %s!", greetingProvider.getMessage(), who);
128 |
129 | return JSON.createObjectBuilder()
130 | .add("message", msg)
131 | .build();
132 | }
133 |
134 | /**
135 | * POJO defining the greeting message content exchanged with clients.
136 | */
137 | public static class GreetingMessage {
138 |
139 | private String message;
140 |
141 | /**
142 | * Gets the message value.
143 | *
144 | * @return message value
145 | */
146 | public String getMessage() {
147 | return message;
148 | }
149 |
150 | /**
151 | * Sets the message value.
152 | *
153 | * @param message message value to set
154 | */
155 | public void setMessage(String message) {
156 | this.message = message;
157 | }
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/java/org/microprofileext/openapi/features/example/GreetingProvider.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.features.example;
2 |
3 | import jakarta.enterprise.context.ApplicationScoped;
4 | import jakarta.inject.Inject;
5 | import java.util.concurrent.atomic.AtomicReference;
6 |
7 | import org.eclipse.microprofile.config.inject.ConfigProperty;
8 |
9 | /**
10 | * Provider for greeting message.
11 | */
12 | @ApplicationScoped
13 | public class GreetingProvider {
14 | private final AtomicReference message = new AtomicReference<>();
15 |
16 | /**
17 | * Create a new greeting provider, reading the message from configuration.
18 | *
19 | * @param message greeting to use
20 | */
21 | @Inject
22 | public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {
23 | this.message.set(message);
24 | }
25 |
26 | String getMessage() {
27 | return message.get();
28 | }
29 |
30 | void setMessage(String message) {
31 | this.message.set(message);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/java/org/microprofileext/openapi/features/example/MyApplication.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.features.example;
2 |
3 |
4 | import jakarta.enterprise.context.ApplicationScoped;
5 | import jakarta.ws.rs.ApplicationPath;
6 | import jakarta.ws.rs.core.Application;
7 | import java.util.Set;
8 |
9 | @ApplicationScoped
10 | @ApplicationPath("/myapp")
11 | public class MyApplication extends Application {
12 |
13 | @Override
14 | public Set> getClasses() {
15 | return Set.of(GreetResource.class);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/java/org/microprofileext/openapi/features/example/UiApplication.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.features.example;
2 |
3 | import jakarta.enterprise.context.ApplicationScoped;
4 | import jakarta.ws.rs.ApplicationPath;
5 | import jakarta.ws.rs.core.Application;
6 | import org.microprofileext.openapi.swaggerui.OpenApiUiService;
7 | import org.microprofileext.openapi.swaggerui.StaticResourcesService;
8 |
9 | import java.util.Set;
10 |
11 | @ApplicationScoped
12 | @ApplicationPath("/myopenapi")
13 | public class UiApplication extends Application {
14 |
15 | @Override
16 | public Set> getClasses() {
17 | return Set.of(OpenApiUiService.class,
18 | StaticResourcesService.class);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/java/org/microprofileext/openapi/features/example/package-info.java:
--------------------------------------------------------------------------------
1 |
2 | package org.microprofileext.openapi.features.example;
3 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/resources/META-INF/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/resources/META-INF/microprofile-config.properties:
--------------------------------------------------------------------------------
1 |
2 | # Application properties. This is the default greeting
3 | app.greeting=Hello
4 |
5 | # Microprofile server properties
6 | server.port=8080
7 | server.host=0.0.0.0
8 |
9 | openapi.web-context=/myopenapi
10 | openapi.ui.yamlUrl=/myopenapi
11 |
12 |
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/resources/META-INF/openapi.yaml:
--------------------------------------------------------------------------------
1 |
2 | components:
3 | schemas:
4 | GreetingMessage:
5 | properties:
6 | message:
7 | type: string
8 | type: object
9 | info:
10 | title: Generated API
11 | version: '1.0'
12 | openapi: 3.0.3
13 | paths:
14 | /myapp/dummyEndpoint:
15 | get:
16 | description: Dummy endpoint from META-INF/openapi.yam file
17 | responses:
18 | default:
19 | description: Nothing interesting to respond
20 | /myapp/greet:
21 | get:
22 | description: Greets the user generically
23 | responses:
24 | default:
25 | content:
26 | application/json:
27 | schema:
28 | $ref: '#/components/schemas/GreetingMessage'
29 | description: Simple JSON containing the greeting
30 | summary: Returns a generic greeting
31 | /myapp/greet/greeting:
32 | put:
33 | description: Permits the client to set the prefix part of the greeting ("Hello")
34 | requestBody:
35 | content:
36 | application/json:
37 | examples:
38 | greeting:
39 | summary: Example greeting message to update
40 | value: New greeting message
41 | schema:
42 | $ref: '#/components/schemas/GreetingMessage'
43 | description: Conveys the new greeting prefix to use in building greetings
44 | responses:
45 | '200':
46 | description: OK
47 | summary: Set the greeting prefix
48 | /myapp/greet/{name}:
49 | get:
50 | parameters:
51 | -
52 | in: path
53 | name: name
54 | required: true
55 | schema:
56 | type: string
57 | responses:
58 | default:
59 | content:
60 | application/json:
61 | schema:
62 | $ref: '#/components/schemas/GreetingMessage'
63 | description: Simple JSON containing the greeting
64 | summary: Returns a personalized greeting
--------------------------------------------------------------------------------
/openapi-examples/helidon-features-example/src/main/resources/logging.properties:
--------------------------------------------------------------------------------
1 |
2 | # Example Logging Configuration File
3 | # For more information see $JAVA_HOME/jre/lib/logging.properties
4 |
5 | # Send messages to the console
6 | handlers=io.helidon.common.HelidonConsoleHandler
7 |
8 | # HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
9 | java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
10 |
11 | # Global logging level. Can be overridden by specific loggers
12 | .level=INFO
13 |
14 | # Quiet Weld
15 | org.jboss.level=WARNING
16 |
17 | # Component specific log levels
18 | #io.helidon.webserver.level=INFO
19 | #io.helidon.config.level=INFO
20 | #io.helidon.security.level=INFO
21 | #io.helidon.common.level=INFO
22 | #io.netty.level=INFO
23 |
--------------------------------------------------------------------------------
/openapi-examples/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.microprofile-ext
6 | openapi-ext
7 | 2.1.2-SNAPSHOT
8 |
9 |
10 | org.microprofile-ext.examples
11 | openapi-examples
12 | pom
13 |
14 | Microprofile OpenApi Extensions :: Examples
15 | Module containing OpenApi Extension examples
16 |
17 |
18 | 3.0.1
19 | 2.13.4
20 | 5.7.0
21 |
22 |
23 | 3.0.1
24 | 1.2.3
25 | 3.0.2
26 | 3.1.2
27 | 1.6.0
28 |
29 |
30 |
31 | basic-example
32 | helidon-features-example
33 | helidon-basic-example
34 |
35 |
36 |
37 |
38 |
39 | org.apache.maven.plugins
40 | maven-war-plugin
41 | 3.3.2
42 |
43 | false
44 |
45 |
46 |
47 | org.apache.maven.plugins
48 | maven-compiler-plugin
49 | 3.11.0
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/openapi-ui/README.md:
--------------------------------------------------------------------------------
1 | [Back to openapi-ext](https://github.com/microprofile-extensions/openapi-ext/blob/main/README.md)
2 |
3 | # OpenAPI UI
4 |
5 | [](https://maven-badges.herokuapp.com/maven-central/org.microprofile-ext.openapi-ext/openapi-ui)
6 | [](https://www.javadoc.io/doc/org.microprofile-ext.openapi-ext/openapi-ui)
7 |
8 | This library adds Swagger UI to MicroProfile OpenAPI.
9 |
10 | Read more about OpenAPI here:
11 |
12 | * [Specification](http://download.eclipse.org/microprofile/microprofile-open-api-1.0/microprofile-openapi-spec.html)
13 | * [Github](https://github.com/eclipse/microprofile-open-api)
14 |
15 | ## Getting started
16 |
17 | In your ```pom.xml```:
18 |
19 | ```xml
20 |
21 |
22 | org.microprofile-ext.openapi-ext
23 | openapi-ui
24 | XXXX
25 | runtime
26 |
27 |
28 | ```
29 |
30 | This will pull in Swagger UI via [webjars](http://webjars.org/) and generate the ```index.html``` from a template that you can configure using [MicroProfile Config API](https://github.com/eclipse/microprofile-config).
31 |
32 | Just adding the above will already give you the default UI, example:
33 |
34 | http://localhost:8080/example/api/openapi-ui/
35 |
36 | 
37 |
38 | ## Personalize your UI
39 |
40 | Using the Config API you can Personalize the UI. Here are the config keys you can use:
41 |
42 | * **openapi.ui.copyrightBy** - Adds a name to the copyright in the footer. Defaults to none.
43 | * **openapi.ui.copyrightYear** - Adds the copyright year. Defaults to current year.
44 | * **openapi.ui.title** - Adds the title in the window. Defaults to "MicroProfile - Open API".
45 | * **openapi.ui.contextRoot** - Adds the context root. Defaults to the current value.
46 | * **openapi.ui.yamlUrl** - The URL for the OpenApi yaml. Defaults to /openapi
47 | * **openapi.ui.swaggerUiTheme** - Use a theme from swagger-ui-themes. Defaults to "flattop".
48 | * **openapi.ui.swaggerHeaderVisibility** - Show/hide the swagger logo header. Defaults to "visible".
49 | * **openapi.ui.exploreFormVisibility** - Show/hide the explore form. Defaults to "hidden".
50 | * **openapi.ui.serverVisibility** - Show/hide the server selection. Defaults to "hidden".
51 | * **openapi.ui.createdWithVisibility** - Show/hide the created with footer. Defaults to "visible".
52 | * **openapi.ui.oauth2RedirectUri** - Add the oauth2 callback uri. Defaults to "/oauth2-redirect.html".
53 |
54 |
55 | Example: Adding this to ```META-INF/microprofile-config.properties```
56 |
57 | ```
58 |
59 | openapi.ui.copyrightBy=Phillip Kruger
60 | openapi.ui.title=My awesome services
61 | openapi.ui.swaggerHeaderVisibility=hidden
62 | openapi.ui.serverVisibility=visible
63 | ```
64 |
65 | will change the UI:
66 |
67 | 
68 |
69 | ### Theme
70 |
71 | The default UI uses the flattop theme from [swagger-ui-themes](http://meostrander.com/swagger-ui-themes/), but you can also change that:
72 |
73 | ```
74 |
75 | openapi.ui.swaggerUiTheme=monokai
76 | ```
77 |
78 | 
79 |
80 | ### Logo
81 |
82 | Lastly, you can change the logo to your company logo by including a file named ```openapi.png``` in ```/src/main/resources/```:
83 |
84 | 
85 |
--------------------------------------------------------------------------------
/openapi-ui/configured1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microprofile-extensions/openapi-ext/43f3ddb6c3e953b70406d00436e86a146186d5ee/openapi-ui/configured1.png
--------------------------------------------------------------------------------
/openapi-ui/configured2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microprofile-extensions/openapi-ext/43f3ddb6c3e953b70406d00436e86a146186d5ee/openapi-ui/configured2.png
--------------------------------------------------------------------------------
/openapi-ui/configured3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microprofile-extensions/openapi-ext/43f3ddb6c3e953b70406d00436e86a146186d5ee/openapi-ui/configured3.png
--------------------------------------------------------------------------------
/openapi-ui/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.microprofile-ext
6 | openapi-ext
7 | 2.1.2-SNAPSHOT
8 |
9 |
10 | org.microprofile-ext.openapi-ext
11 | openapi-ui
12 | jar
13 |
14 | Microprofile OpenApi Extensions :: OpenApi UI
15 | A (swagger) UI for MicroProfile Open API
16 |
17 |
18 | 5.18.2
19 | 3.0.1
20 |
21 |
22 |
23 |
24 | org.junit.jupiter
25 | junit-jupiter-api
26 | 5.3.1
27 | test
28 |
29 |
30 | org.junit.jupiter
31 | junit-jupiter-params
32 | 5.3.1
33 | test
34 |
35 |
36 | org.junit.jupiter
37 | junit-jupiter-engine
38 | 5.3.1
39 | test
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | ${basedir}/src/main/resources
49 |
50 |
51 | ${basedir}/src/main/webapp
52 | ${project.build.directory}/classes/META-INF/resources
53 | true
54 |
55 | **/*.css
56 | **/*.html
57 |
58 |
59 |
60 | ${basedir}/src/main/webapp
61 | ${project.build.directory}/classes/META-INF/resources
62 | false
63 |
64 | **/*.css
65 | **/*.html
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | org.apache.maven.plugins
75 | maven-dependency-plugin
76 | 3.1.1
77 |
78 |
79 |
80 | org.webjars
81 | swagger-ui
82 | ${swagger-ui.version}
83 | jar
84 | true
85 | ${project.build.directory}/classes
86 |
87 |
88 | org.webjars.npm
89 | swagger-ui-themes
90 | ${swagger.ui.themes.version}
91 | jar
92 | true
93 | ${project.build.directory}/classes
94 |
95 |
96 | **/screenshots/**,**/themes/2.x/**,**/README.md,**/bower.json,**/package.json,**/*.gz, META-INF/maven/**,**/index.html,**/favicon*.png
97 | UTF-8
98 |
99 |
100 |
101 | generate-sources
102 |
103 | unpack
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/openapi-ui/src/main/java/org/microprofileext/openapi/swaggerui/OpenApiUiService.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.swaggerui;
2 |
3 | import jakarta.annotation.security.PermitAll;
4 | import jakarta.inject.Inject;
5 | import jakarta.ws.rs.GET;
6 | import jakarta.ws.rs.Path;
7 | import jakarta.ws.rs.Produces;
8 | import jakarta.ws.rs.core.Context;
9 | import jakarta.ws.rs.core.HttpHeaders;
10 | import jakarta.ws.rs.core.MediaType;
11 | import jakarta.ws.rs.core.Response;
12 | import jakarta.ws.rs.core.UriInfo;
13 | import java.net.URI;
14 | import lombok.extern.java.Log;
15 | import org.eclipse.microprofile.openapi.annotations.Operation;
16 |
17 | /**
18 | * This service creates a HTML document for Swagger UI
19 | * @author Phillip Kruger (phillip.kruger@phillip-kruger.com)
20 | */
21 | @Log
22 | @Path("/openapi-ui/")
23 | @PermitAll
24 | public class OpenApiUiService {
25 |
26 | @Inject
27 | private Templates templates;
28 |
29 | @Context
30 | private UriInfo uriInfo;
31 |
32 | @Context
33 | private HttpHeaders httpHeaders;
34 |
35 | @GET
36 | @Produces("image/png")
37 | @Path("logo.png")
38 | @Operation(hidden = true)
39 | public byte[] getLogo(){
40 | return templates.getOriginalLogo();
41 | }
42 |
43 | @GET
44 | @Produces(MediaType.TEXT_HTML)
45 | @Path(INDEX_HTML)
46 | @Operation(hidden = true)
47 | public Response getOpenApiUI(){
48 | RequestInfo requestInfo = new RequestInfo(uriInfo, httpHeaders);
49 | String swaggerUI = templates.getSwaggerUIHtml(requestInfo);
50 | return Response.ok(swaggerUI, MediaType.TEXT_HTML).build();
51 | }
52 |
53 | @GET
54 | @Produces("text/css")
55 | @Path("style.css")
56 | @Operation(hidden = true)
57 | public Response getCss(){
58 | String css = templates.getStyle();
59 | return Response.ok(css, "text/css").build();
60 | }
61 |
62 | @GET
63 | @Produces(MediaType.TEXT_HTML)
64 | @Operation(hidden = true)
65 | public Response getSwaggerUINaked(){
66 | URI fw = uriInfo.getRequestUriBuilder().path(INDEX_HTML).build();
67 | return Response.temporaryRedirect(fw).build();
68 | }
69 |
70 | private static final String INDEX_HTML = "index.html";
71 |
72 | }
--------------------------------------------------------------------------------
/openapi-ui/src/main/java/org/microprofileext/openapi/swaggerui/RequestInfo.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.swaggerui;
2 |
3 | import jakarta.ws.rs.core.HttpHeaders;
4 | import jakarta.ws.rs.core.UriInfo;
5 | import java.net.URI;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Getter;
8 | import lombok.NoArgsConstructor;
9 |
10 | /**
11 | * Holding info about the request
12 | * @author Phillip Kruger (phillip.kruger@redhat.com)
13 | */
14 | @AllArgsConstructor @NoArgsConstructor
15 | public class RequestInfo {
16 | @Getter
17 | private UriInfo uriInfo;
18 | @Getter
19 | private HttpHeaders httpHeaders;
20 |
21 | public String getContextPath(){
22 | if(!isValid())return EMPTY;
23 | String path = this.uriInfo.getBaseUri().getPath();
24 | return getContextPath(path);
25 | }
26 |
27 | public String getContextPath(String path){
28 | if(path.startsWith(SLASH))path = path.substring(1);
29 | if(path.endsWith(SLASH))path = path.substring(0, path.length());
30 | if(path.contains(SLASH)){
31 | return SLASH + path.substring(0,path.indexOf(SLASH));
32 | } else {
33 | return EMPTY; // Asume no context path ?
34 | }
35 | }
36 |
37 | public String getRestPath(){
38 | if(!isValid())return EMPTY;
39 | String path = this.uriInfo.getBaseUri().getPath();
40 | return getRestPath(path);
41 | }
42 |
43 | public String getRestPath(String path){
44 | if(path.startsWith(SLASH))path = path.substring(1);
45 | if(path.endsWith(SLASH))path = path.substring(0, path.length()-1);
46 | if(path.contains(SLASH)){
47 | return path.substring(path.indexOf(SLASH));
48 | } else {
49 | return SLASH + path;
50 | }
51 | }
52 |
53 | private boolean isValid(){
54 | if(this.uriInfo==null)return false;
55 |
56 | URI baseUri = this.uriInfo.getBaseUri();
57 | if(baseUri==null)return false;
58 |
59 | String path = baseUri.getPath();
60 | if(path==null || path.isEmpty()) return false;
61 |
62 | return true;
63 | }
64 |
65 | private static final String EMPTY = "";
66 | private static final String SLASH = "/";
67 | }
68 |
--------------------------------------------------------------------------------
/openapi-ui/src/main/java/org/microprofileext/openapi/swaggerui/StaticResourcesService.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.swaggerui;
2 |
3 | import jakarta.ws.rs.GET;
4 | import jakarta.ws.rs.Path;
5 | import jakarta.ws.rs.PathParam;
6 | import jakarta.ws.rs.core.Response;
7 | import java.io.BufferedReader;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.InputStreamReader;
11 | import java.io.StringWriter;
12 | import java.nio.charset.StandardCharsets;
13 | import java.util.Objects;
14 | import java.util.logging.Level;
15 | import lombok.extern.java.Log;
16 | import org.eclipse.microprofile.openapi.annotations.Operation;
17 |
18 | /**
19 | * Serving static data from webjars
20 | * @author Phillip Kruger (phillip.kruger@redhat.com)
21 | */
22 | @Log
23 | @Path("{path: webjars/.*}")
24 | public class StaticResourcesService {
25 |
26 | @GET
27 | @Operation(hidden = true)
28 | public Response staticJsResources(@PathParam("path") final String path) {
29 | try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(String.format("META-INF/resources/%s", path))) {
30 | if(Objects.isNull(inputStream)) {
31 | log.log(Level.WARNING, "Could not find resource [{0}]", path);
32 | return Response.status(Response.Status.NOT_FOUND).build();
33 | }
34 | try ( BufferedReader buffer = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
35 | StringWriter stringWriter = new StringWriter()) {
36 | buffer.lines().forEach(stringWriter::write);
37 | String response = stringWriter.toString();
38 | if (response != null && !response.isEmpty()) {
39 | Response.ResponseBuilder ret = Response.ok(response);
40 | if (path.endsWith(".js")) {
41 | ret = ret.type("application/javascript");
42 | }
43 | return ret.build();
44 | } else {
45 | log.log(Level.WARNING, "The requested swagger file is empty!");
46 | return Response.noContent().build();
47 | }
48 | }
49 | } catch (IOException | NullPointerException ex) {
50 | log.log(Level.SEVERE, "Failed to read the static Swagger file at path: {0}. Error details: {1}", new Object[]{path, ex.getMessage()});
51 | return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
52 | }
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/openapi-ui/src/main/java/org/microprofileext/openapi/swaggerui/Templates.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.swaggerui;
2 |
3 | import jakarta.annotation.PostConstruct;
4 | import jakarta.enterprise.context.ApplicationScoped;
5 | import jakarta.inject.Inject;
6 | import java.io.BufferedReader;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.InputStreamReader;
10 | import java.net.URISyntaxException;
11 | import java.net.URL;
12 | import java.nio.file.Files;
13 | import java.nio.file.Paths;
14 | import java.util.Arrays;
15 | import java.util.Calendar;
16 | import java.util.List;
17 | import java.util.Optional;
18 | import java.util.logging.Level;
19 | import java.util.stream.Collectors;
20 | import lombok.Getter;
21 | import lombok.extern.java.Log;
22 | import org.eclipse.microprofile.config.Config;
23 | import org.eclipse.microprofile.config.inject.ConfigProperty;
24 |
25 | /**
26 | * Helping with the templates (
27 | * @author Phillip Kruger (phillip.kruger@phillip-kruger.com)
28 | */
29 | @Log
30 | @ApplicationScoped
31 | public class Templates {
32 |
33 | @Getter
34 | private byte[] originalLogo = null;
35 |
36 | @Getter
37 | private String style = null;
38 |
39 | @Inject
40 | private WhiteLabel whiteLabel;
41 |
42 | private String swaggerUIHtml = null;
43 |
44 | @PostConstruct
45 | public void afterCreate() {
46 | this.originalLogo = getLogo();
47 | log.finest("OpenApi UI: Created logo");
48 | this.style = getCss();
49 | }
50 |
51 | public String getSwaggerUIHtml(RequestInfo requestInfo){
52 | if(this.swaggerUIHtml==null){
53 | this.swaggerUIHtml = parseHtmlTemplate(requestInfo);
54 | }
55 | return this.swaggerUIHtml;
56 | }
57 |
58 | private String parseHtmlTemplate(RequestInfo requestInfo){
59 | String html = getHTMLTemplate();
60 |
61 | html = html.replaceAll(VAR_CONTEXT_ROOT, getContextRoot(requestInfo));
62 | html = html.replaceAll(VAR_YAML_URL, yamlUrl);
63 | html = html.replaceAll(VAR_CURRENT_YEAR, getCopyrightYear());
64 | html = html.replaceAll(VAR_OAUTH2_REDIRECT_URI, oauth2RedirectUri);
65 |
66 | // Dynamic whitelabel properties.
67 | try {
68 | Iterable propertyNames = config.getPropertyNames();
69 | for(String key: propertyNames){
70 | if(key.startsWith(KEY_IDENTIFIER) && !isKnownProperty(key)){
71 | String htmlKey = PERSENTAGE + key + PERSENTAGE;
72 | html = html.replaceAll(htmlKey, config.getValue(key,String.class));
73 | }
74 | }
75 | }catch(UnsupportedOperationException uoe){
76 | log.log(Level.WARNING, "Can not replace dynamic properties in the Open API Swagger template. {0}", uoe.getMessage());
77 | }
78 | // Then properties with defaults.
79 | html = html.replaceAll(VAR_COPYRIGHT_BY, getCopyrightBy());
80 | html = html.replaceAll(VAR_TITLE, title);
81 | html = html.replaceAll(VAR_SWAGGER_THEME, swaggerUiTheme);
82 |
83 | if ("hidden".equalsIgnoreCase(modelsVisibility)) {
84 | String domId = "dom_id: '#swagger-ui',";
85 | html = html.replaceAll(domId, domId + "\n defaultModelsExpandDepth: -1,");
86 | }
87 | return html;
88 | }
89 |
90 | private String getOriginalContextPath(RequestInfo requestInfo){
91 | String xRequestUriHeader = requestInfo.getHttpHeaders().getHeaderString(X_REQUEST_URI);
92 | if(xRequestUriHeader!=null && !xRequestUriHeader.isEmpty()){
93 | return getContextPathPart(requestInfo,xRequestUriHeader);
94 | }
95 | return requestInfo.getContextPath();
96 | }
97 |
98 | private String getContextPathPart(RequestInfo requestInfo,String xRequestUriHeader){
99 |
100 | String restBase = requestInfo.getRestPath();
101 | String restUrl = restBase + requestInfo.getUriInfo().getPath();
102 |
103 | int restUrlStart = xRequestUriHeader.indexOf(restUrl);
104 |
105 | if(restUrlStart>0){
106 | return xRequestUriHeader.substring(0, restUrlStart);
107 | }else{
108 | return xRequestUriHeader;
109 | }
110 |
111 | }
112 |
113 | private String toString(InputStream input) throws IOException {
114 | try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
115 | return buffer.lines().collect(Collectors.joining(NL));
116 | }
117 | }
118 |
119 | private byte[] getLogo(){
120 | if(whiteLabel.hasLogo())return whiteLabel.getLogo();
121 |
122 | // Logo
123 | InputStream logoStream = this.getClass().getClassLoader().getResourceAsStream(FILE_LOGO);
124 | try{
125 | if(logoStream!=null){
126 | return logoStream.readAllBytes();
127 | }
128 | } catch (IOException ex) {
129 | log.warning(ex.getMessage());
130 | }
131 | return null;
132 | }
133 |
134 | private String getCss() {
135 | String rawcss;
136 |
137 | if(whiteLabel.hasCss()){
138 | rawcss = whiteLabel.getCss();
139 | }else {
140 |
141 | try(InputStream css = this.getClass().getClassLoader().getResourceAsStream(FILE_STYLE)){
142 | rawcss = toString(css);
143 | } catch (IOException ex) {
144 | return EMPTY;
145 | }
146 | }
147 |
148 | rawcss = rawcss.replaceAll(VAR_SWAGGER_HEADER_VISIBILITY, swaggerHeaderVisibility);
149 | rawcss = rawcss.replaceAll(VAR_EXPLORE_FORM_VISIBILITY, exploreFormVisibility);
150 | rawcss = rawcss.replaceAll(VAR_SERVER_VISIBILITY, serverVisibility);
151 | rawcss = rawcss.replaceAll(VAR_SERVER_VISIBILITY_BLOCK_SIZE, getServerVisibilityBlockSize());
152 | rawcss = rawcss.replaceAll(VAR_CREATED_WITH_VISIBILITY, createdWithVisibility);
153 |
154 | return rawcss;
155 | }
156 |
157 | private String getServerVisibilityBlockSize() {
158 | if(serverVisibility.equals("hidden"))return "0px";
159 | return "auto";
160 | }
161 |
162 | private String getHTMLTemplate() {
163 | if(whiteLabel.hasHtml())return whiteLabel.getHtml();
164 | try(InputStream template = this.getClass().getClassLoader().getResourceAsStream(FILE_TEMPLATE)){
165 | return toString(template);
166 | } catch (IOException ex) {
167 | return EMPTY;
168 | }
169 | }
170 |
171 | private String getCopyrightYear(){
172 | if(copyrightYear.isPresent()){
173 | return copyrightYear.get();
174 | }
175 | return String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
176 | }
177 |
178 | private String getCopyrightBy(){
179 | if(copyrightBy.isPresent()){
180 | return copyrightBy.get();
181 | }
182 | return EMPTY;
183 | }
184 |
185 | private String getContextRoot(RequestInfo requestInfo){
186 | if(contextRoot.isPresent()){
187 | return contextRoot.get();
188 | }
189 | return getOriginalContextPath(requestInfo);
190 | }
191 |
192 | private boolean isKnownProperty(String key){
193 | return KNOWN_PROPERTIES.contains(key);
194 | }
195 |
196 | private static final String X_REQUEST_URI = "x-request-uri";
197 | private static final List KNOWN_PROPERTIES = Arrays.asList(new String[]{"openapi.ui.serverVisibility","openapi.ui.exploreFormVisibility","openapi.ui.swaggerHeaderVisibility","openapi.ui.copyrightBy","openapi.ui.copyrightYear","openapi.ui.title","openapi.ui.contextRoot","openapi.ui.yamlUrl","openapi.ui.swaggerUiTheme"});
198 |
199 | @Inject @ConfigProperty(name = "openapi.ui.copyrightBy")
200 | private Optional copyrightBy;
201 |
202 | @Inject @ConfigProperty(name = "openapi.ui.copyrightYear")
203 | private Optional copyrightYear;
204 |
205 | @Inject @ConfigProperty(name = "openapi.ui.title", defaultValue = "MicroProfile - Open API")
206 | private String title;
207 |
208 | @Inject @ConfigProperty(name = "openapi.ui.contextRoot")
209 | private Optional contextRoot;
210 |
211 | @Inject @ConfigProperty(name = "openapi.ui.yamlUrl", defaultValue = "/openapi")
212 | private String yamlUrl;
213 |
214 | @Inject @ConfigProperty(name = "openapi.ui.swaggerUiTheme", defaultValue = "flattop")
215 | private String swaggerUiTheme;
216 |
217 | @Inject @ConfigProperty(name = "openapi.ui.swaggerHeaderVisibility", defaultValue = "visible")
218 | private String swaggerHeaderVisibility;
219 |
220 | @Inject @ConfigProperty(name = "openapi.ui.exploreFormVisibility", defaultValue = "hidden")
221 | private String exploreFormVisibility;
222 |
223 | @Inject @ConfigProperty(name = "openapi.ui.serverVisibility", defaultValue = "hidden")
224 | private String serverVisibility;
225 |
226 | @Inject @ConfigProperty(name = "openapi.ui.createdWithVisibility", defaultValue = "visible")
227 | private String createdWithVisibility;
228 |
229 | @Inject @ConfigProperty(name = "openapi.ui.modelsVisibility", defaultValue = "visible")
230 | private String modelsVisibility;
231 |
232 | @Inject @ConfigProperty(name = "openapi.ui.oauth2RedirectUri",
233 | defaultValue = "/oauth2-redirect.html")
234 | private String oauth2RedirectUri;
235 |
236 | @Inject
237 | private Config config;
238 |
239 | private static final String VAR_COPYRIGHT_BY = "%copyrighBy%";
240 | private static final String VAR_TITLE = "%title%";
241 | private static final String VAR_CURRENT_YEAR = "%currentYear%";
242 | private static final String VAR_CONTEXT_ROOT = "%contextRoot%";
243 | private static final String VAR_YAML_URL = "%yamlUrl%";
244 |
245 | private static final String VAR_SWAGGER_THEME = "%swaggerUiTheme%";
246 | private static final String VAR_SWAGGER_HEADER_VISIBILITY = "%swaggerHeaderVisibility%";
247 | private static final String VAR_EXPLORE_FORM_VISIBILITY = "%exploreFormVisibility%";
248 | private static final String VAR_SERVER_VISIBILITY = "%serverVisibility%";
249 | private static final String VAR_SERVER_VISIBILITY_BLOCK_SIZE = "%serverVisibilityBlockSize%";
250 | private static final String VAR_CREATED_WITH_VISIBILITY = "%createdWithVisibility%";
251 | private static final String VAR_OAUTH2_REDIRECT_URI = "%oauth2RedirectUri%";
252 |
253 | private static final String PERSENTAGE = "%";
254 |
255 | private static final String NL = "\n";
256 | private static final String EMPTY = "";
257 | private static final String FILE_TEMPLATE = "META-INF/resources/templates/template.html";
258 | private static final String FILE_LOGO = "META-INF/resources/templates/logo.png";
259 | private static final String FILE_STYLE = "META-INF/resources/templates/style.css";
260 | private static final String KEY_IDENTIFIER = "openapi.ui.";
261 | }
--------------------------------------------------------------------------------
/openapi-ui/src/main/java/org/microprofileext/openapi/swaggerui/WhiteLabel.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.swaggerui;
2 |
3 | import jakarta.annotation.PostConstruct;
4 | import jakarta.enterprise.context.ApplicationScoped;
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.InputStreamReader;
9 | import java.util.logging.Level;
10 | import java.util.stream.Collectors;
11 | import lombok.Getter;
12 | import lombok.extern.java.Log;
13 |
14 | /**
15 | * White label the UI
16 | * @author Phillip Kruger (phillip.kruger@phillip-kruger.com)
17 | */
18 | @Log
19 | @ApplicationScoped
20 | public class WhiteLabel {
21 |
22 | private final String LOGO_FILE_NAME = "openapi.png";
23 | private final String CSS_FILE_NAME = "openapi.css";
24 | private final String HTML_FILE_NAME = "openapi.html";
25 |
26 | @Getter
27 | private byte[] logo = null;
28 |
29 | @Getter
30 | private String css = null;
31 | @Getter
32 | private String html = null;
33 |
34 | @PostConstruct
35 | public void init(){
36 |
37 | // Logo
38 | try(InputStream logoStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(LOGO_FILE_NAME)){
39 | if(logoStream!=null){
40 | this.logo = logoStream.readAllBytes();
41 | }else{
42 | log.log(Level.FINEST, "Can not load whilelable logo [{0}]", LOGO_FILE_NAME);
43 | }
44 | } catch (IOException ex) {
45 | log.log(Level.FINEST, "Can not load whilelable logo [{0}] - {1}", new Object[]{LOGO_FILE_NAME,ex.getMessage()});
46 | }
47 |
48 | // Css
49 | try(InputStream cssStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(CSS_FILE_NAME)){
50 | if(cssStream!=null){
51 | this.css = toString(cssStream);
52 | }else{
53 | log.log(Level.FINEST, "Can not load whilelable css [{0}]", CSS_FILE_NAME);
54 | }
55 | } catch (IOException ex) {
56 | log.log(Level.FINEST, "Can not load whilelable css [{0}] - {1}", new Object[]{CSS_FILE_NAME, ex.getMessage()});
57 | }
58 |
59 | // Html
60 | try(InputStream htmlStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(HTML_FILE_NAME)){
61 | if(htmlStream!=null){
62 | this.html = toString(htmlStream);
63 | }else{
64 | log.log(Level.FINEST, "Can not load whilelable html [{0}]", HTML_FILE_NAME);
65 | }
66 | } catch (IOException ex) {
67 | log.log(Level.FINEST, "Can not load whilelable html [{0}] - {1}", new Object[]{HTML_FILE_NAME, ex.getMessage()});
68 | }
69 | }
70 |
71 | public boolean hasLogo(){
72 | return logo!=null;
73 | }
74 |
75 | public boolean hasCss() {
76 | return css!=null;
77 | }
78 |
79 | public boolean hasHtml() {
80 | return html!=null;
81 | }
82 |
83 | private String toString(InputStream input) throws IOException {
84 | try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
85 | return buffer.lines().collect(Collectors.joining(NL));
86 | }
87 | }
88 | private static final String NL = "\n";
89 | }
90 |
--------------------------------------------------------------------------------
/openapi-ui/src/main/resources/META-INF/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/openapi-ui/src/main/resources/META-INF/web-fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | resteasy.resources
10 | org.microprofileext.openapi.swaggerui.OpenApiUiService
11 |
12 |
13 |
--------------------------------------------------------------------------------
/openapi-ui/src/main/webapp/templates/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microprofile-extensions/openapi-ext/43f3ddb6c3e953b70406d00436e86a146186d5ee/openapi-ui/src/main/webapp/templates/logo.png
--------------------------------------------------------------------------------
/openapi-ui/src/main/webapp/templates/style.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | overflow: -moz-scrollbars-vertical;
4 | overflow-y: scroll;
5 | }
6 |
7 | *,*:before,*:after {
8 | box-sizing: inherit;
9 | }
10 |
11 | body {
12 | margin:0;
13 | margin-bottom: 100px;
14 | background-image: url("logo.png");
15 | background-repeat: no-repeat;
16 | background-attachment: fixed;
17 | background-position: bottom right;
18 | background-size: 200px;
19 | }
20 |
21 | #footer {
22 | color: #999;
23 | font-size: 80%;
24 | position:fixed;
25 | bottom:0;
26 | background: #2c3e50;
27 | width: 100%;
28 | text-align: center;
29 | }
30 |
31 | #footer a , #footer a:link ,#footer a:visited {
32 | color: #999;
33 | text-decoration-line: none;
34 | }
35 |
36 | #footer a:hover {
37 | color: black;
38 | text-decoration-line: underline;
39 | }
40 |
41 | .createdWith {
42 | visibility: %createdWithVisibility%;
43 | }
44 |
45 | .swagger-ui .topbar .download-url-wrapper {
46 | display:-webkit-box;
47 | display:-ms-flexbox;
48 | display:flex;
49 | -webkit-box-flex:3;
50 | -ms-flex:3;
51 | flex:3;
52 | -webkit-box-pack:end;
53 | -ms-flex-pack:end;
54 | justify-content:flex-end;
55 | visibility: %exploreFormVisibility%;
56 | }
57 |
58 | .swagger-ui .topbar .topbar-wrapper,.swagger-ui .topbar a {
59 | display:-webkit-box;
60 | display:-ms-flexbox;
61 | display:flex;
62 | -webkit-box-align:center;
63 | -ms-flex-align:center;
64 | align-items:center;
65 | visibility: %swaggerHeaderVisibility%;
66 | }
67 |
68 | .swagger-ui .global-server-container {
69 | visibility: %serverVisibility%;
70 | block-size: %serverVisibilityBlockSize%;
71 | margin: unset;
72 | padding: 0px;
73 | }
--------------------------------------------------------------------------------
/openapi-ui/src/main/webapp/templates/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %title%
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
40 |
41 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/openapi-ui/src/test/java/org/microprofileext/openapi/swaggerui/RequestInfoTest.java:
--------------------------------------------------------------------------------
1 | package org.microprofileext.openapi.swaggerui;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.junit.jupiter.api.Test;
6 |
7 | /**
8 | * Test all the types of paths
9 | * @author Phillip Kruger (phillip.kruger@gmail.com)
10 | */
11 | public class RequestInfoTest {
12 |
13 | @Test
14 | public void testContextPathWithRestPath() {
15 | String path = "/somecontext/api";
16 |
17 | RequestInfo requestInfo = new RequestInfo();
18 | String context = requestInfo.getContextPath(path);
19 | assertEquals("/somecontext", context);
20 |
21 | String rest = requestInfo.getRestPath(path);
22 | assertEquals("/api", rest);
23 | }
24 |
25 | @Test
26 | public void testWhenNoContextPathButWithRestPath() {
27 | String path = "/api";
28 |
29 | RequestInfo requestInfo = new RequestInfo();
30 | String context = requestInfo.getContextPath(path);
31 | assertEquals("", context);
32 |
33 | String rest = requestInfo.getRestPath(path);
34 | assertEquals("/api", rest);
35 | }
36 |
37 | @Test
38 | public void testWhenContextPathButNoRestPath() {
39 | String path = "/somecontext";
40 |
41 | RequestInfo requestInfo = new RequestInfo();
42 | String context = requestInfo.getContextPath(path);
43 | assertEquals("", context);
44 |
45 | String rest = requestInfo.getRestPath(path);
46 | assertEquals("/somecontext", rest);
47 | }
48 |
49 | @Test
50 | public void testWhenNoContextPathAndNoRestPath() {
51 | String path = "/";
52 |
53 | RequestInfo requestInfo = new RequestInfo();
54 | String context = requestInfo.getContextPath(path);
55 | assertEquals("", context);
56 |
57 | String rest = requestInfo.getRestPath(path);
58 | assertEquals("/", rest);
59 | }
60 |
61 | @Test
62 | public void testWhenNoContextPathAndNoRestPath2() {
63 | String path = "";
64 |
65 | RequestInfo requestInfo = new RequestInfo();
66 | String context = requestInfo.getContextPath(path);
67 | assertEquals("", context);
68 |
69 | String rest = requestInfo.getRestPath(path);
70 | assertEquals("/", rest);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/openapi-ui/vanilla.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microprofile-extensions/openapi-ext/43f3ddb6c3e953b70406d00436e86a146186d5ee/openapi-ui/vanilla.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.microprofile-ext
8 | openapi-ext
9 | 2.1.2-SNAPSHOT
10 | pom
11 |
12 | Microprofile OpenAPI Extensions
13 | https://github.com/microprofile-extensions/openapi-ext
14 | Some extensions for MicroProfile OpenAPI
15 |
16 |
17 |
18 | Apache License, Version 2.0
19 | http://www.apache.org/licenses/LICENSE-2.0.txt
20 | repo
21 |
22 |
23 |
24 |
25 | scm:git:https://github.com/microprofile-extensions/openapi-ext.git
26 | https://github.com/microprofile-extensions/openapi-ext
27 |
28 |
29 |
30 |
31 | wiki
32 | http://www.microprofile-ext.org
33 |
34 |
35 |
36 | ossrh
37 | https://oss.sonatype.org/content/repositories/snapshots
38 |
39 |
40 | ossrh
41 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
42 |
43 |
44 |
45 |
46 |
47 |
48 | Phillip Kruger
49 | phillip.kruger@phillip-kruger.com
50 | http://www.phillip-kruger.com
51 |
52 |
53 |
54 |
55 | UTF-8
56 | 1.8
57 | 1.8
58 |
59 | 1.18.30
60 | 6.0
61 |
62 |
63 |
64 |
65 |
66 |
67 | org.eclipse.microprofile
68 | microprofile
69 | ${microProfile.version}
70 | pom
71 | provided
72 |
73 |
74 |
75 | org.projectlombok
76 | lombok
77 | ${lombok.version}
78 | provided
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | org.eclipse.microprofile
88 | microprofile
89 | pom
90 | provided
91 |
92 |
93 |
94 | org.projectlombok
95 | lombok
96 | provided
97 |
98 |
99 |
100 |
101 |
102 |
103 | release
104 |
105 |
106 | release
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | org.sonatype.plugins
115 | nexus-staging-maven-plugin
116 | 1.6.13
117 | true
118 |
119 | ossrh
120 | https://oss.sonatype.org/
121 | true
122 |
123 |
124 |
125 |
126 | org.apache.maven.plugins
127 | maven-source-plugin
128 | 3.1.0
129 |
130 |
131 | attach-sources
132 |
133 | jar-no-fork
134 |
135 |
136 |
137 |
138 |
139 | org.apache.maven.plugins
140 | maven-javadoc-plugin
141 | 3.1.0
142 |
143 |
144 | attach-javadocs
145 |
146 | jar
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | org.apache.maven.plugins
155 | maven-gpg-plugin
156 | 1.6
157 |
158 |
159 | sign-artifacts
160 | verify
161 |
162 | sign
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 | openapi-examples
175 | openapi-ui
176 |
177 |
178 |
--------------------------------------------------------------------------------