Skip to content

Commit c7eda98

Browse files
Flossyclaude
andcommitted
feat: add Checker Framework annotations for null-safety
Adds @nonnull and @nullable annotations to improve null-safety. Changes: - Added checker-qual 3.42.0 dependency to parent POM - Added checker-qual with 'provided' scope to platform-api and platform-core - Annotated ApplicationContext interface (13 methods) - Annotated ServiceRegistry interface (4 methods) - Annotated ApplicationLifecycleListener interface (6 methods) Benefits: - Compile-time null-safety checks - Better IDE support for null analysis - Documents null contracts in method signatures - Zero runtime overhead (provided scope) Key annotations: - @nonnull: Method parameters/return values that cannot be null - @nullable: Values that may be null (e.g., getApplicationInstance()) - Optional<T> always marked @nonnull (container is non-null) All 226 tests passing with null-safety annotations. Closes #332 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 0ef6361 commit c7eda98

7 files changed

Lines changed: 9272 additions & 23 deletions

File tree

‎platform-api/pom.xml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
<description>Public APIs for JPlatform - interfaces and contracts for applications and deployers</description>
1616

1717
<dependencies>
18-
<!-- No runtime dependencies - pure interfaces -->
18+
<!-- Null-safety annotations (compile-time only) -->
19+
<dependency>
20+
<groupId>org.checkerframework</groupId>
21+
<artifactId>checker-qual</artifactId>
22+
<scope>provided</scope>
23+
</dependency>
1924

2025
<!-- Test dependencies -->
2126
<dependency>

‎platform-api/src/main/java/org/flossware/platform/api/ApplicationContext.java‎

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import java.util.Map;
2222
import java.util.Optional;
2323

24+
import org.checkerframework.checker.nullness.qual.NonNull;
25+
import org.checkerframework.checker.nullness.qual.Nullable;
26+
2427
/**
2528
* Runtime context for an application running on the platform. Provides access to isolated resources
2629
* and optional platform features.
@@ -49,68 +52,68 @@ public interface ApplicationContext {
4952
*
5053
* @return the application ID
5154
*/
52-
String getApplicationId();
55+
@NonNull String getApplicationId();
5356

5457
/**
5558
* Returns the current lifecycle state of this application.
5659
*
5760
* @return the application state
5861
* @see ApplicationState
5962
*/
60-
ApplicationState getState();
63+
@NonNull ApplicationState getState();
6164

6265
/**
6366
* Returns the timestamp when this application was deployed.
6467
*
6568
* @return the deployment timestamp
6669
*/
67-
Instant getDeployedAt();
70+
@NonNull Instant getDeployedAt();
6871

6972
/**
7073
* Returns the isolated classloader for this application. All application classes are loaded
7174
* through this classloader for isolation.
7275
*
7376
* @return the application's classloader
7477
*/
75-
ClassLoader getClassLoader();
78+
@NonNull ClassLoader getClassLoader();
7679

7780
/**
7881
* Returns the dedicated thread pool for this application. Use this for concurrent execution to
7982
* maintain resource isolation.
8083
*
8184
* @return the application's thread pool
8285
*/
83-
ThreadPoolExecutor getThreadPool();
86+
@NonNull ThreadPoolExecutor getThreadPool();
8487

8588
/**
8689
* Returns the security policy for this application. Use this to check permissions before
8790
* performing privileged operations.
8891
*
8992
* @return the application's security policy
9093
*/
91-
SecurityPolicy getSecurityPolicy();
94+
@NonNull SecurityPolicy getSecurityPolicy();
9295

9396
/**
9497
* Returns the resource monitor tracking this application's resource usage. Provides CPU time,
9598
* memory usage, and thread count metrics.
9699
*
97100
* @return the application's resource monitor
98101
*/
99-
ResourceMonitor getResourceMonitor();
102+
@NonNull ResourceMonitor getResourceMonitor();
100103

101104
/**
102105
* Returns the message bus if messaging is enabled for this application.
103106
*
104107
* @return optional message bus, empty if messaging is not enabled
105108
*/
106-
Optional<MessageBus> getMessageBus();
109+
@NonNull Optional<MessageBus> getMessageBus();
107110

108111
/**
109112
* Returns the service registry if messaging is enabled for this application.
110113
*
111114
* @return optional service registry, empty if messaging is not enabled
112115
*/
113-
Optional<ServiceRegistry> getServiceRegistry();
116+
@NonNull Optional<ServiceRegistry> getServiceRegistry();
114117

115118
/**
116119
* Returns the volume manager if volumes are defined for this application. Provides access to
@@ -119,19 +122,19 @@ public interface ApplicationContext {
119122
* @return optional volume manager, empty if no volumes are defined
120123
* @since 2.0
121124
*/
122-
Optional<VolumeManager> getVolumeManager();
125+
@NonNull Optional<VolumeManager> getVolumeManager();
123126

124127
/**
125128
* Returns custom properties configured for this application.
126129
*
127130
* @return immutable map of application properties
128131
*/
129-
Map<String, String> getProperties();
132+
@NonNull Map<String, String> getProperties();
130133

131134
/**
132135
* Returns the application instance if it has been started.
133136
*
134137
* @return the application instance, or null if not yet started
135138
*/
136-
Object getApplicationInstance();
139+
@Nullable Object getApplicationInstance();
137140
}

‎platform-api/src/main/java/org/flossware/platform/api/ApplicationLifecycleListener.java‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package org.flossware.platform.api;
1919

20+
import org.checkerframework.checker.nullness.qual.NonNull;
21+
2022
/**
2123
* Observer interface for application lifecycle events.
2224
*
@@ -61,30 +63,30 @@ public interface ApplicationLifecycleListener {
6163
* @param applicationId the application identifier
6264
* @param descriptor the application descriptor containing configuration
6365
*/
64-
void onDeployed(String applicationId, ApplicationDescriptor descriptor);
66+
void onDeployed(@NonNull String applicationId, @NonNull ApplicationDescriptor descriptor);
6567

6668
/**
6769
* Called when an application transitions to RUNNING state.
6870
*
6971
* @param applicationId the application identifier
7072
*/
71-
void onStarted(String applicationId);
73+
void onStarted(@NonNull String applicationId);
7274

7375
/**
7476
* Called when an application transitions to STOPPED or FAILED state.
7577
*
7678
* @param applicationId the application identifier
7779
* @param exitCode the exit code (0 for normal shutdown, non-zero for errors)
7880
*/
79-
void onStopped(String applicationId, int exitCode);
81+
void onStopped(@NonNull String applicationId, int exitCode);
8082

8183
/**
8284
* Called when an application is automatically restarted by the RestartManager.
8385
*
8486
* @param applicationId the application identifier
8587
* @param attemptNumber the restart attempt number (1-based)
8688
*/
87-
void onRestarted(String applicationId, int attemptNumber);
89+
void onRestarted(@NonNull String applicationId, int attemptNumber);
8890

8991
/**
9092
* Called when an application's health status changes.
@@ -95,7 +97,10 @@ public interface ApplicationLifecycleListener {
9597
* @param oldStatus the previous health status
9698
* @param newStatus the new health status
9799
*/
98-
void onHealthChanged(String applicationId, HealthStatus oldStatus, HealthStatus newStatus);
100+
void onHealthChanged(
101+
@NonNull String applicationId,
102+
@NonNull HealthStatus oldStatus,
103+
@NonNull HealthStatus newStatus);
99104

100105
/**
101106
* Called when an application is undeployed from the platform.
@@ -104,5 +109,5 @@ public interface ApplicationLifecycleListener {
104109
*
105110
* @param applicationId the application identifier
106111
*/
107-
void onUndeployed(String applicationId);
112+
void onUndeployed(@NonNull String applicationId);
108113
}

‎platform-api/src/main/java/org/flossware/platform/api/ServiceRegistry.java‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.util.List;
2121
import java.util.Optional;
2222

23+
import org.checkerframework.checker.nullness.qual.NonNull;
24+
2325
/**
2426
* Service registry for inter-application service discovery. Allows applications to register
2527
* services and look up services provided by other applications.
@@ -50,7 +52,7 @@ public interface ServiceRegistry {
5052
* @throws IllegalArgumentException if serviceInterface is not an interface or implementation does
5153
* not implement the interface
5254
*/
53-
<T> void registerService(Class<T> serviceInterface, T implementation);
55+
<T> void registerService(@NonNull Class<T> serviceInterface, @NonNull T implementation);
5456

5557
/**
5658
* Returns the first registered service for the specified interface. If multiple services are
@@ -60,7 +62,7 @@ public interface ServiceRegistry {
6062
* @param serviceInterface the interface class
6163
* @return optional containing the service, or empty if none found
6264
*/
63-
<T> Optional<T> getService(Class<T> serviceInterface);
65+
@NonNull <T> Optional<T> getService(@NonNull Class<T> serviceInterface);
6466

6567
/**
6668
* Returns all registered services for the specified interface.
@@ -69,13 +71,13 @@ public interface ServiceRegistry {
6971
* @param serviceInterface the interface class
7072
* @return list of all registered services, empty if none found
7173
*/
72-
<T> List<T> getAllServices(Class<T> serviceInterface);
74+
@NonNull <T> List<T> getAllServices(@NonNull Class<T> serviceInterface);
7375

7476
/**
7577
* Unregisters a specific service implementation.
7678
*
7779
* @param serviceInterface the interface class
7880
* @param implementation the service implementation to remove
7981
*/
80-
void unregisterService(Class<?> serviceInterface, Object implementation);
82+
void unregisterService(@NonNull Class<?> serviceInterface, @NonNull Object implementation);
8183
}

0 commit comments

Comments
 (0)