This is an automated email from the ASF dual-hosted git repository.

epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-mcp.git


The following commit(s) were added to refs/heads/main by this push:
     new a84033b  feat(jspecify): complete the @NullMarked opt-in for test 
packages (#179)
a84033b is described below

commit a84033b00cba6d0e8a9420bb4033499f48a75734
Author: Aditya Parikh <[email protected]>
AuthorDate: Tue Aug 18 18:02:55 2026 -0400

    feat(jspecify): complete the @NullMarked opt-in for test packages (#179)
    
    * chore(jspecify): roll @NullMarked out to all sub-packages
    
    Background: prior to this change only the root package
    `org.apache.solr.mcp.server` was @NullMarked via package-info.java. All
    sub-packages — `.collection`, `.config`, `.indexing`,
    `.indexing.documentcreator`, `.metadata`, `.search`, `.security`,
    `.util`, plus the test-only `.containerization` and `.observability` —
    were running unannotated, so NullAway (`OnlyNullMarked=true`) was
    silently skipping them.
    
    Changes:
    
    1. Adds `package-info.java` with `@NullMarked` to every sub-package (10
       files: 8 main + 2 test-only).
    
    2. Annotates production code with `@Nullable` where return types,
       parameters, or record components legitimately admit null. The
       non-obvious nullable surfaces:
       - `CollectionUtils.getLong/getFloat/getInteger` return null on missing
         or unparseable keys.
       - `CollectionService` cache/handler metrics methods return null when
         the underlying Solr endpoint is unavailable (graceful degradation
         by design).
       - `SolrMetrics.cacheStats` / `handlerStats`, `CacheStats.*`,
         `CacheInfo.*`, `HandlerStats.*`, `HandlerInfo.*`,
         `SolrHealthStatus.errorMessage` / `responseTime` / `totalDocuments`
         / `solrVersion` / `status` — all documented as nullable, now
         annotated.
       - `IndexStats.numDocs` / `segmentCount` — Luke can return either
         field as null.
       - Optional `@McpToolParam(required = false)` parameters on
         `CollectionService.createCollection` and `SearchService.search`.
       - `JsonResponseParser.convertValue` — JSON null inputs.
    
    3. `HttpSecurityConfiguration` Spring `@Value` fields initialised with
       defaults (`""` for `issuerUrl` matching the property default,
       `List.of()` for `allowedOrigins`) so the analyser can see they are
       always non-null after construction.
    
    4. NullAway is explicitly disabled on `compileTestJava` (with an
       explanatory comment). The @NullMarked rollout exposes ~30 test sites
       that unbox or dereference values now declared @Nullable in
       production (Map.get returns, metric fields that are null when an
       endpoint is unavailable, etc.). Each can be tightened by extracting
       to a local + `assertNotNull`, but the volume makes it a deliberate
       follow-up. Production is fully enforced.
    
    Build verified green (compile + unit + integration).
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    Signed-off-by: adityamparikh <[email protected]>
    
    * refactor(jspecify): drop unnecessary @Nullable on extractCacheStats
    
    The method unconditionally returns `new CacheStats(...)`; null-wrapping
    happens one level up in `fetchCacheMetrics` via the `isCacheStatsEmpty`
    check. The @Nullable was misleading — readers expect a method marked
    @Nullable to actually have a `return null` path.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    Signed-off-by: adityamparikh <[email protected]>
    
    * chore(jspecify): complete the @NullMarked opt-in for test packages
    
    @NullMarked on a package-info.java applies to that package only - Java
    packages are not hierarchical for annotation purposes. Combined with
    NullAway:OnlyNullMarked=true, that means an unmarked package is exempt from
    nullness checking even though NullAway is configured at error level.
    
    #133 marked every main package and two test packages (containerization,
    observability). This adds the six that were still unmarked, so every main
    and test package is now null-marked and the opt-in is uniform.
    
    NullAway remains disabled on compileTestJava, so this is declarative for
    now. Enabling it surfaces 48 test sites (the note in build.gradle.kts
    estimates ~30); that is left as a follow-up rather than folded in here.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
    Signed-off-by: Aditya Parikh <[email protected]>
    
    ---------
    
    Signed-off-by: adityamparikh <[email protected]>
    Signed-off-by: Aditya Parikh <[email protected]>
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
    Co-authored-by: Eric Pugh <[email protected]>
---
 build.gradle.kts                                   | 11 +++++
 .../mcp/server/collection/CollectionService.java   | 28 +++++++------
 .../mcp/server/collection/CollectionUtils.java     |  7 ++--
 .../apache/solr/mcp/server/collection/Dtos.java    | 49 +++++++++++-----------
 .../solr/mcp/server/collection/package-info.java   | 20 +++++++++
 .../solr/mcp/server/config/JsonResponseParser.java |  3 +-
 .../solr/mcp/server/config/package-info.java       | 20 +++++++++
 .../indexing/documentcreator/package-info.java     | 20 +++++++++
 .../solr/mcp/server/indexing/package-info.java     | 20 +++++++++
 .../solr/mcp/server/schema/package-info.java       | 20 +++++++++
 .../solr/mcp/server/search/SearchService.java      | 15 ++++---
 .../solr/mcp/server/search/package-info.java       | 20 +++++++++
 .../server/security/HttpSecurityConfiguration.java |  4 +-
 .../solr/mcp/server/security/package-info.java     | 20 +++++++++
 .../apache/solr/mcp/server/util/package-info.java  | 20 +++++++++
 .../solr/mcp/server/collection/package-info.java   | 20 +++++++++
 .../solr/mcp/server/config/package-info.java       | 20 +++++++++
 .../mcp/server/containerization/package-info.java  | 20 +++++++++
 .../solr/mcp/server/indexing/package-info.java     | 20 +++++++++
 .../mcp/server/observability/package-info.java     | 20 +++++++++
 .../org/apache/solr/mcp/server/package-info.java   | 20 +++++++++
 .../solr/mcp/server/schema/package-info.java       | 20 +++++++++
 .../solr/mcp/server/search/package-info.java       | 20 +++++++++
 23 files changed, 389 insertions(+), 48 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index f1df742..6a846c9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -289,10 +289,21 @@ tasks.withType<JavaCompile>().configureEach {
     options.errorprone {
         disableAllChecks.set(true) // Other error prone checks are disabled
         option("NullAway:OnlyNullMarked", "true") // Enable nullness checks 
only in null-marked code
+        option("NullAway:HandleTestAssertionLibraries", "true") // Teach 
NullAway that JUnit assertNotNull narrows nullness
         error("NullAway") // bump checks from warnings (default) to errors
     }
 }
 
+// NullAway is currently disabled on test compilation. The rollout of 
@NullMarked
+// to all sub-packages reveals many test sites that unbox / dereference a value
+// declared as @Nullable in production code (e.g. metrics fields that are null
+// when a Solr endpoint is unavailable). Each of those sites can be tightened 
by
+// extracting a local + assertNotNull, but the volume (~30 sites) makes that a
+// follow-up. Production code is fully enforced.
+tasks.named<JavaCompile>("compileTestJava") {
+    options.errorprone.disable("NullAway")
+}
+
 tasks.build {
     dependsOn(tasks.spotlessApply)
 }
diff --git 
a/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java 
b/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java
index 48c69b4..011d278 100644
--- a/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java
+++ b/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java
@@ -44,6 +44,7 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.mcp.server.config.SolrConfigurationProperties;
 import org.apache.solr.mcp.server.util.PromptNames;
+import org.jspecify.annotations.Nullable;
 import org.springaicommunity.mcp.annotation.McpArg;
 import org.springaicommunity.mcp.annotation.McpComplete;
 import org.springaicommunity.mcp.annotation.McpPrompt;
@@ -668,7 +669,7 @@ public class CollectionService {
         * @see #extractCacheStats(NamedList)
         * @see #isCacheStatsEmpty(CacheStats)
         */
-       public CacheStats getCacheMetrics(String collection) throws 
SolrServerException, IOException {
+       public @Nullable CacheStats getCacheMetrics(String collection) throws 
SolrServerException, IOException {
                String actualCollection = extractCollectionName(collection);
 
                if (!validateCollectionExists(actualCollection)) {
@@ -682,7 +683,7 @@ public class CollectionService {
         * Internal cache metrics fetch that assumes the collection has already 
been
         * validated and the name has been extracted from any shard identifier.
         */
-       private CacheStats fetchCacheMetrics(String collection) {
+       private @Nullable CacheStats fetchCacheMetrics(String collection) {
                try {
                        NamedList<Object> coreMetrics = 
fetchMetrics(collection, CACHE_METRIC_PREFIX);
                        if (coreMetrics == null) {
@@ -708,7 +709,7 @@ public class CollectionService {
         *            the cache statistics to evaluate
         * @return true if the stats are null or all cache types are null
         */
-       private boolean isCacheStatsEmpty(CacheStats stats) {
+       private boolean isCacheStatsEmpty(@Nullable CacheStats stats) {
                return stats == null
                                || (stats.queryResultCache() == null && 
stats.documentCache() == null && stats.filterCache() == null);
        }
@@ -727,7 +728,7 @@ public class CollectionService {
        }
 
        @SuppressWarnings("unchecked")
-       private CacheInfo extractSingleCacheInfo(NamedList<Object> coreMetrics, 
String key) {
+       private @Nullable CacheInfo extractSingleCacheInfo(NamedList<Object> 
coreMetrics, String key) {
                NamedList<Object> cache = (NamedList<Object>) 
coreMetrics.get(key);
                if (cache == null) {
                        return null;
@@ -784,7 +785,7 @@ public class CollectionService {
         * @see #fetchFlatHandlerInfo(String, String, String)
         * @see #isHandlerStatsEmpty(HandlerStats)
         */
-       public HandlerStats getHandlerMetrics(String collection) throws 
SolrServerException, IOException {
+       public @Nullable HandlerStats getHandlerMetrics(String collection) 
throws SolrServerException, IOException {
                String actualCollection = extractCollectionName(collection);
 
                if (!validateCollectionExists(actualCollection)) {
@@ -798,7 +799,7 @@ public class CollectionService {
         * Internal handler metrics fetch that assumes the collection has 
already been
         * validated and the name has been extracted from any shard identifier.
         */
-       private HandlerStats fetchHandlerMetrics(String collection) {
+       private @Nullable HandlerStats fetchHandlerMetrics(String collection) {
                try {
                        // Handler metrics are flat keys (e.g. 
QUERY./select.requests) so we
                        // fetch each handler prefix separately and reconstruct 
HandlerInfo
@@ -840,7 +841,8 @@ public class CollectionService {
         * @return the core-level metrics NamedList, or null if unavailable
         */
        @SuppressWarnings("unchecked")
-       private NamedList<Object> fetchMetrics(String collection, String 
prefix) throws SolrServerException, IOException {
+       private @Nullable NamedList<Object> fetchMetrics(String collection, 
String prefix)
+                       throws SolrServerException, IOException {
                ModifiableSolrParams params = new ModifiableSolrParams();
                params.set(GROUP_PARAM, CORE_GROUP);
                params.set(PREFIX_PARAM, prefix);
@@ -885,7 +887,7 @@ public class CollectionService {
         *            {@code QUERY./select.})
         * @return HandlerInfo with stats, or null if unavailable
         */
-       private HandlerInfo fetchFlatHandlerInfo(String collection, String 
metricPrefix, String keyPrefix)
+       private @Nullable HandlerInfo fetchFlatHandlerInfo(String collection, 
String metricPrefix, String keyPrefix)
                        throws SolrServerException, IOException {
                NamedList<Object> coreMetrics = fetchMetrics(collection, 
metricPrefix);
                if (coreMetrics == null) {
@@ -905,7 +907,7 @@ public class CollectionService {
         * @return HandlerInfo reconstructed from flat keys, or null if no 
requests key
         *         found
         */
-       private HandlerInfo extractFlatHandlerInfo(NamedList<Object> 
coreMetrics, String keyPrefix) {
+       private @Nullable HandlerInfo extractFlatHandlerInfo(NamedList<Object> 
coreMetrics, String keyPrefix) {
                Long requests = getLong(coreMetrics, keyPrefix + 
REQUESTS_FIELD);
                if (requests == null) {
                        return null;
@@ -1122,13 +1124,15 @@ public class CollectionService {
                                        + "configSet defaults to _default, 
numShards and replicationFactor default to 1.")
        public CollectionCreationResult createCollection(
                        @McpToolParam(description = "Name of the collection to 
create") String name,
-                       @McpToolParam(description = "Configset name. Defaults 
to _default.", required = false) String configSet,
+                       @McpToolParam(
+                                       description = "Configset name. Defaults 
to _default.",
+                                       required = false) @Nullable String 
configSet,
                        @McpToolParam(
                                        description = "Number of shards 
(SolrCloud only). Defaults to 1.",
-                                       required = false) Integer numShards,
+                                       required = false) @Nullable Integer 
numShards,
                        @McpToolParam(
                                        description = "Replication factor 
(SolrCloud only). Defaults to 1.",
-                                       required = false) Integer 
replicationFactor)
+                                       required = false) @Nullable Integer 
replicationFactor)
                        throws SolrServerException, IOException {
 
                if (name == null || name.isBlank()) {
diff --git 
a/src/main/java/org/apache/solr/mcp/server/collection/CollectionUtils.java 
b/src/main/java/org/apache/solr/mcp/server/collection/CollectionUtils.java
index f64e878..a1ece62 100644
--- a/src/main/java/org/apache/solr/mcp/server/collection/CollectionUtils.java
+++ b/src/main/java/org/apache/solr/mcp/server/collection/CollectionUtils.java
@@ -17,6 +17,7 @@
 package org.apache.solr.mcp.server.collection;
 
 import org.apache.solr.common.util.NamedList;
+import org.jspecify.annotations.Nullable;
 
 /**
  * Utility class providing type-safe helper methods for extracting values from
@@ -113,7 +114,7 @@ public class CollectionUtils {
         * @see Number#longValue()
         * @see Long#parseLong(String)
         */
-       public static Long getLong(NamedList<Object> response, String key) {
+       public static @Nullable Long getLong(NamedList<Object> response, String 
key) {
                Object value = response.get(key);
                if (value == null)
                        return null;
@@ -172,7 +173,7 @@ public class CollectionUtils {
         * @return the Float value if found and convertible, {@code null} 
otherwise
         * @see Number#floatValue()
         */
-       public static Float getFloat(NamedList<Object> stats, String key) {
+       public static @Nullable Float getFloat(NamedList<Object> stats, String 
key) {
                Object value = stats.get(key);
                if (value == null)
                        return null;
@@ -252,7 +253,7 @@ public class CollectionUtils {
         * @see Integer#parseInt(String)
         * @see #getLong(NamedList, String)
         */
-       public static Integer getInteger(NamedList<Object> response, String 
key) {
+       public static @Nullable Integer getInteger(NamedList<Object> response, 
String key) {
                Object value = response.get(key);
                if (value == null)
                        return null;
diff --git a/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java 
b/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java
index e5ab3f2..2df8568 100644
--- a/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java
+++ b/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import java.time.Instant;
+import org.jspecify.annotations.Nullable;
 
 /**
  * Data Transfer Objects (DTOs) for the Apache Solr MCP Server.
@@ -95,13 +96,13 @@ record SolrMetrics(
                 * Cache utilization statistics for query result, document, and 
filter caches
                 * (may be null)
                 */
-               CacheStats cacheStats,
+               @Nullable CacheStats cacheStats,
 
                /**
                 * Request handler performance metrics for select and update 
operations (may be
                 * null)
                 */
-               HandlerStats handlerStats,
+               @Nullable HandlerStats handlerStats,
 
                /** Timestamp when these metrics were collected, formatted as 
ISO 8601 */
                @JsonFormat(shape = JsonFormat.Shape.STRING) Instant timestamp) 
{
@@ -139,13 +140,13 @@ record SolrMetrics(
 @JsonInclude(JsonInclude.Include.NON_NULL)
 record IndexStats(
                /** Total number of documents in the index (excluding deleted 
documents) */
-               Integer numDocs,
+               @Nullable Integer numDocs,
 
                /**
                 * Number of Lucene segments in the index (lower numbers 
generally indicate
                 * better performance)
                 */
-               Integer segmentCount) {
+               @Nullable Integer segmentCount) {
 }
 
 /**
@@ -223,13 +224,13 @@ record QueryStats(
 @JsonInclude(JsonInclude.Include.NON_NULL)
 record CacheStats(
                /** Performance metrics for the query result cache */
-               CacheInfo queryResultCache,
+               @Nullable CacheInfo queryResultCache,
 
                /** Performance metrics for the document cache */
-               CacheInfo documentCache,
+               @Nullable CacheInfo documentCache,
 
                /** Performance metrics for the filter cache */
-               CacheInfo filterCache) {
+               @Nullable CacheInfo filterCache) {
 }
 
 /**
@@ -262,28 +263,28 @@ record CacheStats(
 @JsonInclude(JsonInclude.Include.NON_NULL)
 record CacheInfo(
                /** Total number of cache lookup requests */
-               Long lookups,
+               @Nullable Long lookups,
 
                /** Number of successful cache hits */
-               Long hits,
+               @Nullable Long hits,
 
                /**
                 * Cache hit ratio (hits/lookups) - higher values indicate 
better cache
                 * performance
                 */
-               Float hitratio,
+               @Nullable Float hitratio,
 
                /** Number of new entries added to the cache */
-               Long inserts,
+               @Nullable Long inserts,
 
                /**
                 * Number of entries removed due to cache size limits 
(indicates memory
                 * pressure)
                 */
-               Long evictions,
+               @Nullable Long evictions,
 
                /** Current number of entries stored in the cache */
-               Long size) {
+               @Nullable Long size) {
 }
 
 /**
@@ -317,10 +318,10 @@ record CacheInfo(
 @JsonInclude(JsonInclude.Include.NON_NULL)
 record HandlerStats(
                /** Performance metrics for the search/select request handler */
-               HandlerInfo selectHandler,
+               @Nullable HandlerInfo selectHandler,
 
                /** Performance metrics for the document update request handler 
*/
-               HandlerInfo updateHandler) {
+               @Nullable HandlerInfo updateHandler) {
 }
 
 /**
@@ -352,22 +353,22 @@ record HandlerStats(
 @JsonInclude(JsonInclude.Include.NON_NULL)
 record HandlerInfo(
                /** Total number of requests processed by this handler */
-               Long requests,
+               @Nullable Long requests,
 
                /** Number of requests that resulted in errors */
-               Long errors,
+               @Nullable Long errors,
 
                /** Number of requests that exceeded timeout limits */
-               Long timeouts,
+               @Nullable Long timeouts,
 
                /** Cumulative time spent processing all requests 
(milliseconds) */
-               Long totalTime,
+               @Nullable Long totalTime,
 
                /** Average time per request in milliseconds */
-               Float avgTimePerRequest,
+               @Nullable Float avgTimePerRequest,
 
                /** Average throughput in requests per second */
-               Float avgRequestsPerSecond) {
+               @Nullable Float avgRequestsPerSecond) {
 }
 
 /**
@@ -412,13 +413,13 @@ record SolrHealthStatus(
                boolean isHealthy,
 
                /** Detailed error message when isHealthy is false, null when 
healthy */
-               String errorMessage,
+               @Nullable String errorMessage,
 
                /** Response time in milliseconds for the health check ping 
request */
-               Long responseTime,
+               @Nullable Long responseTime,
 
                /** Total number of documents currently indexed in the 
collection */
-               Long totalDocuments,
+               @Nullable Long totalDocuments,
 
                /** Timestamp when this health check was performed, formatted 
as ISO 8601 */
                @JsonFormat(shape = JsonFormat.Shape.STRING) Instant 
lastChecked,
diff --git 
a/src/main/java/org/apache/solr/mcp/server/collection/package-info.java 
b/src/main/java/org/apache/solr/mcp/server/collection/package-info.java
new file mode 100644
index 0000000..6c8a68a
--- /dev/null
+++ b/src/main/java/org/apache/solr/mcp/server/collection/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.collection;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/main/java/org/apache/solr/mcp/server/config/JsonResponseParser.java 
b/src/main/java/org/apache/solr/mcp/server/config/JsonResponseParser.java
index 235b57a..545d5e8 100644
--- a/src/main/java/org/apache/solr/mcp/server/config/JsonResponseParser.java
+++ b/src/main/java/org/apache/solr/mcp/server/config/JsonResponseParser.java
@@ -29,6 +29,7 @@ import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
+import org.jspecify.annotations.Nullable;
 import org.springframework.http.MediaType;
 
 /**
@@ -102,7 +103,7 @@ class JsonResponseParser extends ResponseParser {
                return result;
        }
 
-       private Object convertValue(JsonNode node) {
+       private @Nullable Object convertValue(JsonNode node) {
                if (node.isNull())
                        return null;
                if (node.isBoolean())
diff --git a/src/main/java/org/apache/solr/mcp/server/config/package-info.java 
b/src/main/java/org/apache/solr/mcp/server/config/package-info.java
new file mode 100644
index 0000000..a2951a6
--- /dev/null
+++ b/src/main/java/org/apache/solr/mcp/server/config/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.config;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/main/java/org/apache/solr/mcp/server/indexing/documentcreator/package-info.java
 
b/src/main/java/org/apache/solr/mcp/server/indexing/documentcreator/package-info.java
new file mode 100644
index 0000000..60983ee
--- /dev/null
+++ 
b/src/main/java/org/apache/solr/mcp/server/indexing/documentcreator/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.indexing.documentcreator;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/main/java/org/apache/solr/mcp/server/indexing/package-info.java 
b/src/main/java/org/apache/solr/mcp/server/indexing/package-info.java
new file mode 100644
index 0000000..b89126a
--- /dev/null
+++ b/src/main/java/org/apache/solr/mcp/server/indexing/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.indexing;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/main/java/org/apache/solr/mcp/server/schema/package-info.java 
b/src/main/java/org/apache/solr/mcp/server/schema/package-info.java
new file mode 100644
index 0000000..dde06d6
--- /dev/null
+++ b/src/main/java/org/apache/solr/mcp/server/schema/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.schema;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/main/java/org/apache/solr/mcp/server/search/SearchService.java 
b/src/main/java/org/apache/solr/mcp/server/search/SearchService.java
index 57eaa6c..cff5168 100644
--- a/src/main/java/org/apache/solr/mcp/server/search/SearchService.java
+++ b/src/main/java/org/apache/solr/mcp/server/search/SearchService.java
@@ -33,6 +33,7 @@ import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.FacetParams;
 import org.apache.solr.mcp.server.util.PromptNames;
+import org.jspecify.annotations.Nullable;
 import org.springaicommunity.mcp.annotation.McpArg;
 import org.springaicommunity.mcp.annotation.McpPrompt;
 import org.springaicommunity.mcp.annotation.McpTool;
@@ -296,14 +297,16 @@ public class SearchService {
                        @McpToolParam(
                                        description = "Solr q parameter. Lucene 
syntax; supports local params such as"
                                                        + " {!edismax qf='name 
author'}. If none specified defaults to \"*:*\"",
-                                       required = false) String query,
+                                       required = false) @Nullable String 
query,
                        @McpToolParam(
                                        description = "Solr fq parameter: list 
of filter queries, one filter per entry",
-                                       required = false) List<String> 
filterQueries,
-                       @McpToolParam(description = "Solr facet fields", 
required = false) List<String> facetFields,
-                       @McpToolParam(description = "Solr sort parameter", 
required = false) List<Map<String, String>> sortClauses,
-                       @McpToolParam(description = "Starting offset for 
pagination", required = false) Integer start,
-                       @McpToolParam(description = "Number of rows to return", 
required = false) Integer rows)
+                                       required = false) @Nullable 
List<String> filterQueries,
+                       @McpToolParam(description = "Solr facet fields", 
required = false) @Nullable List<String> facetFields,
+                       @McpToolParam(
+                                       description = "Solr sort parameter",
+                                       required = false) @Nullable 
List<Map<String, String>> sortClauses,
+                       @McpToolParam(description = "Starting offset for 
pagination", required = false) @Nullable Integer start,
+                       @McpToolParam(description = "Number of rows to return", 
required = false) @Nullable Integer rows)
                        throws SolrServerException, IOException {
 
                // query
diff --git a/src/main/java/org/apache/solr/mcp/server/search/package-info.java 
b/src/main/java/org/apache/solr/mcp/server/search/package-info.java
new file mode 100644
index 0000000..08a3041
--- /dev/null
+++ b/src/main/java/org/apache/solr/mcp/server/search/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.search;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java
 
b/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java
index a8f0905..b0ab728 100644
--- 
a/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java
+++ 
b/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java
@@ -38,10 +38,10 @@ import 
org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 class HttpSecurityConfiguration {
 
        @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri:}")
-       private String issuerUrl;
+       private String issuerUrl = "";
 
        @Value("${mcp.cors.allowed-origins}")
-       private List<String> allowedOrigins;
+       private List<String> allowedOrigins = List.of();
 
        @Bean
        @ConditionalOnProperty(name = "http.security.enabled", havingValue = 
"true", matchIfMissing = true)
diff --git 
a/src/main/java/org/apache/solr/mcp/server/security/package-info.java 
b/src/main/java/org/apache/solr/mcp/server/security/package-info.java
new file mode 100644
index 0000000..088cb55
--- /dev/null
+++ b/src/main/java/org/apache/solr/mcp/server/security/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.security;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/main/java/org/apache/solr/mcp/server/util/package-info.java 
b/src/main/java/org/apache/solr/mcp/server/util/package-info.java
new file mode 100644
index 0000000..614f24c
--- /dev/null
+++ b/src/main/java/org/apache/solr/mcp/server/util/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.util;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/test/java/org/apache/solr/mcp/server/collection/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/collection/package-info.java
new file mode 100644
index 0000000..6c8a68a
--- /dev/null
+++ b/src/test/java/org/apache/solr/mcp/server/collection/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.collection;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/test/java/org/apache/solr/mcp/server/config/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/config/package-info.java
new file mode 100644
index 0000000..a2951a6
--- /dev/null
+++ b/src/test/java/org/apache/solr/mcp/server/config/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.config;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/test/java/org/apache/solr/mcp/server/containerization/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/containerization/package-info.java
new file mode 100644
index 0000000..b30fa1e
--- /dev/null
+++ 
b/src/test/java/org/apache/solr/mcp/server/containerization/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.containerization;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/test/java/org/apache/solr/mcp/server/indexing/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/indexing/package-info.java
new file mode 100644
index 0000000..b89126a
--- /dev/null
+++ b/src/test/java/org/apache/solr/mcp/server/indexing/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.indexing;
+
+import org.jspecify.annotations.NullMarked;
diff --git 
a/src/test/java/org/apache/solr/mcp/server/observability/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/observability/package-info.java
new file mode 100644
index 0000000..5405596
--- /dev/null
+++ b/src/test/java/org/apache/solr/mcp/server/observability/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.observability;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/test/java/org/apache/solr/mcp/server/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/package-info.java
new file mode 100644
index 0000000..0ff54ed
--- /dev/null
+++ b/src/test/java/org/apache/solr/mcp/server/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/test/java/org/apache/solr/mcp/server/schema/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/schema/package-info.java
new file mode 100644
index 0000000..dde06d6
--- /dev/null
+++ b/src/test/java/org/apache/solr/mcp/server/schema/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.schema;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/test/java/org/apache/solr/mcp/server/search/package-info.java 
b/src/test/java/org/apache/solr/mcp/server/search/package-info.java
new file mode 100644
index 0000000..08a3041
--- /dev/null
+++ b/src/test/java/org/apache/solr/mcp/server/search/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@NullMarked
+package org.apache.solr.mcp.server.search;
+
+import org.jspecify.annotations.NullMarked;

Reply via email to