-
Notifications
You must be signed in to change notification settings - Fork 7
feat: Automatically open Swagger UI on local startup #175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| package ar.com.nanotaboada.java.samples.spring.boot.listeners; | ||
|
|
||
| import java.awt.Desktop; | ||
| import java.net.URI; | ||
| import java.util.Arrays; | ||
| import java.awt.GraphicsEnvironment; | ||
|
|
||
|
|
||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.boot.context.event.ApplicationReadyEvent; | ||
| import org.springframework.context.ApplicationListener; | ||
| import org.springframework.context.annotation.Profile; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| @Profile("local") | ||
|
|
||
|
|
||
| public class SwaggerUiOpener implements ApplicationListener<ApplicationReadyEvent>{ | ||
| private static final Logger log = LoggerFactory.getLogger(SwaggerUiOpener.class); | ||
|
|
||
| @Value("${server.port}") | ||
| private int port; | ||
|
|
||
| @Value("${springdoc.swagger-ui.path:/swagger/index.html}") | ||
| private String swaggerPath; | ||
|
|
||
| @Override | ||
| public void onApplicationEvent(ApplicationReadyEvent event) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor this method to reduce its Cognitive Complexity from 20 to the 15 allowed. |
||
| String url = "http://localhost:" + port + swaggerPath; | ||
| log.info("✅ Swagger UI will open at: {}", url); | ||
|
|
||
| try { | ||
| if (Desktop.isDesktopSupported() && !GraphicsEnvironment.isHeadless()) { | ||
| Desktop.getDesktop().browse(new URI(url)); | ||
| } else { | ||
| launchBrowserByOS(url); | ||
| } | ||
| } catch (Exception e) { | ||
| log.error("❌ Failed to open Swagger UI", e); | ||
| } | ||
| } | ||
|
|
||
| private void launchBrowserByOS(String url) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Method There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Method |
||
| String os = System.getProperty("os.name").toLowerCase(); | ||
| try { | ||
| if (os.contains("win")) { | ||
| new ProcessBuilder("rundll32", "url.dll,FileProtocolHandler", url).start(); | ||
| } else if (os.contains("mac")) { | ||
| new ProcessBuilder("open", url).start(); | ||
| } else if (os.contains("nix") || os.contains("nux")) { | ||
| boolean launched = false; | ||
| for (String browser : Arrays.asList("xdg-open", "google-chrome", "firefox")) { | ||
| Process process = new ProcessBuilder("which", browser).start(); | ||
| try { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extract this nested try block into a separate method. |
||
| int exitCode = process.waitFor(); | ||
| if (exitCode == 0) { | ||
| new ProcessBuilder(browser, url).start(); | ||
| launched = true; | ||
| break; | ||
| } | ||
| } catch (InterruptedException ie) { | ||
| Thread.currentThread().interrupt(); | ||
| log.warn("Browser detection was interrupted", ie); | ||
| } | ||
| } | ||
| if (!launched) { | ||
| log.warn("⚠️ No supported browser found to open Swagger."); | ||
| } | ||
| } else { | ||
| log.warn("⚠️ Unsupported OS for automatic browser launch."); | ||
| } | ||
| } catch (Exception e) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either re-interrupt this method or rethrow the "InterruptedException" that can be caught here. |
||
| log.error("❌ Error while launching browser", e); | ||
| } | ||
| } | ||
|
Comment on lines
+46
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Simplify OS detection & browser launch logic. The method contains nested conditionals, a for-loop over possible Linux browsers, and multiple error-handling blocks, which can inflate its overall complexity. Consider splitting it into separate helper methods (e.g., one for detecting the operating system, another for launching a given browser). This modular approach can reduce complexity and improve testability. |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Dependency version downgrade confirmed as necessary
The downgrade from
2.8.6to2.2.0forspringdoc-openapi-starter-webmvc-uiaddresses the runtimeNoClassDefFoundErrorforLiteWebJarsResourceResolvermentioned in the PR objectives.🌐 Web query:
💡 Result:
Yes, there are known compatibility issues with springdoc-openapi-starter-webmvc-ui 2.2.0 when used with Spring Boot 3.1.8:
1. Multipart Request Content-Type Support
swagger-uidependency (5.2.0), which lacks support for boundary-specificContent-Typeheaders in multipart requests[2][8]. This prevents proper rendering of multipart endpoints in Swagger UI.springdoc-openapiversion (≥2.7.0), which includesswagger-ui5.4.2+[2][6].2. Parameter Name Discovery Issues
-parameterscompiler flag is missing[1][3]. This can cause parameters to be incorrectly marked as required or omitted.-parametersflag to the Maven/Gradle compiler plugin[1]:3. Dependency Vulnerabilities
spring-webmvc,spring-security-config)[5][8]. These expose risks like path traversal and improper access control.springdoc-openapiversion (2.8.6) and ensure Spring Boot dependencies are updated to patched versions (e.g., Spring Boot 3.2.10)[5][6].4. Jakarta EE Compatibility
springdoc-openapiversions may require manual adjustments for imports (e.g., replacingjavaxwithjakarta)[6]. Version 2.2.0 generally handles this correctly but may conflict with non-updated dependencies.Recommended Upgrade Path
springdoc-openapi-starter-webmvc-ui ≥2.8.6with Spring Boot 3.1.8 for full compatibility and security fixes[1][4].webjars/swagger-uito 5.20.3+ to resolve multipart issues[8].For migration steps, see the Spring Boot 3 migration guide[6].
Citations:
Action Required: Revisit Dependency Version for springdoc-openapi-starter-webmvc-ui
While the downgrade to version 2.2.0 was originally applied to work around the
NoClassDefFoundErrorforLiteWebJarsResourceResolver, recent findings show that springdoc-openapi-starter-webmvc-ui 2.2.0 has several compatibility issues with Spring Boot 3.1.8. In particular, it suffers from:swagger-ui(5.2.0) that does not support boundary-specificContent-Typeheaders for multipart requests.-parameterscompiler flag is not enabled.spring-webmvc,spring-security-config).Recommendation:
- Instead of downgrading to 2.2.0, consider retaining or upgrading to version ≥2.8.6, which addresses the runtime error while ensuring better compatibility with Spring Boot 3.1.8.
- Additionally, verify that the Maven compiler plugin is set to use the
-parametersflag for proper parameter name resolution.Diff Snapshot:
Please review these points and update the dependency version accordingly to avoid the highlighted compatibility issues.