-
Notifications
You must be signed in to change notification settings - Fork 2
refactor(minor): Replace direct imports with reflection for native tr… #90
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
Conversation
…ansport classes in SocketIOServer Signed-off-by: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com>
WalkthroughThis PR refactors Netty transport backend detection in SocketIOServer to use runtime reflection-based feature detection instead of direct availability checks. It introduces helper methods for dynamic class resolution and factory acquisition, with graceful NIO fallback when optional backends (IO_URING, EPOLL, KQUEUE) are unavailable. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Pull request overview
This PR fixes a NoClassDefFoundError that occurs when native transport dependencies (Epoll, KQueue, IoUring) are missing from the classpath by replacing direct imports with reflection-based class loading and availability checks.
Key Changes:
- Replaced direct class imports with reflection-based helper methods to check class availability and instantiate transport classes dynamically
- Fixed incorrect default handler from
IoUringIoHandlertoNioIoHandlerin theinitGroups()method - Added graceful fallback to NIO transport when native transports are unavailable
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java
Show resolved
Hide resolved
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java
Show resolved
Hide resolved
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java
Show resolved
Hide resolved
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java
Show resolved
Hide resolved
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.
Actionable comments posted: 1
♻️ Duplicate comments (1)
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java (1)
377-411: Apply the same warning message clarification as in startAsync.Similar to the IO_URING/EPOLL/KQUEUE cases in
startAsync, these blocks have duplicate warning messages with identical text. Apply the same differentiation suggested in the earlier comment for lines 246-256.
🧹 Nitpick comments (2)
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java (2)
74-108: Consider caching the Class<?> to avoid redundant lookups.Each availability check loads the same class twice - once in
isClassAvailableand again inClass.forName. While this works correctly, you could refactor to load the class once and reuse it.Example refactor for
isIoUringAvailable():private static boolean isIoUringAvailable() { - if (!isClassAvailable("io.netty.channel.uring.IoUring")) { - return false; - } try { Class<?> clazz = Class.forName("io.netty.channel.uring.IoUring"); return (Boolean) clazz.getMethod("isAvailable").invoke(null); } catch (Exception e) { return false; } }Apply the same pattern to
isEpollAvailable()andisKQueueAvailable().
282-309: Consider removing intermediate "NIO selected" logs in AUTO cascade.Lines 288, 296, and 304 log "AUTO selected NIO transport" even when the check cascade continues to the next transport. This could confuse log analysis. Consider logging only the final selection or using a different message for intermediate failures.
Example approach - only log the final decision:
+ String selectedTransport = "NIO"; if (isIoUringAvailable()) { Class<? extends ServerChannel> clazz = getIoUringServerSocketChannelClass(); if (clazz != null) { channelClass = clazz; - log.info("AUTO selected IO_URING transport"); + selectedTransport = "IO_URING"; } else { - log.info("AUTO selected NIO transport"); + // continue cascade } } else if (isEpollAvailable()) { Class<? extends ServerChannel> clazz = getEpollServerSocketChannelClass(); if (clazz != null) { channelClass = clazz; - log.info("AUTO selected EPOLL transport"); + selectedTransport = "EPOLL"; } else { - log.info("AUTO selected NIO transport"); + // continue cascade } } else if (isKQueueAvailable()) { Class<? extends ServerChannel> clazz = getKQueueServerSocketChannelClass(); if (clazz != null) { channelClass = clazz; - log.info("AUTO selected KQUEUE transport"); + selectedTransport = "KQUEUE"; } else { - log.info("AUTO selected NIO transport"); + // already NIO } - } else { - log.info("AUTO selected NIO transport"); } + log.info("AUTO selected {} transport", selectedTransport);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: build (21) / build
- GitHub Check: build (25) / build
- GitHub Check: build (17) / build
- GitHub Check: qodana
- GitHub Check: Analyze (java-kotlin)
- GitHub Check: Analyze (java-kotlin)
🔇 Additional comments (5)
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java (5)
65-72: LGTM - Helper method works for availability checks.The approach is appropriate for detecting optional dependencies. Note that other class-loading errors (e.g.,
LinkageError,NoClassDefFoundError) will propagate, but in this context that's acceptable since those indicate more serious configuration issues.
110-135: LGTM - Dynamic channel class resolution is correct.The reflection-based approach with null fallback aligns with the PR's goal of avoiding hard dependencies on native transports.
137-162: LGTM - IoHandler factory resolution handles missing dependencies gracefully.The methods correctly return null when classes are unavailable, allowing callers to fall back to NIO.
413-437: LGTM - AUTO cascade is cleaner than in startAsync.This implementation avoids the intermediate logging issue present in
startAsync's AUTO case by logging only once at the end. The approach is correct and maintainable.
439-442: LGTM - Default case correctly uses NioIoHandler.This change addresses the issue mentioned in the PR objectives where IoUringIoHandler was incorrectly used in the default case.
netty-socketio-core/src/main/java/com/socketio4j/socketio/SocketIOServer.java
Show resolved
Hide resolved
Qodana for JVM61 new problems were found
☁️ View the detailed Qodana report Detected 123 dependenciesThird-party software listThis page lists the third-party software dependencies used in project
Contact Qodana teamContact us at qodana-support@jetbrains.com
|
Description
Fixed an issue where
SocketIOServerdirectly imported IoUring, Epoll, and KQueue classes, which would causeNoClassDefFoundErrorwhen these native transport dependencies are not present in the classpath. The fix uses reflection to dynamically check class availability and gracefully falls back to NIO transport when these classes are unavailable.Type of Change
Related Issue
Closes #(issue number)
Changes Made
IoUring,Epoll,KQueueand their related classesstartAsync()andinitGroups()methods to use reflection instead of direct class referencesIoUringIoHandlerin default case, changed to useNioIoHandlerTesting
mvn testChecklist
Additional Notes
This fix ensures that
SocketIOServercan start normally and automatically fall back to NIO transport even whennetty-transport-native-epoll,netty-transport-native-kqueue, ornetty-transport-native-io_uringdependencies are missing from the classpath. The code has been verified to compile successfully.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.