You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@solr.apache.org by GitBox <gi...@apache.org> on 2022/08/17 17:55:05 UTC

[GitHub] [solr] gerlowskija opened a new pull request, #975: Allow JAX-RS v2 API definition

gerlowskija opened a new pull request, #975:
URL: https://github.com/apache/solr/pull/975

   # Description
   
   Currently, v2 APIs are defined using a "homegrown" annotation-based framework.  Generally speaking, this works well.  But there are a few downsides:
   
   1. The Solr community must maintain our API framework, in addition to the APIs themselves.
   2. Our framework is less feature-rich than some off-the-shelf alternatives.
   3. Our framework lacks the integrations and tooling that some off-the-shelf alternatives offer, such as the OpenAPI support offered by libraries like `swagger-core`.
   
   # Solution
   
   This draft PR adds a Jersey integration to Solr.  v2 APIs can now be defined using standard JAX-RS annotations.  These APIs are then looked up and executed using the Jersey "ApplicationHandler" class.  (This class serves as a near-parallel to the existing v2 framework's `ApiBag` abstraction.)
   
   The draft PR currently supports:
   
   - loading of both "admin"/core-container APIs, as well as core/collection-level APIs.
   - use of Solr authentication/authorization plugins (using Jersey's ContainerRequestFilter interface)
   - API responses in JSON and (experimentally) javabin.
   
   An example v2 API (ListConfigSetsAPI) has also been converted to JAX-RS to serve as an example.
   
   The functionality offered in this PR is by no means complete.  It's intended only to serve as a starting point and show the overall shape and complexity of a potential integration. 
   
   # Tests
   
   N/A - not fully tested.
   
   # Checklist
   
   Please review the following and check all that apply:
   
   - [x] I have reviewed the guidelines for [How to Contribute](https://wiki.apache.org/solr/HowToContribute) and my code conforms to the standards described there to the best of my ability.
   - [ ] I have created a Jira issue and added the issue ID to my pull request title.
   - [x] I have given Solr maintainers [access](https://help.github.com/en/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork) to contribute to my PR branch. (optional but recommended)
   - [x] I have developed this patch against the `main` branch.
   - [ ] I have run `./gradlew check`.
   - [ ] I have added tests for my changes.
   - [ ] I have added documentation for the [Reference Guide](https://github.com/apache/solr/tree/main/solr/solr-ref-guide)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r953816961


##########
solr/core/src/java/org/apache/solr/handler/api/SomeCoreResource.java:
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.api;
+
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.security.PermissionNameProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.lang.invoke.MethodHandles;
+
+@Path("/collections/{collectionName}/somecorepath")
+public class SomeCoreResource extends JerseyResource {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    @PermissionName(PermissionNameProvider.Name.READ_PERM)
+    public String helloPlainText(@PathParam("collectionName") String collectionName) {
+        log.info("Made it into SomeCoreResource.helloPlainText with collName {}", collectionName);

Review Comment:
   Agreed - wouldn't it flag most or all nontrivial log messages?
   
   Thanks David!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965335669


##########
solr/core/src/java/org/apache/solr/core/CoreContainer.java:
##########
@@ -16,12 +16,51 @@
  */
 package org.apache.solr.core;
 
+import static java.util.Objects.requireNonNull;

Review Comment:
   This is driving me nuts.  I'm not sure if it's just my editor settings but it seems like half the LOC in any given PR is just import reordering or changes.  I would've thought spotless would standardize this but apparently not?
   
   No reason we shouldn't have a standard here if we're already making people run spotless.  Not that I love spotless either, given how it's mangled every comment in this PR 😉  But at least it's something.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r969938336


##########
solr/solrj/src/java/org/apache/solr/common/util/Utils.java:
##########
@@ -916,7 +926,10 @@ public static void reflectWrite(
   }
 
   private static List<FieldWriter> getReflectData(

Review Comment:
   I'm slightly concerned about the perf overhead of hitting this on every single call to /select but we could optimize known cases at some point if it's a problem.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r969971947


##########
solr/solrj/src/java/org/apache/solr/common/util/Utils.java:
##########
@@ -916,7 +926,10 @@ public static void reflectWrite(
   }
 
   private static List<FieldWriter> getReflectData(

Review Comment:
   There'll definitely be some overhead, but it might be less than you imagine.  (Or at least, it was something I was much more worried about until I dug into things a bit more).
   
   In particular - once we compute the list of FieldWriter's for a particular class here, we cache it in a static map so we can skip all the reflection-y computation on subsequent calls.  That only caches the annotated fields (we can't cache the "unknown/additional properties" stuff as that could change request-to-request).  But it's still a huge drop in the number of reflection/introspection calls that happen on a per-request basis.  Which should help a good bit?
   
   Anyway, I do think we'll want to move away from this in the longer term.  As things are converted over to JAX-RS and we build a bigger and bigger library of strongly-typed response objects, maybe it'll become feasible to just rely on Jackson for conversion to all of our formats/media-types?  Jackson has deps you can add to handle common formats like XML, and allows extension that we could probably use to cover custom response formats like javabin if we want to.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r959811323


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   Currently, v1 APIs return `application/octet-stream`, so I thought about putting that here for the sake of consistency, but that felt too generic.
   
   I like your suggestion better Jan, will change.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r953832066


##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigSetsAPI.java:
##########
@@ -16,34 +16,54 @@
  */
 package org.apache.solr.handler.configsets;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
-
-import java.util.List;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.cloud.OverseerSolrResponse;
-import org.apache.solr.common.util.NamedList;
+import org.apache.solr.api.JerseyResource;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.jersey.PermissionName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
 
 /**
  * V2 API for adding or updating a single file within a configset.
  *
  * <p>This API (GET /v2/cluster/configs) is analogous to the v1 /admin/configs?action=LIST command.
  */
-public class ListConfigSetsAPI extends ConfigSetAPIBase {
+
+@Path("/cluster/configs")
+public class ListConfigSetsAPI extends JerseyResource {
+
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  @Context
+  public HttpHeaders headers;
+
+  private final CoreContainer coreContainer;
+
+  @Inject
   public ListConfigSetsAPI(CoreContainer coreContainer) {
-    super(coreContainer);
+    this.coreContainer = coreContainer;
   }
 
-  @EndPoint(method = GET, path = "/cluster/configs", permission = CONFIG_READ_PERM)
-  public void listConfigSet(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    final NamedList<Object> results = new NamedList<>();
-    List<String> configSetsList = configSetService.listConfigs();
-    results.add("configSets", configSetsList);
-    SolrResponse response = new OverseerSolrResponse(results);
-    rsp.getValues().addAll(response.getResponse());
+
+  @GET
+  @Produces({"application/json", "application/javabin"})
+  @PermissionName(CONFIG_READ_PERM)
+  public ListConfigsetsResponse listConfigSet() throws Exception {
+    log.info("CoreContainer={}, HttpHeaders.accept={}", coreContainer, (headers != null) ? headers.getAcceptableMediaTypes() : "null");

Review Comment:
   Agreed - this PR still has a lot of logging that I've added for myself as I'm working out some of the kinks, but that would have no place in the Solr codebase proper.  I'll try to get into the habit of using 'NOCOMMIT' to mark these messages, as you suggested elsewhere.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r958598470


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -362,14 +363,15 @@ private void invokeJerseyRequest(CoreContainer cores, SolrCore core, Application
 
       // Set properties that may be used by Jersey filters downstream
       containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
-      containerRequest.setProperty(SolrRequestAuthorizer.CORE_CONTAINER_PROP_NAME, cores);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_REQ_PROP_NAME, req);
-      containerRequest.setProperty(SolrRequestAuthorizer.REQUEST_TYPE_PROP_NAME, requestType);
-      containerRequest.setProperty(SolrRequestAuthorizer.SOLR_PARAMS_PROP_NAME, queryParams);
-      containerRequest.setProperty(SolrRequestAuthorizer.COLLECTION_LIST_PROP_NAME, collectionsList);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_RSP_PROP_NAME, response);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);

Review Comment:
   Personally I prefer the current, static-import syntax.  IMO fully qualifying every last constant adds "noise" without any extra "signal".  (Since it's trivial to lookup the origin of these constants in an IDE)
   
   But if you or anyone else feels differently I'm happy to change it. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on PR #975:
URL: https://github.com/apache/solr/pull/975#issuecomment-1241042225

   > Found a buried question from @dsmiley that I'd failed to answer:
   > 
   > > do you think your work here might be better characterized as a V3 API rather than changing V2? Of course we agreed to change V2 as we see fit but I'm just wondering if you are hampered by lots of code already existing for V2.
   > 
   > In some ways this work does _feel_ like a v3 effort. Particularly because we're integrating a new (to Solr) API framework. But from the user or API-consumer perspective I think this is "just" v2 hardening and refactoring. We're not introducing new APIs that will exist alongside their v2 counterparts, etc. So I personally tend to think of this work as "v2".
   > 
   > In terms of the development, the existing v2 code hasn't done too much "hampering". Of course, in terms of this specific PR, it's been a big pain to add JAX-RS support to V2HttpCall while still keeping the existing `Api` and introspect codepaths there working. But I don't see that being much of a problem on an api-by-api basis as we add new or convert existing endpoints over to JAX-RS.
   > 
   > > Lots of V2 classes could be marked Deprecated to communicate our intent to not take it into the future.
   > 
   > I'm all for deprecating some of the existing (but now legacy?) v2 framework, especially: `Api`, `ApiBag`, `ApiSupport`, `Command`, `PayloadObj`, `AnnotatedApi`, etc.
   > 
   > I'd probably wait on adding those deprecations until we have a bit more history converting things over to JAX-RS, but in a few month's time I'd love to push up a PR for that. I don't want to put the "cart before the horse" there though.
   
   I'll chime in a bit too...   We did decide to mark V2 API's as experimental, so that we could free ourselves up to change them ;-).    


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966044159


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   Ah, yeah, this comment got buried but it's been on my list, sorry!
   
   I'm 👍 on Jan's suggestion of `application/vnd.apache.solr.javabin`, I just need to implement it.  This will need changed both here, as well as in SolrJ so that it knows about the updated media-type value.  (There's not much v2 support in SolrJ, but you can manually construct your own request using the `V2Request` class)
   
   Starting in on that now; will confirm here when that's finished.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r950383999


##########
solr/core/src/java/org/apache/solr/jersey/CoreContainerApp.java:
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.configsets.ListConfigSetsAPI;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Singleton;
+import java.lang.invoke.MethodHandles;
+import java.util.Map;
+
+/**
+ * CoreContainer-level (i.e. ADMIN) Jersey API registration.
+ */
+public class CoreContainerApp extends ResourceConfig {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

Review Comment:
   *[UnusedVariable](https://errorprone.info/bugpattern/UnusedVariable):*  The field 'log' is never read.
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=318377112&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=318377112&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=318377112&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=318377112&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=318377112&lift_comment_rating=5) ]



##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -17,32 +17,51 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.security.PermissionNameProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import java.lang.invoke.MethodHandles;
 
 /**
  * V2 API for checking the name of an in-use schema.
  *
  * <p>This API (GET /v2/collections/collectionName/schema/name) is analogous to the v1
  * /solr/collectionName/schema/name API.
  */
-public class SchemaNameAPI {
-  private final SchemaHandler schemaHandler;
+@Path("/collections/{collectionName}/schema/name")
+public class SchemaNameAPI extends JerseyResource {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

Review Comment:
   *[UnusedVariable](https://errorprone.info/bugpattern/UnusedVariable):*  The field 'log' is never read.
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=318377111&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=318377111&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=318377111&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=318377111&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=318377111&lift_comment_rating=5) ]



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] janhoy commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
janhoy commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r959818403


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   My suggestion is based on the recommendation by IANA, see https://en.wikipedia.org/wiki/Media_type#Vendor_tree. Here are the apache specific `vnd` formats I could find at https://www.iana.org/assignments/media-types/media-types.xhtml:
   ```
   application/vnd.apache.arrow.file
   application/vnd.apache.arrow.stream
   application/vnd.apache.thrift.binary
   application/vnd.apache.thrift.compact
   ```
   So perhaps `application/vnd.apache.solr.javabin` is better.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r959835650


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -397,7 +399,7 @@ protected void handleAdmin(SolrQueryResponse solrResp) {
   @Override
   protected void executeCoreRequest(SolrQueryResponse rsp) {
     if (api == null) {
-      invokeJerseyRequest(cores, core, core.getApplicationHandler());
+      invokeJerseyRequest(cores, core, core.getApplicationHandler(), rsp);

Review Comment:
   I found myself confusing the names every time I came into this class.  I held off on renaming variables too much in fear of muddying the diff, but I'm happy to do it here if you think it'd help more than it hurts the review here?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r968926145


##########
solr/solrj/src/java/org/apache/solr/client/solrj/ResponseParser.java:
##########
@@ -34,11 +37,22 @@ public abstract class ResponseParser {
    * A well behaved ResponseParser will return its content-type.
    *
    * @return the content-type this parser expects to parse
+   * @deprecated use {@link #getContentTypes()} instead
    */
+  @Deprecated
   public String getContentType() {

Review Comment:
   @sonatype-lift exclude issue



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r962080721


##########
solr/core/src/java/org/apache/solr/core/SolrCore.java:
##########
@@ -184,7 +185,7 @@
  * to make it work. When multi-core support was added to Solr way back in version 1.3, this class
  * was required so that the core functionality could be re-used multiple times.
  */
-public final class SolrCore implements SolrInfoBean, Closeable {
+public class SolrCore implements SolrInfoBean, Closeable {

Review Comment:
   Why not final anymore?



##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigSetsAPI.java:
##########
@@ -16,34 +16,41 @@
  */
 package org.apache.solr.handler.configsets;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
 import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
 
-import java.util.List;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.cloud.OverseerSolrResponse;
-import org.apache.solr.common.util.NamedList;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import org.apache.solr.api.JerseyResource;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.jersey.PermissionName;
 
 /**
  * V2 API for adding or updating a single file within a configset.
  *
  * <p>This API (GET /v2/cluster/configs) is analogous to the v1 /admin/configs?action=LIST command.
  */
-public class ListConfigSetsAPI extends ConfigSetAPIBase {
+@Path("/cluster/configs")
+public class ListConfigSetsAPI extends JerseyResource {
+
+  @Context public HttpHeaders headers;
+
+  private final CoreContainer coreContainer;
+
+  @Inject
   public ListConfigSetsAPI(CoreContainer coreContainer) {
-    super(coreContainer);
+    this.coreContainer = coreContainer;
   }
 
-  @EndPoint(method = GET, path = "/cluster/configs", permission = CONFIG_READ_PERM)
-  public void listConfigSet(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    final NamedList<Object> results = new NamedList<>();
-    List<String> configSetsList = configSetService.listConfigs();
-    results.add("configSets", configSetsList);
-    SolrResponse response = new OverseerSolrResponse(results);
-    rsp.getValues().addAll(response.getResponse());
+  @GET
+  @Produces({"application/json", "application/javabin"})
+  @PermissionName(CONFIG_READ_PERM)
+  public ListConfigsetsResponse listConfigSet() throws Exception {
+    final ListConfigsetsResponse response = new ListConfigsetsResponse();
+    response.configSets = coreContainer.getConfigSetService().listConfigs();
+    return response;

Review Comment:
   Let's have ListConfigSetsResponse be immutable with a constructor.  



##########
solr/core/src/java/org/apache/solr/handler/api/V2ApiUtils.java:
##########
@@ -40,4 +44,41 @@ public static void flattenToCommaDelimitedString(
     final String flattenedStr = String.join(",", toFlatten);
     destination.put(newKey, flattenedStr);
   }
+
+  /**
+   * Convert a JacksonReflectMapWriter (typically a {@link
+   * org.apache.solr.jersey.SolrJerseyResponse}) into the NamedList on a SolrQueryResponse
+   *
+   * @param rsp the response to attach the resulting NamedList to
+   * @param mw the input object to be converted into a NamedList
+   * @param trimHeader should the 'responseHeader' portion of the response be added to the
+   *     NamedList, or should populating that header be left to code elsewhere. This value should
+   *     usually be 'false' when called from v2 code, and 'true' when called from v1 code.
+   */
+  public static void squashIntoSolrResponse(
+      SolrQueryResponse rsp, JacksonReflectMapWriter mw, boolean trimHeader) {
+    squashIntoNamedList(rsp.getValues(), mw, trimHeader);
+  }
+
+  public static void squashIntoSolrResponse(SolrQueryResponse rsp, JacksonReflectMapWriter mw) {
+    squashIntoSolrResponse(rsp, mw, false);
+  }
+
+  public static void squashIntoNamedList(
+      NamedList<Object> destination, JacksonReflectMapWriter mw) {
+    squashIntoNamedList(destination, mw, false);
+  }
+
+  // TODO Come up with a better approach (maybe change Responses to be based on some class that can
+  // natively do this
+  //  without the intermediate map(s)?)

Review Comment:
   I'll push a solution to this



##########
solr/core/src/java/org/apache/solr/api/JerseyResource.java:
##########
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.api;
+
+import org.apache.solr.jersey.CatchAllExceptionMapper;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.servlet.HttpSolrCall;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Context;
+import java.util.function.Supplier;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_JERSEY_RESPONSE_KEY;
+
+/**
+ * A marker parent type for all Jersey resource classes
+ */
+public class JerseyResource {
+
+    @Context
+    public ContainerRequestContext containerRequestContext;
+
+    /**
+     * Create an instance of the {@link SolrJerseyResponse} subclass; registering it with the Jersey request-context upon creation

Review Comment:
   nit: end the first sentence of any javadoc with a period. Really all sentences but especially the first as it acts as a summary.  Newlines are not honored in javadoc when rendered; so it's not a substitute for ending sentences with a period.



##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigsetsResponse.java:
##########
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import org.apache.solr.jersey.SolrJerseyResponse;
+
+/** Response body POJO for the {@link ListConfigSetsAPI} resource. */
+public class ListConfigsetsResponse extends SolrJerseyResponse {

Review Comment:
   Can we just make this a static inner class of the API that needs it?  And make Immutable



##########
solr/core/src/java/org/apache/solr/jersey/MessageBodyWriters.java:
##########
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_RESPONSE_KEY;
+import static org.apache.solr.response.QueryResponseWriter.CONTENT_TYPE_TEXT_UTF8;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.BinaryResponseWriter;
+import org.apache.solr.response.CSVResponseWriter;
+import org.apache.solr.response.QueryResponseWriter;
+import org.apache.solr.response.QueryResponseWriterUtil;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.response.XMLResponseWriter;
+
+/**
+ * A collection of thin Jersey shims around Solr's existing {@link QueryResponseWriter} interface
+ */
+public class MessageBodyWriters {
+
+  // Jersey has a default MessageBodyWriter for JSON so we don't need to declare one here
+  // Which other response-writer formats are worth carrying forward into v2?
+
+  @Produces(MediaType.APPLICATION_XML)
+  public static class XmlMessageBodyWriter extends BaseMessageBodyWriter
+      implements MessageBodyWriter<JacksonReflectMapWriter> {
+    @Override
+    public QueryResponseWriter createResponseWriter() {
+      return new XMLResponseWriter();
+    }
+
+    @Override
+    public String getSupportedMediaType() {
+      return MediaType.APPLICATION_XML;
+    }
+  }
+
+  @Produces("application/javabin")

Review Comment:
   Jan suggested changing this



##########
solr/core/src/test/org/apache/solr/handler/configsets/package-info.java:
##########
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** Testing for the org.apache.solr.handler.configsets package. */
+package org.apache.solr.handler.configsets;

Review Comment:
   I hope we don't make it mandatory to provide package-info.java for *tests*



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -362,14 +363,15 @@ private void invokeJerseyRequest(CoreContainer cores, SolrCore core, Application
 
       // Set properties that may be used by Jersey filters downstream
       containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
-      containerRequest.setProperty(SolrRequestAuthorizer.CORE_CONTAINER_PROP_NAME, cores);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_REQ_PROP_NAME, req);
-      containerRequest.setProperty(SolrRequestAuthorizer.REQUEST_TYPE_PROP_NAME, requestType);
-      containerRequest.setProperty(SolrRequestAuthorizer.SOLR_PARAMS_PROP_NAME, queryParams);
-      containerRequest.setProperty(SolrRequestAuthorizer.COLLECTION_LIST_PROP_NAME, collectionsList);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_RSP_PROP_NAME, response);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);

Review Comment:
   I agree; it's consistency.  FWIW I like the code being fully qualified because it shows where the constant is coming from.



##########
solr/core/src/java/org/apache/solr/core/CoreContainer.java:
##########
@@ -180,6 +185,17 @@ public CoreLoadFailure(CoreDescriptor cd, Exception loadFailure) {
   private volatile PluginBag<SolrRequestHandler> containerHandlers =
       new PluginBag<>(SolrRequestHandler.class, null);
 
+  private volatile ResourceConfig config;

Review Comment:
   Please name this variable `jerseyResourceConfig`.  



##########
solr/core/src/java/org/apache/solr/api/JerseyResource.java:
##########
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.api;
+
+import org.apache.solr.jersey.CatchAllExceptionMapper;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.servlet.HttpSolrCall;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Context;
+import java.util.function.Supplier;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_JERSEY_RESPONSE_KEY;
+
+/**
+ * A marker parent type for all Jersey resource classes
+ */
+public class JerseyResource {
+
+    @Context
+    public ContainerRequestContext containerRequestContext;
+
+    /**
+     * Create an instance of the {@link SolrJerseyResponse} subclass; registering it with the Jersey request-context upon creation
+     *
+     * This utility method primarily exists to allow Jersey resources to return error responses that match those
+     * returned by Solr's v1 APIs.
+     *
+     * When a severe-enough exception halts a v1 request, Solr generates a summary of the error and attaches it to the
+     * {@link org.apache.solr.response.SolrQueryResponse} given to the request handler.  This SolrQueryResponse may
+     * already hold some portion of the normal "success" response for that API.
+     *
+     * The JAX-RS framework isn't well suited to mimicking responses of this sort, as the "response" from a Jersey resource
+     * is its return value (instead of a passed-in value that gets modified).  This utility works around this limitation
+     * by attaching the eventual return value of a JerseyResource to the context associated with the Jersey
+     * request.  This allows partially-constructed responses to be accessed later in the case of an exception.
+     *
+     * In order to instantiate arbitrary SolrJerseyResponse subclasses, this utility uses reflection to find and invoke
+     * the first (no-arg) constructor for the specified type.  SolrJerseyResponse subclasses without a no-arg constructor
+     * can be instantiated and registered using {@link #instantiateJerseyResponse(Supplier)}
+     *
+     * @param clazz the SolrJerseyResponse class to instantiate and register
+     *
+     * @see CatchAllExceptionMapper
+     * @see HttpSolrCall#call()
+     */
+    @SuppressWarnings("unchecked")
+    protected <T extends SolrJerseyResponse> T instantiateJerseyResponse(Class<T> clazz) {
+        return instantiateJerseyResponse(() -> {
+            try {
+                return (T) clazz.getConstructors()[0].newInstance();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
+    }
+
+    /**
+     * Create an instance of the {@link SolrJerseyResponse} subclass; registering it with the Jersey request-context upon creation

Review Comment:
   Again; misses period.



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -388,33 +335,65 @@ public CompositeApi add(Api api) {
     }
   }
 
+  // We don't rely on any of Jersey's authc/z features so we pass in this empty context for
+  // all requests.
+  public static final SecurityContext DEFAULT_SECURITY_CONTEXT = new SecurityContext() {
+    public boolean isUserInRole(String role) { return false; }
+    public boolean isSecure() { return false; }
+    public Principal getUserPrincipal() { return null; }
+    public String getAuthenticationScheme() { return null; }
+  };
+
+  private void invokeJerseyRequest(CoreContainer cores, SolrCore core, ApplicationHandler jerseyHandler, SolrQueryResponse rsp) {
+    try {
+      final ContainerRequest containerRequest = ContainerRequestUtils.createContainerRequest(req, response, jerseyHandler.getConfiguration());
+
+      // Set properties that may be used by Jersey filters downstream
+      containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);
+      containerRequest.setProperty(RequestContextConstants.CORE_CONTAINER_KEY, cores);

Review Comment:
   `RequestContextConstants` holds nothing but "keys", so we don't need a suffix of `_KEY` on each one.



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -273,7 +278,7 @@ public static Api getApiInfo(
     }
 
     if (api == null) {
-      return getSubPathApi(requestHandlers, path, fullPath, new CompositeApi(null));

Review Comment:
   What became of this getSubPathApi?



##########
solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java:
##########
@@ -215,54 +215,59 @@ public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
         }
       }
     } catch (Exception e) {
-      if (req.getCore() != null) {
-        boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
-        if (isTragic) {
-          if (e instanceof SolrException) {
-            // Tragic exceptions should always throw a server error
-            assert ((SolrException) e).code() == 500;
-          } else {
-            // wrap it in a solr exception
-            e = new SolrException(SolrException.ErrorCode.SERVER_ERROR, e.getMessage(), e);
-          }
-        }
-      }
-      boolean incrementErrors = true;
-      boolean isServerError = true;
-      if (e instanceof SolrException) {
-        SolrException se = (SolrException) e;
-        if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
-          incrementErrors = false;
-        } else if (se.code() >= 400 && se.code() < 500) {
-          isServerError = false;
-        }
-      } else {
-        if (e instanceof SyntaxError) {
-          isServerError = false;
-          e = new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
-        }
-      }
-
+      e = normalizeReceivedException(req, e);
+      processErrorMetricsOnException(e, metrics);
       rsp.setException(e);
+    } finally {
+      long elapsed = timer.stop();
+      metrics.totalTime.inc(elapsed);
+    }
+  }
 
-      if (incrementErrors) {
-        SolrException.log(log, e);
+  public static void processErrorMetricsOnException(Exception e, HandlerMetrics metrics) {
+    boolean isClientError = false;
+    if (e instanceof SolrException) {
+      final SolrException se = (SolrException) e;
+      if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
+        return;
+      } else if (se.code() >= 400 && se.code() < 500) {
+        isClientError = true;
+      }
+    }
+
+    SolrException.log(log, e);
+    metrics.numErrors.mark();
+    if (isClientError) {
+      metrics.numClientErrors.mark();
+    } else {
+      metrics.numServerErrors.mark();
+    }
+  }
 
-        metrics.numErrors.mark();
-        if (isServerError) {
-          metrics.numServerErrors.mark();
+  public static Exception normalizeReceivedException(SolrQueryRequest req, Exception e) {
+    if (req.getCore() != null) {
+      assert req.getCoreContainer() != null;
+      boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
+      if (isTragic) {
+        if (e instanceof SolrException) {
+          // Tragic exceptions should always throw a server error
+          assert ((SolrException) e).code() == 500;

Review Comment:
   equals is too strict; I think >= 500 & < 600.



##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -192,6 +200,28 @@ public Category getCategory() {
     return Category.ADMIN;
   }
 
+  public Boolean registerV2() {
+    return true;
+  }
+
+  @Override
+  public Collection<Api> getApis() {
+    final List<Api> apis = new ArrayList<>();
+    apis.addAll(AnnotatedApi.getApis(new CreateConfigSetAPI(coreContainer)));
+    apis.addAll(AnnotatedApi.getApis(new DeleteConfigSetAPI(coreContainer)));
+    apis.addAll(AnnotatedApi.getApis(new UploadConfigSetAPI(coreContainer)));
+    apis.addAll(AnnotatedApi.getApis(new UploadConfigSetFileAPI(coreContainer)));
+
+    return apis;
+  }
+
+  @Override
+  public Collection<Class<? extends JerseyResource>> getJerseyResources() {

Review Comment:
   List.of



##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -213,6 +237,24 @@ public PluginHolder<T> put(String name, PluginHolder<T> plugin) {
                 apiBag.register(api, nameSubstitutes);
               }
             }
+
+            // TODO Should we use <requestHandler name="/blah"> to override the path that each
+            //  resource registers under?
+            Collection<Class<? extends JerseyResource>> jerseyApis =
+                apiSupport.getJerseyResources();
+            if (!CollectionUtils.isEmpty(jerseyApis)) {
+              for (Class<? extends JerseyResource> jerseyClazz : jerseyApis) {
+                if (log.isDebugEnabled()) {
+                  log.debug("Registering jersey resource class: {}", jerseyClazz.getName());
+                }
+                jerseyResources.register(jerseyClazz);
+                // See MetricsBeanFactory javadocs for a better understanding of this resource->RH
+                // mapping
+                if (inst instanceof RequestHandlerBase) {

Review Comment:
   This reference to RequestHandlerBase is a smell to me.  There is a typical general pattern where an interface exists (SolrRequestInfo) and a base implementation (RequestHandlerBase) that is an implementation detail and ideally not mandatory.  So I don't think we should refer to RequestHandlerBase unless it's to extend it.  Likewise I got wind of this smell when you made some RHB methods public that were protected; it's suspicious.



##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -192,6 +200,28 @@ public Category getCategory() {
     return Category.ADMIN;
   }
 
+  public Boolean registerV2() {
+    return true;
+  }
+
+  @Override
+  public Collection<Api> getApis() {

Review Comment:
   List.of



##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -490,4 +532,8 @@ public Api v2lookup(String path, String method, Map<String, String> parts) {
   public ApiBag getApiBag() {
     return apiBag;
   }
+
+  public ResourceConfig getJerseyEndpoints() {

Review Comment:
   It's curious to me to see getXXXX and the type doesn't have an obvious correlation to XXXX.  Can you explain?  In CoreContainer you called a similar method just getResourceConfig.



##########
solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaNameResponse.java:
##########
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.solr.jersey.SolrJerseyResponse;
+
+public class GetSchemaNameResponse extends SolrJerseyResponse {

Review Comment:
   This could even be an inner class of the handler that uses it?



##########
solr/core/src/java/org/apache/solr/api/JerseyResource.java:
##########
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.api;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_JERSEY_RESPONSE_KEY;
+
+import java.util.function.Supplier;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Context;
+import org.apache.solr.jersey.CatchAllExceptionMapper;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.servlet.HttpSolrCall;
+
+/** A marker parent type for all Jersey resource classes */

Review Comment:
   And what is a "Jersey resource class"?  I'm new to this.  Maybe say it's for "request handlers" in the V3 API?



##########
solr/core/src/java/org/apache/solr/core/SolrCore.java:
##########
@@ -1955,6 +1958,10 @@ public PluginBag<SolrRequestHandler> getRequestHandlers() {
     return reqHandlers.handlers;
   }
 
+  public ApplicationHandler getApplicationHandler() {

Review Comment:
   Use "Jersey" in the name please.  Same with the field name.



##########
solr/core/src/java/org/apache/solr/core/CoreContainer.java:
##########
@@ -180,6 +185,17 @@ public CoreLoadFailure(CoreDescriptor cd, Exception loadFailure) {
   private volatile PluginBag<SolrRequestHandler> containerHandlers =
       new PluginBag<>(SolrRequestHandler.class, null);
 
+  private volatile ResourceConfig config;
+  private volatile ApplicationHandler appHandler;

Review Comment:
   Please name this `jerseyAppHandler`.
   
   The point is to make it clear where we have our "Jersey" stuff in existing Solr classes with tons of Solr things so that we can clearly spot major _other_ APIs.  Names like "ResourceConfig" and "ApplicationHandler" are so generic sounding that it's not obvious it's related to Jersey unless you already know Jersey well.
   
   Similarly the getters could be named accordingly at your discretion.



##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -136,7 +143,8 @@ public SolrParams getParams() {
         }
         break;
       case LIST:
-        new ListConfigSetsAPI(coreContainer).listConfigSet(req, rsp);
+        final ListConfigSetsAPI listConfigSetsAPI = new ListConfigSetsAPI(coreContainer);
+        V2ApiUtils.squashIntoSolrResponse(rsp, listConfigSetsAPI.listConfigSet(), true);

Review Comment:
   The final boolean is harder to judge reading the code; I think it would be clearer if it was called squashIntoSolrResponseWithoutHeader even though it's a long name.



##########
solr/core/src/java/org/apache/solr/jersey/ApplicationEventLogger.java:
##########
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.ApplicationEvent;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out application-level information useful for troubleshooting Jersey development.
+ *
+ * @see RequestEventLogger
+ */
+public class ApplicationEventLogger implements ApplicationEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount = 0;
+
+  @Override
+  public void onEvent(ApplicationEvent event) {
+    if (log.isInfoEnabled()) {
+      log.info("Received ApplicationEvent {}", event.getType());
+    }
+  }
+
+  @Override
+  public RequestEventListener onRequest(RequestEvent requestEvent) {
+    requestCount++;
+    log.info("Starting Jersey request {}", requestCount);

Review Comment:
   Another INFO level that should probably simply be removed



##########
solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaNameResponse.java:
##########
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.solr.jersey.SolrJerseyResponse;
+
+public class GetSchemaNameResponse extends SolrJerseyResponse {
+  @JsonProperty("name")
+  public String name;

Review Comment:
   Instead of a mutable class; can't this be a simple immutable object with a constructor?



##########
solr/core/src/java/org/apache/solr/handler/api/ApiRegistrar.java:
##########
@@ -79,12 +73,4 @@ public static void registerShardApis(ApiBag apiBag, CollectionsHandler collectio
     // here for simplicity.
     apiBag.registerObject(new DeleteReplicaAPI(collectionsHandler));
   }
-
-  public static void registerConfigsetApis(ApiBag apiBag, CoreContainer container) {

Review Comment:
   These are no longer registered in ApiBag?  I don't see that the code merely moved.



##########
solr/core/src/java/org/apache/solr/jersey/MetricBeanFactory.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.PluginBag;
+import org.glassfish.hk2.api.Factory;
+
+/**
+ * Factory to inject JerseyMetricsLookupRegistry instances into Jersey resources and filters.
+ *
+ * <p>Currently, Jersey resources that have a corresponding v1 API produce the same metrics as their
+ * v1 equivalent and rely on the v1 requestHandler instance to do so. Solr facilitates this by
+ * building a map of the Jersey resource to requestHandler mapping (a {@link
+ * org.apache.solr.core.PluginBag.JerseyMetricsLookupRegistry}), and injecting it into the pre- and
+ * post- Jersey filters that handle metrics.
+ *
+ * <p>This isn't ideal, as requestHandler's don't really "fit" conceptually here. But it's
+ * unavoidable while we want our v2 APIs to exactly match the metrics produced by v1 calls.

Review Comment:
   If we didn't retain this exact metrics match with V1, what might a metric look like before & after?



##########
solr/core/src/test/org/apache/solr/handler/configsets/ListConfigSetsAPITest.java:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.ConfigSetService;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.CoreContainerFactory;
+import org.apache.solr.jersey.SolrJacksonMapper;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ListConfigSetsAPITest extends JerseyTest {
+
+  private CoreContainer mockCoreContainer;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Override
+  protected Application configure() {
+    resetMocks();
+    final ResourceConfig config = new ResourceConfig();
+    config.register(ListConfigSetsAPI.class);
+    config.register(SolrJacksonMapper.class);
+    config.register(
+        new AbstractBinder() {
+          @Override
+          protected void configure() {
+            bindFactory(new CoreContainerFactory(mockCoreContainer))
+                .to(CoreContainer.class)
+                .in(Singleton.class);
+          }
+        });
+
+    return config;
+  }
+
+  private void resetMocks() {
+    mockCoreContainer = mock(CoreContainer.class);
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsRaw() throws Exception {
+    final String expectedJson =
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}";
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final Response response = target("/cluster/configs").request().get();
+    final String jsonBody = response.readEntity(String.class);
+
+    assertEquals(200, response.getStatus());
+    assertEquals("application/json", response.getHeaders().getFirst("Content-type"));
+    assertEquals(1, 1);
+    assertEquals(
+        expectedJson,
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}");
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsTyped() throws Exception {
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final ListConfigsetsResponse response =
+        target("/cluster/configs").request().get(ListConfigsetsResponse.class);
+
+    assertNotNull(response.configSets);
+    assertNull(response.error);
+    assertEquals(2, response.configSets.size());
+    assertTrue(response.configSets.contains("cs1"));
+    assertTrue(response.configSets.contains("cs2"));
+  }
+
+  /**
+   * Test the v2 to v1 response mapping for /cluster/configs
+   *
+   * <p>{@link org.apache.solr.handler.admin.ConfigSetsHandler} uses {@link ListConfigSetsAPI} (and
+   * its response class {@link ListConfigsetsResponse}) internally to serve the v1 version of this
+   * functionality. So it's important to make sure that the v2 response stays compatible with SolrJ
+   * - both because that's important in its own right and because that ensures we haven't
+   * accidentally changed the v1 response format.
+   */
+  @Test
+  public void testListConfigsetsV1Compatibility() throws Exception {

Review Comment:
   IMO the best test for v1 or v-whatever compatibility would be high level -- test the JSON or XML.  Such tests are very easy to understand and thus high-confidence as well (i.e. is whatever _really_ tested).  Then we can play with class internals without tests acting as quick-sand for change (my beef with many unit tests).  Why test internals like this?



##########
solr/core/src/java/org/apache/solr/jersey/RequestContextConstants.java:
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.codahale.metrics.Timer;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.security.AuthorizationContext;
+
+/**
+ * Keys used to store and retrieve values from the Jersey request context.
+ *
+ * <p>Properties are generally set in V2HttpCall's 'invokeJerseyRequest' and retrieved in individual
+ * {@link javax.ws.rs.container.ContainerRequestFilter}s using {@link
+ * ContainerRequestContext#getProperty(String)}
+ */
+public class RequestContextConstants {

Review Comment:
   Interfaces are nice to hold constants -- you can omit the "public static final" before each.  I added a several relating to cluster state like Slice.SliceStateProps recently.



##########
versions.props:
##########
@@ -56,6 +57,8 @@ org.bitbucket.b_c:jose4j=0.7.9
 org.carrot2:carrot2-core=4.4.2
 org.codehaus.woodstox:stax2-api=4.2.1
 org.eclipse.jetty*:*=9.4.44.v20210927
+org.glassfish.hk2*:*=2.6.1
+org.glassfish.jersey*:*=2.35

Review Comment:
   there is a Jersey 2.36



##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   Can't there be more; like doesn't echoParams stuff show up under here too?  I'm a little concerned that SolrJerseyResponse may be a bit rigid in structure when Solr is rather flexible.



##########
solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java:
##########
@@ -215,54 +215,59 @@ public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
         }
       }
     } catch (Exception e) {
-      if (req.getCore() != null) {
-        boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
-        if (isTragic) {
-          if (e instanceof SolrException) {
-            // Tragic exceptions should always throw a server error
-            assert ((SolrException) e).code() == 500;
-          } else {
-            // wrap it in a solr exception
-            e = new SolrException(SolrException.ErrorCode.SERVER_ERROR, e.getMessage(), e);
-          }
-        }
-      }
-      boolean incrementErrors = true;
-      boolean isServerError = true;
-      if (e instanceof SolrException) {
-        SolrException se = (SolrException) e;
-        if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
-          incrementErrors = false;
-        } else if (se.code() >= 400 && se.code() < 500) {
-          isServerError = false;
-        }
-      } else {
-        if (e instanceof SyntaxError) {
-          isServerError = false;
-          e = new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
-        }
-      }
-
+      e = normalizeReceivedException(req, e);
+      processErrorMetricsOnException(e, metrics);
       rsp.setException(e);
+    } finally {
+      long elapsed = timer.stop();
+      metrics.totalTime.inc(elapsed);
+    }
+  }
 
-      if (incrementErrors) {
-        SolrException.log(log, e);
+  public static void processErrorMetricsOnException(Exception e, HandlerMetrics metrics) {
+    boolean isClientError = false;
+    if (e instanceof SolrException) {
+      final SolrException se = (SolrException) e;
+      if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
+        return;
+      } else if (se.code() >= 400 && se.code() < 500) {
+        isClientError = true;
+      }
+    }
+
+    SolrException.log(log, e);
+    metrics.numErrors.mark();
+    if (isClientError) {
+      metrics.numClientErrors.mark();
+    } else {
+      metrics.numServerErrors.mark();
+    }
+  }
 
-        metrics.numErrors.mark();
-        if (isServerError) {
-          metrics.numServerErrors.mark();
+  public static Exception normalizeReceivedException(SolrQueryRequest req, Exception e) {
+    if (req.getCore() != null) {
+      assert req.getCoreContainer() != null;
+      boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
+      if (isTragic) {
+        if (e instanceof SolrException) {
+          // Tragic exceptions should always throw a server error
+          assert ((SolrException) e).code() == 500;

Review Comment:
   better yet, add this as a SolrException method.



##########
solr/core/src/java/org/apache/solr/jersey/JerseyApplications.java:
##########
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.util.Map;
+import javax.inject.Singleton;
+import org.apache.solr.core.PluginBag;
+import org.apache.solr.core.SolrCore;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+
+/**
+ * JAX-RS "application" configurations for Solr's {@link org.apache.solr.core.CoreContainer} and
+ * {@link SolrCore} instances
+ */
+public class JerseyApplications {
+
+  public static class CoreContainerApp extends ResourceConfig {
+    public CoreContainerApp(PluginBag.JerseyMetricsLookupRegistry beanRegistry) {
+      super();
+
+      // Authentication and authorization
+      register(SolrRequestAuthorizer.class);
+
+      // Request and response serialization/deserialization
+      // TODO: could these be singletons to save per-request object creations?
+      register(MessageBodyWriters.JavabinMessageBodyWriter.class);
+      register(MessageBodyWriters.XmlMessageBodyWriter.class);
+      register(MessageBodyWriters.CsvMessageBodyWriter.class);
+      register(SolrJacksonMapper.class);
+
+      // Request lifecycle logic
+      register(CatchAllExceptionMapper.class);
+      register(PreRequestMetricsFilter.class);
+      register(PostRequestMetricsFilter.class);

Review Comment:
   I think these two classes could be combined and it'd be clearer for them since they interact (pre & post for same topic).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965213364


##########
solr/core/src/test/org/apache/solr/handler/configsets/ListConfigSetsAPITest.java:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.ConfigSetService;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.CoreContainerFactory;
+import org.apache.solr.jersey.SolrJacksonMapper;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ListConfigSetsAPITest extends JerseyTest {
+
+  private CoreContainer mockCoreContainer;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Override
+  protected Application configure() {
+    resetMocks();
+    final ResourceConfig config = new ResourceConfig();
+    config.register(ListConfigSetsAPI.class);
+    config.register(SolrJacksonMapper.class);
+    config.register(
+        new AbstractBinder() {
+          @Override
+          protected void configure() {
+            bindFactory(new CoreContainerFactory(mockCoreContainer))
+                .to(CoreContainer.class)
+                .in(Singleton.class);
+          }
+        });
+
+    return config;
+  }
+
+  private void resetMocks() {
+    mockCoreContainer = mock(CoreContainer.class);
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsRaw() throws Exception {
+    final String expectedJson =
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}";
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final Response response = target("/cluster/configs").request().get();
+    final String jsonBody = response.readEntity(String.class);
+
+    assertEquals(200, response.getStatus());
+    assertEquals("application/json", response.getHeaders().getFirst("Content-type"));
+    assertEquals(1, 1);
+    assertEquals(
+        expectedJson,
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}");
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsTyped() throws Exception {
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final ListConfigsetsResponse response =
+        target("/cluster/configs").request().get(ListConfigsetsResponse.class);
+
+    assertNotNull(response.configSets);
+    assertNull(response.error);
+    assertEquals(2, response.configSets.size());
+    assertTrue(response.configSets.contains("cs1"));
+    assertTrue(response.configSets.contains("cs2"));
+  }
+
+  /**
+   * Test the v2 to v1 response mapping for /cluster/configs
+   *
+   * <p>{@link org.apache.solr.handler.admin.ConfigSetsHandler} uses {@link ListConfigSetsAPI} (and
+   * its response class {@link ListConfigsetsResponse}) internally to serve the v1 version of this
+   * functionality. So it's important to make sure that the v2 response stays compatible with SolrJ
+   * - both because that's important in its own right and because that ensures we haven't
+   * accidentally changed the v1 response format.
+   */
+  @Test
+  public void testListConfigsetsV1Compatibility() throws Exception {

Review Comment:
   Hah, the old integration vs unit test debate.
   
   Each has a place at the table IMO.  Integration tests do give you better fidelity for high level functionality.  I wouldn't rely on unit tests alone.  And unit tests do often need to change with the code, which is a pain.
   
   But IMO unit tests have a lot of advantages: they're faster, more targeted, run less risk of unrelated environmental issues (such as cause many of Solr's flaky build issues), allow testing of otherwise hard-to-trigger codepaths, etc.
   
   To answer your specific question about this test, I thought a unit test would be a good addition for two reasons:
   
   First, Solr has lots of integration tests around configset-listing, and I trust those to flag issues with json/xml/javabin serialization if this were to break.  But none of them are very focused on serialization.  They each leave a pretty big gap between seeing the failure and understanding the root cause and fixing it.  This test addresses that by having something very narrowly focused on just the response conversions involved, hopefully making a failure much more actionable.
   
   Second, I wanted to create an example test case based on a Jersey test-application.  The relative simplicity of the list-configset API doesn't make the point very well, but more complex APIs will benefit a lot from Jersey-framework-aided unit testing.  And I wanted to include an example of that in this PR.
   
   If neither of those reasons are convincing for you though, I'm happy to rip it out for now and rely on the existing list-configset tests.  (Deferring the example jersey-framework test, until we convert a v2 API complex enough to require it)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r957745742


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -397,7 +399,7 @@ protected void handleAdmin(SolrQueryResponse solrResp) {
   @Override
   protected void executeCoreRequest(SolrQueryResponse rsp) {
     if (api == null) {
-      invokeJerseyRequest(cores, core, core.getApplicationHandler());
+      invokeJerseyRequest(cores, core, core.getApplicationHandler(), rsp);

Review Comment:
   `rsp` or `solrResp`, but maybe not both ???



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r948381273


##########
solr/core/src/java/org/apache/solr/security/AuthorizationUtils.java:
##########
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.security;
+
+import org.apache.http.HttpStatus;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATE;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETE;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.RELOAD;
+import static org.apache.solr.servlet.HttpSolrCall.shouldAudit;
+
+public class AuthorizationUtils {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    private AuthorizationUtils() { /* Private ctor prevents instantiation */}
+
+    public static class AuthorizationFailure {
+        private final int statusCode;
+        private final String message;
+        public AuthorizationFailure(int statusCode, String message) {
+            this.statusCode = statusCode;
+            this.message = message;
+        }
+
+        public int getStatusCode() { return statusCode; }
+        public String getMessage() { return message; }
+    }
+
+    public static AuthorizationFailure authorize(HttpServletRequest servletReq, HttpServletResponse response,
+                                               CoreContainer cores, AuthorizationContext context) throws IOException {
+        log.debug("AuthorizationContext : {}", context);
+        AuthorizationResponse authResponse = cores.getAuthorizationPlugin().authorize(context);

Review Comment:
   đŸ’Ŧ 3 similar findings have been found in this PR
   
   ---
   
   *NULL_DEREFERENCE:*  object returned by `cores.getAuthorizationPlugin()` could be null and is dereferenced at line 60.
   
   ---
   
   <details><summary><b>Expand here to view all instances of this finding</b></summary><br/>
   
   <div align="center">
   
   | **File Path** | **Line Number** |
   | ------------- | ------------- |
   | solr/core/src/java/org/apache/solr/schema/BBoxField.java | [142](https://github.com/gerlowskija/solr/blob/f2959369e5541d377ee6ef34ae703ab4013b79d5/solr/core/src/java/org/apache/solr/schema/BBoxField.java#L142)|
   | solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java | [1422](https://github.com/gerlowskija/solr/blob/f2959369e5541d377ee6ef34ae703ab4013b79d5/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java#L1422)|
   | solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java | [1512](https://github.com/gerlowskija/solr/blob/f2959369e5541d377ee6ef34ae703ab4013b79d5/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java#L1512)|
   <p><a href="https://lift.sonatype.com/results/github.com/apache/solr/01GAPMKNSD4R1GX3CC4ST9P9MV?t=Infer|NULL_DEREFERENCE" target="_blank">Visit the Lift Web Console</a> to find more details in your report.</p></div></details>
   
   
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=317126461&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=317126461&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317126461&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317126461&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=317126461&lift_comment_rating=5) ]



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r953822401


##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -75,6 +77,18 @@ public static boolean isAutoGeneratedConfigSet(String configName) {
     return configName != null && configName.endsWith(AUTOCREATED_CONFIGSET_SUFFIX);
   }
 
+  private void squashIntoSolrResponse(SolrQueryResponse rsp, ReflectMapWriter mw) {
+    Map<String, Object> myMap = new HashMap<>();
+    myMap = mw.toMap(myMap);
+    if (myMap.isEmpty()) {
+      log.info("Hmm, map is empty after writing in values from {}", mw);
+    }
+    for (String key : myMap.keySet()) {
+      log.info("Adding key={}, value={} to rsp", key, myMap.get(key));

Review Comment:
   Agreed - I think I went through about a week ago and fixed this, though maybe I missed some?
   
   One thing that I find a little confusing about the Github UI is that it doesn't hide conversations/comments like these after the code underlying them has changed.  I removed many instances of this a week or so ago, but you'd never know from the landing page of this PR (if you miss the tiny 'Outdated' indicator next to the filename in the snippet)
   
   Oh well, there's no use complaining about Github's UI.  I can always just manually resolve all these conversations I guess...



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r967291913


##########
solr/core/src/java/org/apache/solr/jersey/ApplicationEventLogger.java:
##########
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.ApplicationEvent;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out application-level information useful for troubleshooting Jersey development.
+ *
+ * @see RequestEventLogger
+ */
+public class ApplicationEventLogger implements ApplicationEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount = 0;

Review Comment:
   On second thought I've decided to just cut these classes.  The sort of information they log was very helpful in tracking resource registration and understanding how resources are looked up at request time, but very few users should need that now that the framework will be in place.
   
   (If we do want them later, they're trivial for an IDE to generate from Jersey's ApplicationEventListener and RequestEventListener interfaces, so there'll be no real loss if we need to "180" on this later.)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966010573


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -388,33 +335,65 @@ public CompositeApi add(Api api) {
     }
   }
 
+  // We don't rely on any of Jersey's authc/z features so we pass in this empty context for
+  // all requests.
+  public static final SecurityContext DEFAULT_SECURITY_CONTEXT = new SecurityContext() {
+    public boolean isUserInRole(String role) { return false; }
+    public boolean isSecure() { return false; }
+    public Principal getUserPrincipal() { return null; }
+    public String getAuthenticationScheme() { return null; }
+  };
+
+  private void invokeJerseyRequest(CoreContainer cores, SolrCore core, ApplicationHandler jerseyHandler, SolrQueryResponse rsp) {
+    try {
+      final ContainerRequest containerRequest = ContainerRequestUtils.createContainerRequest(req, response, jerseyHandler.getConfiguration());
+
+      // Set properties that may be used by Jersey filters downstream
+      containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);
+      containerRequest.setProperty(RequestContextConstants.CORE_CONTAINER_KEY, cores);

Review Comment:
   I've renamed the interface to include 'Keys', and dropped the suffix from each individual constants.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] janhoy commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
janhoy commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r958606212


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   `application/javabin` is not a registered type, so should perhaps be something like `application/vnd.apachesolr.javabin`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r959808595


##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -27,8 +27,7 @@
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.handler.RequestHandlerBase;
 import org.apache.solr.handler.component.SearchComponent;
-import org.apache.solr.jersey.CoreContainerApp;
-import org.apache.solr.jersey.SolrCoreApp;
+import org.apache.solr.jersey.JerseyApplications;

Review Comment:
   Yep!
   
   An "Application" in JAX-RS is pretty far from the colloquial usage.  It's not a whole process or package or something runnable - it's more like Solr's existing "PluginBag" abstraction - a collection of endpoints and config needed to look them up and invoke them.
   
   "JerseyApplications" is plural because it holds multiple of these application configs.  There are two currently: `CoreContainerApp` is a registration point for our container/cluster level APIs, and `SolrCoreApp` handles per-core API registration.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r957745294


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -362,14 +363,15 @@ private void invokeJerseyRequest(CoreContainer cores, SolrCore core, Application
 
       // Set properties that may be used by Jersey filters downstream
       containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
-      containerRequest.setProperty(SolrRequestAuthorizer.CORE_CONTAINER_PROP_NAME, cores);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_REQ_PROP_NAME, req);
-      containerRequest.setProperty(SolrRequestAuthorizer.REQUEST_TYPE_PROP_NAME, requestType);
-      containerRequest.setProperty(SolrRequestAuthorizer.SOLR_PARAMS_PROP_NAME, queryParams);
-      containerRequest.setProperty(SolrRequestAuthorizer.COLLECTION_LIST_PROP_NAME, collectionsList);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_RSP_PROP_NAME, response);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);

Review Comment:
   Should we static import all the keys, or use the `RequestContextConstants.SOLR_QUERY_RESPONSE_KEY`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r957796541


##########
solr/core/src/java/org/apache/solr/jersey/PostRequestDecorationFilter.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+
+/**
+ * Applies standard post-processing decorations to a {@link SolrJerseyResponse} that are needed on all responses.
+ *
+ * @see SolrCore#postDecorateResponse(SolrRequestHandler, SolrQueryRequest, SolrQueryResponse)
+ */
+public class PostRequestDecorationFilter implements ContainerResponseFilter {
+
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+        final SolrQueryRequest solrQueryRequest = (SolrQueryRequest) requestContext.getProperty(SOLR_QUERY_REQUEST_KEY);
+        if ( ! responseContext.hasEntity() || ! SolrJerseyResponse.class.isInstance(responseContext.getEntity())) {
+            log.debug("Skipping QTime assignment because response was not a SolrJerseyResponse");

Review Comment:
   Would we do QTime if we started from scratch?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r957746223


##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -27,8 +27,7 @@
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.handler.RequestHandlerBase;
 import org.apache.solr.handler.component.SearchComponent;
-import org.apache.solr.jersey.CoreContainerApp;
-import org.apache.solr.jersey.SolrCoreApp;
+import org.apache.solr.jersey.JerseyApplications;

Review Comment:
   Why plural?   Is this because it hosts mulitple applications in Jersey?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r958476775


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   Hah, yeah it does look weird as you add more and more formats to this list.  There must be a cleaner way to declare these.
   
   > Do we actually want a javabin version for this API????
   
   I think there's a good question of whether we want to hang on to javabin long term.  But while we do support it, I think we might as well allow it everywhere unless we have a reason not to?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r948314317


##########
solr/core/src/java/org/apache/solr/handler/api/SomeCoreResource.java:
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.api;
+
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.security.PermissionNameProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.lang.invoke.MethodHandles;
+
+@Path("/collections/{collectionName}/somecorepath")
+public class SomeCoreResource extends JerseyResource {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    @PermissionName(PermissionNameProvider.Name.READ_PERM)
+    public String helloPlainText(@PathParam("collectionName") String collectionName) {
+        log.info("Made it into SomeCoreResource.helloPlainText with collName {}", collectionName);

Review Comment:
   *[CRLF_INJECTION_LOGS](https://find-sec-bugs.github.io/bugs.htm#CRLF_INJECTION_LOGS):*  This use of org/slf4j/Logger.info(Ljava/lang/String;Ljava/lang/Object;)V might be used to include CRLF characters into log messages
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=317026945&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=317026945&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317026945&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317026945&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=317026945&lift_comment_rating=5) ]



##########
solr/core/src/java/org/apache/solr/security/AuthorizationUtils.java:
##########
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.security;
+
+import org.apache.http.HttpStatus;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATE;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETE;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.RELOAD;
+import static org.apache.solr.servlet.HttpSolrCall.shouldAudit;
+
+public class AuthorizationUtils {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    private AuthorizationUtils() { /* Private ctor prevents instantiation */}
+
+    public static class AuthorizationFailure {
+        private final int statusCode;
+        private final String message;
+        public AuthorizationFailure(int statusCode, String message) {
+            this.statusCode = statusCode;
+            this.message = message;
+        }
+
+        public int getStatusCode() { return statusCode; }
+        public String getMessage() { return message; }
+    }
+
+    public static AuthorizationFailure authorize(HttpServletRequest servletReq, HttpServletResponse response,
+                                               CoreContainer cores, AuthorizationContext context) throws IOException {
+        log.debug("AuthorizationContext : {}", context);
+        AuthorizationResponse authResponse = cores.getAuthorizationPlugin().authorize(context);
+        int statusCode = authResponse.statusCode;
+
+        if (statusCode == AuthorizationResponse.PROMPT.statusCode) {
+            @SuppressWarnings({"unchecked"})
+            Map<String, String> headers =
+                    (Map<String, String>) servletReq.getAttribute(AuthenticationPlugin.class.getName());
+            if (headers != null) {
+                for (Map.Entry<String, String> e : headers.entrySet())
+                    response.setHeader(e.getKey(), e.getValue());
+            }
+            if (log.isDebugEnabled()) {
+                log.debug("USER_REQUIRED {} {}", servletReq.getHeader("Authorization"), servletReq.getUserPrincipal());
+            }
+            if (shouldAudit(cores, AuditEvent.EventType.REJECTED)) {
+                cores.getAuditLoggerPlugin().doAudit(new AuditEvent(AuditEvent.EventType.REJECTED, servletReq, context));
+            }
+            return new AuthorizationFailure(statusCode, "Authentication failed, Response code: " + statusCode);
+        }
+        if (statusCode == AuthorizationResponse.FORBIDDEN.statusCode) {
+            if (log.isDebugEnabled()) {
+                log.debug(

Review Comment:
   *[CRLF_INJECTION_LOGS](https://find-sec-bugs.github.io/bugs.htm#CRLF_INJECTION_LOGS):*  This use of org/slf4j/Logger.debug(Ljava/lang/String;[Ljava/lang/Object;)V might be used to include CRLF characters into log messages
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=317027078&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=317027078&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317027078&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317027078&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=317027078&lift_comment_rating=5) ]



##########
solr/core/src/java/org/apache/solr/security/AuthorizationUtils.java:
##########
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.security;
+
+import org.apache.http.HttpStatus;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATE;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETE;
+import static org.apache.solr.common.params.CollectionParams.CollectionAction.RELOAD;
+import static org.apache.solr.servlet.HttpSolrCall.shouldAudit;
+
+public class AuthorizationUtils {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    private AuthorizationUtils() { /* Private ctor prevents instantiation */}
+
+    public static class AuthorizationFailure {
+        private final int statusCode;
+        private final String message;
+        public AuthorizationFailure(int statusCode, String message) {
+            this.statusCode = statusCode;
+            this.message = message;
+        }
+
+        public int getStatusCode() { return statusCode; }
+        public String getMessage() { return message; }
+    }
+
+    public static AuthorizationFailure authorize(HttpServletRequest servletReq, HttpServletResponse response,
+                                               CoreContainer cores, AuthorizationContext context) throws IOException {
+        log.debug("AuthorizationContext : {}", context);
+        AuthorizationResponse authResponse = cores.getAuthorizationPlugin().authorize(context);
+        int statusCode = authResponse.statusCode;
+
+        if (statusCode == AuthorizationResponse.PROMPT.statusCode) {
+            @SuppressWarnings({"unchecked"})
+            Map<String, String> headers =
+                    (Map<String, String>) servletReq.getAttribute(AuthenticationPlugin.class.getName());
+            if (headers != null) {
+                for (Map.Entry<String, String> e : headers.entrySet())
+                    response.setHeader(e.getKey(), e.getValue());

Review Comment:
   *CROSS_SITE_SCRIPTING:*  UserControlledString(HttpServletRequest.getAttribute(...)) at line 66 ~> HTML(HttpServletResponse.setHeader(...)) at line 69.
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=317027804&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=317027804&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317027804&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317027804&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=317027804&lift_comment_rating=5) ]



##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -75,6 +77,18 @@ public static boolean isAutoGeneratedConfigSet(String configName) {
     return configName != null && configName.endsWith(AUTOCREATED_CONFIGSET_SUFFIX);
   }
 
+  private void squashIntoSolrResponse(SolrQueryResponse rsp, ReflectMapWriter mw) {
+    Map<String, Object> myMap = new HashMap<>();
+    myMap = mw.toMap(myMap);
+    if (myMap.isEmpty()) {
+      log.info("Hmm, map is empty after writing in values from {}", mw);
+    }
+    for (String key : myMap.keySet()) {
+      log.info("Adding key={}, value={} to rsp", key, myMap.get(key));
+      rsp.add(key, myMap.get(key));

Review Comment:
   *INEFFICIENT_KEYSET_ITERATOR:*  Accessing a value using a key that was retrieved from a `keySet` iterator. It is more efficient to use an iterator on the `entrySet` of the map, avoiding the extra `HashMap.get(key)` lookup.
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=317027791&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=317027791&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317027791&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317027791&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=317027791&lift_comment_rating=5) ]



##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -75,6 +77,18 @@ public static boolean isAutoGeneratedConfigSet(String configName) {
     return configName != null && configName.endsWith(AUTOCREATED_CONFIGSET_SUFFIX);
   }
 
+  private void squashIntoSolrResponse(SolrQueryResponse rsp, ReflectMapWriter mw) {
+    Map<String, Object> myMap = new HashMap<>();
+    myMap = mw.toMap(myMap);
+    if (myMap.isEmpty()) {
+      log.info("Hmm, map is empty after writing in values from {}", mw);
+    }
+    for (String key : myMap.keySet()) {
+      log.info("Adding key={}, value={} to rsp", key, myMap.get(key));

Review Comment:
   *INEFFICIENT_KEYSET_ITERATOR:*  Accessing a value using a key that was retrieved from a `keySet` iterator. It is more efficient to use an iterator on the `entrySet` of the map, avoiding the extra `HashMap.get(key)` lookup.
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=317028064&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=317028064&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317028064&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317028064&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=317028064&lift_comment_rating=5) ]



##########
solr/core/src/java/org/apache/solr/jersey/SolrRequestAuthorizer.java:
##########
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.security.AuthorizationContext;
+import org.apache.solr.security.AuthorizationUtils;
+import org.apache.solr.security.HttpServletAuthorizationContext;
+import org.apache.solr.security.PermissionNameProvider;
+import org.apache.solr.servlet.ServletUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+
+@Provider
+public class SolrRequestAuthorizer implements ContainerRequestFilter {
+
+    public static final String CORE_CONTAINER_PROP_NAME = CoreContainer.class.getName();
+    public static final String HTTP_SERVLET_REQ_PROP_NAME = HttpServletRequest.class.getName();
+    public static final String HTTP_SERVLET_RSP_PROP_NAME = HttpServletResponse.class.getName();
+    public static final String SOLR_CORE_PROP_NAME = SolrCore.class.getName();
+    public static final String REQUEST_TYPE_PROP_NAME = AuthorizationContext.RequestType.class.getName();
+    public static final String SOLR_PARAMS_PROP_NAME = SolrParams.class.getName();
+    public static final String COLLECTION_LIST_PROP_NAME = "collection_name_list";
+
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @Context
+    private ResourceInfo resourceInfo;
+
+    public SolrRequestAuthorizer() {
+        log.info("Creating a new SolrRequestAuthorizer");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void filter(ContainerRequestContext requestContext) throws IOException {
+        final CoreContainer coreContainer = (CoreContainer) requestContext.getProperty(CORE_CONTAINER_PROP_NAME);
+        final SolrCore solrCore = (SolrCore) requestContext.getProperty(SOLR_CORE_PROP_NAME); // May be null

Review Comment:
   đŸ’Ŧ 5 similar findings have been found in this PR
   
   ---
   
   *[UnusedVariable](https://errorprone.info/bugpattern/UnusedVariable):*  The local variable 'solrCore' is never read.
   
   ---
   
   <details><summary><b>Expand here to view all instances of this finding</b></summary><br/>
   
   <div align="center">
   
   | **File Path** | **Line Number** |
   | ------------- | ------------- |
   | solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java | [148](https://github.com/gerlowskija/solr/blob/051d2d568d2bd25660d21f19c4b4a88295f598a9/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java#L148)|
   | solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java | [615](https://github.com/gerlowskija/solr/blob/051d2d568d2bd25660d21f19c4b4a88295f598a9/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java#L615)|
   | solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java | [506](https://github.com/gerlowskija/solr/blob/051d2d568d2bd25660d21f19c4b4a88295f598a9/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java#L506)|
   | solr/core/src/java/org/apache/solr/jersey/SolrRequestAuthorizer.java | [96](https://github.com/gerlowskija/solr/blob/051d2d568d2bd25660d21f19c4b4a88295f598a9/solr/core/src/java/org/apache/solr/jersey/SolrRequestAuthorizer.java#L96)|
   | solr/core/src/java/org/apache/solr/core/ConfigOverlay.java | [182](https://github.com/gerlowskija/solr/blob/051d2d568d2bd25660d21f19c4b4a88295f598a9/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java#L182)|
   <p><a href="https://lift.sonatype.com/results/github.com/apache/solr/01GAPF3M32GGTWD6W3BR98PRRD?t=ErrorProne|UnusedVariable" target="_blank">Visit the Lift Web Console</a> to find more details in your report.</p></div></details>
   
   
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=317026749&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=317026749&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317026749&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=317026749&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=317026749&lift_comment_rating=5) ]



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] madrob commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
madrob commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r948274391


##########
solr/core/src/java/org/apache/solr/jersey/PermissionName.java:
##########
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.security.PermissionNameProvider;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PermissionName {

Review Comment:
   javadoc



##########
solr/core/src/java/org/apache/solr/api/JerseyResource.java:
##########
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.api;
+
+public class JerseyResource {

Review Comment:
   javadoc



##########
solr/core/src/java/org/apache/solr/handler/api/SomeCoreHandler.java:
##########
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.api;
+
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.security.AuthorizationContext;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class SomeCoreHandler extends RequestHandlerBase {

Review Comment:
   Was this mean to be left in as an example, or just left over from your experimentation?



##########
solr/core/src/java/org/apache/solr/jersey/container/package-info.java:
##########
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * asdf

Review Comment:
   jklsemicolon



##########
solr/core/src/java/org/apache/solr/api/ApiSupport.java:
##########
@@ -29,6 +30,10 @@ public interface ApiSupport {
    */
   Collection<Api> getApis();
 
+  default Collection<Class<? extends JerseyResource>> getJerseyResources() {

Review Comment:
   javadoc



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r948326320


##########
solr/core/src/java/org/apache/solr/handler/api/SomeCoreHandler.java:
##########
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.api;
+
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.security.AuthorizationContext;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class SomeCoreHandler extends RequestHandlerBase {

Review Comment:
   Left in as an example.
   
   This PR changes a "admin"/core-container API over to using JAX-RS, but I wanted an example of a core/collection API set up in the same way.
   
   I plan on circling back to this shortly and updating one of our "real" core APIs to use JAX-RS, and I can toss this example/stub class at that point.  But I'll keep it around until then so people can test out the per-core loading if they'd like.
   
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on PR #975:
URL: https://github.com/apache/solr/pull/975#issuecomment-1241402958

   Alright, tests and precommit passing, and I _think_ I've addressed everyone's comments, excepting a few that I asked for more info/clarification on?  Feels like this is getting close 🎉 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965936792


##########
solr/core/src/java/org/apache/solr/jersey/CatchAllExceptionMapper.java:
##########
@@ -93,10 +98,12 @@ public Response toResponse(Exception exception) {
       RequestHandlerBase.processErrorMetricsOnException(normalizedException, metrics);
     }
 
-    // Then, convert the exception into a SolrJerseyResponse (creating one as necessary if resource was matched, etc.)
-    final SolrJerseyResponse response = containerRequestContext.getProperty(SOLR_JERSEY_RESPONSE_KEY) == null ?
-            new SolrJerseyResponse() :
-            (SolrJerseyResponse) containerRequestContext.getProperty(SOLR_JERSEY_RESPONSE_KEY);
+    // Then, convert the exception into a SolrJerseyResponse (creating one as necessary if resource
+    // was matched, etc.)

Review Comment:
   I reformatted this a bit and chose a new place to break the line so it looks a little more even, but it still looks a bit awkward.  I wish spotless allowed longer lines for comments (or in general).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r950237076


##########
solr/core/src/java/org/apache/solr/handler/api/SomeCoreResource.java:
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.api;
+
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.security.PermissionNameProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.lang.invoke.MethodHandles;
+
+@Path("/collections/{collectionName}/somecorepath")
+public class SomeCoreResource extends JerseyResource {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    @PermissionName(PermissionNameProvider.Name.READ_PERM)
+    public String helloPlainText(@PathParam("collectionName") String collectionName) {
+        log.info("Made it into SomeCoreResource.helloPlainText with collName {}", collectionName);

Review Comment:
   @sonatype-lift ignore



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r957767548


##########
solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java:
##########
@@ -215,54 +216,58 @@ public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
         }
       }
     } catch (Exception e) {
-      if (req.getCore() != null) {
-        boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
-        if (isTragic) {
-          if (e instanceof SolrException) {
-            // Tragic exceptions should always throw a server error
-            assert ((SolrException) e).code() == 500;
-          } else {
-            // wrap it in a solr exception
-            e = new SolrException(SolrException.ErrorCode.SERVER_ERROR, e.getMessage(), e);
-          }
-        }
-      }
-      boolean incrementErrors = true;
-      boolean isServerError = true;
-      if (e instanceof SolrException) {
-        SolrException se = (SolrException) e;
-        if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
-          incrementErrors = false;
-        } else if (se.code() >= 400 && se.code() < 500) {
-          isServerError = false;
-        }
-      } else {
-        if (e instanceof SyntaxError) {
-          isServerError = false;
-          e = new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
-        }
-      }
-
+      e = normalizeReceivedException(req, e);
+      processErrorMetricsOnException(e, metrics);
       rsp.setException(e);
+    } finally {
+      long elapsed = timer.stop();
+      metrics.totalTime.inc(elapsed);
+    }
+  }
 
-      if (incrementErrors) {
-        SolrException.log(log, e);
+  public static void processErrorMetricsOnException(Exception e, HandlerMetrics metrics) {
+    boolean isClientError = false;
+    if (e instanceof SolrException) {
+      final SolrException se = (SolrException) e;
+      if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
+        return;
+      } else if (se.code() >= 400 && se.code() < 500) {
+        isClientError = true;
+      }
+    }
 
-        metrics.numErrors.mark();
-        if (isServerError) {
-          metrics.numServerErrors.mark();
+    SolrException.log(log, e);
+    metrics.numErrors.mark();
+    if (isClientError) {
+      metrics.numClientErrors.mark();
+    } else {
+      metrics.numServerErrors.mark();
+    }
+  }
+
+  public static Exception normalizeReceivedException(SolrQueryRequest req, Exception e) {
+    if (req.getCore() != null) {
+      boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());

Review Comment:
   đŸ’Ŧ 3 similar findings have been found in this PR
   
   ---
   
   *NULL_DEREFERENCE:*  object returned by `req.getCoreContainer()` could be null and is dereferenced at line 250.
   
   ---
   
   <details><summary><b>🔎 Expand here to view all instances of this finding</b></summary><br/>
   
   <div align="center">
   
   | **File Path** | **Line Number** |
   | ------------- | ------------- |
   | solr/core/src/java/org/apache/solr/cloud/ZkController.java | [1285](https://github.com/gerlowskija/solr/blob/112dd72d41e3d472590f8cc29eedae766f81b73d/solr/core/src/java/org/apache/solr/cloud/ZkController.java#L1285)|
   | solr/core/src/java/org/apache/solr/logging/MDCLoggingContext.java | [115](https://github.com/gerlowskija/solr/blob/112dd72d41e3d472590f8cc29eedae766f81b73d/solr/core/src/java/org/apache/solr/logging/MDCLoggingContext.java#L115)|
   | solr/core/src/java/org/apache/solr/cloud/ZkController.java | [1699](https://github.com/gerlowskija/solr/blob/112dd72d41e3d472590f8cc29eedae766f81b73d/solr/core/src/java/org/apache/solr/cloud/ZkController.java#L1699)|
   <p><a href="https://lift.sonatype.com/results/github.com/apache/solr/01GBNHAB9HV5K2ZMGK4T6GD0S0?t=Infer|NULL_DEREFERENCE" target="_blank">Visit the Lift Web Console</a> to find more details in your report.</p></div></details>
   
   
   
   ---
   
   <details><summary><b>ℹī¸ Learn about @sonatype-lift commands</b></summary>
   
   You can reply with the following commands. For example, reply with ***@sonatype-lift ignoreall*** to leave out all findings.
   | **Command** | **Usage** |
   | ------------- | ------------- |
   | `@sonatype-lift ignore` | Leave out the above finding from this PR |
   | `@sonatype-lift ignoreall` | Leave out all the existing findings from this PR |
   | `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified `file\|issue\|path\|tool` from Lift findings by updating your config.toml file |
   
   **Note:** When talking to LiftBot, you need to **refresh** the page to see its response.
   <sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) to add LiftBot to another repo.</sub></details>
   
   
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=323998399&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=323998399&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=323998399&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=323998399&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=323998399&lift_comment_rating=5) ]



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r964814595


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -362,14 +363,15 @@ private void invokeJerseyRequest(CoreContainer cores, SolrCore core, Application
 
       // Set properties that may be used by Jersey filters downstream
       containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
-      containerRequest.setProperty(SolrRequestAuthorizer.CORE_CONTAINER_PROP_NAME, cores);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_REQ_PROP_NAME, req);
-      containerRequest.setProperty(SolrRequestAuthorizer.REQUEST_TYPE_PROP_NAME, requestType);
-      containerRequest.setProperty(SolrRequestAuthorizer.SOLR_PARAMS_PROP_NAME, queryParams);
-      containerRequest.setProperty(SolrRequestAuthorizer.COLLECTION_LIST_PROP_NAME, collectionsList);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_RSP_PROP_NAME, response);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);

Review Comment:
   Ah, looks like I missed the point đŸ˜Ŧ 
   
   I think the fully-qualified identifiers are from an IDE refactor and the unqualified ones were added by hand.  I'll add qualification across the board here, to keep things consistent and as-per David's preference.



##########
solr/core/src/java/org/apache/solr/jersey/RequestEventLogger.java:
##########
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out request-specific information useful for troubleshooting Jersey development.
+ *
+ * @see ApplicationEventLogger
+ */
+public class RequestEventLogger implements RequestEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount;

Review Comment:
   Happy to oblige if we do keep this class, though, see comment [here](https://github.com/apache/solr/pull/975/files#r960826852)



##########
solr/core/src/java/org/apache/solr/jersey/ApplicationEventLogger.java:
##########
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.ApplicationEvent;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out application-level information useful for troubleshooting Jersey development.
+ *
+ * @see RequestEventLogger
+ */
+public class ApplicationEventLogger implements ApplicationEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount = 0;
+
+  @Override
+  public void onEvent(ApplicationEvent event) {
+    if (log.isInfoEnabled()) {
+      log.info("Received ApplicationEvent {}", event.getType());
+    }
+  }
+
+  @Override
+  public RequestEventListener onRequest(RequestEvent requestEvent) {
+    requestCount++;
+    log.info("Starting Jersey request {}", requestCount);

Review Comment:
   ditto, re: my reply to Kevin [here](https://github.com/apache/solr/pull/975/files#r960826852)
   
   I'm not sure how useful these classes will be once the framework is in place.  I can keep them if you guys would like though



##########
solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java:
##########
@@ -215,54 +216,58 @@ public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
         }
       }
     } catch (Exception e) {
-      if (req.getCore() != null) {
-        boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
-        if (isTragic) {
-          if (e instanceof SolrException) {
-            // Tragic exceptions should always throw a server error
-            assert ((SolrException) e).code() == 500;
-          } else {
-            // wrap it in a solr exception
-            e = new SolrException(SolrException.ErrorCode.SERVER_ERROR, e.getMessage(), e);
-          }
-        }
-      }
-      boolean incrementErrors = true;
-      boolean isServerError = true;
-      if (e instanceof SolrException) {
-        SolrException se = (SolrException) e;
-        if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
-          incrementErrors = false;
-        } else if (se.code() >= 400 && se.code() < 500) {
-          isServerError = false;
-        }
-      } else {
-        if (e instanceof SyntaxError) {
-          isServerError = false;
-          e = new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
-        }
-      }
-
+      e = normalizeReceivedException(req, e);
+      processErrorMetricsOnException(e, metrics);
       rsp.setException(e);
+    } finally {
+      long elapsed = timer.stop();
+      metrics.totalTime.inc(elapsed);
+    }
+  }
 
-      if (incrementErrors) {
-        SolrException.log(log, e);
+  public static void processErrorMetricsOnException(Exception e, HandlerMetrics metrics) {
+    boolean isClientError = false;
+    if (e instanceof SolrException) {
+      final SolrException se = (SolrException) e;
+      if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
+        return;
+      } else if (se.code() >= 400 && se.code() < 500) {
+        isClientError = true;
+      }
+    }
 
-        metrics.numErrors.mark();
-        if (isServerError) {
-          metrics.numServerErrors.mark();
+    SolrException.log(log, e);
+    metrics.numErrors.mark();
+    if (isClientError) {
+      metrics.numClientErrors.mark();
+    } else {
+      metrics.numServerErrors.mark();
+    }
+  }
+
+  public static Exception normalizeReceivedException(SolrQueryRequest req, Exception e) {
+    if (req.getCore() != null) {
+      boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());

Review Comment:
   🙍  Bleh, really dislike all the 'lift' noise from code that was shifted around but not really added in the PR.  I get that even understanding what lines are "new" is a hard problem, but bleh.



##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -490,4 +532,8 @@ public Api v2lookup(String path, String method, Map<String, String> parts) {
   public ApiBag getApiBag() {
     return apiBag;
   }
+
+  public ResourceConfig getJerseyEndpoints() {

Review Comment:
   I really dislike the name "ResourceConfig" that comes out of Jersey.  So my thought process here was to abstract away the bad name as much as we can by giving this method a name that describes things more from a conceptual or functional perspective.  The main thing ResourceConfig does for us is wrap up all of the APIs/endpoints we want available on a given core, etc, so emphasizing that in the method name seemed like it'd be clearer than "getResourceConfig" or even "getJerseyResourceConfig".
   
   No rhyme or reason I didn't do the same thing to CoreContainer - I just missed updating it when I renamed the method here.  (In any case - I've deleted the method off of CC in an upcoming commit, so consistency there is a bit moot.)
   
   Anyway - I don't feel strongly about it.  Happy to change or keep if you have a preference.



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -388,33 +335,65 @@ public CompositeApi add(Api api) {
     }
   }
 
+  // We don't rely on any of Jersey's authc/z features so we pass in this empty context for
+  // all requests.
+  public static final SecurityContext DEFAULT_SECURITY_CONTEXT = new SecurityContext() {
+    public boolean isUserInRole(String role) { return false; }
+    public boolean isSecure() { return false; }
+    public Principal getUserPrincipal() { return null; }
+    public String getAuthenticationScheme() { return null; }
+  };
+
+  private void invokeJerseyRequest(CoreContainer cores, SolrCore core, ApplicationHandler jerseyHandler, SolrQueryResponse rsp) {
+    try {
+      final ContainerRequest containerRequest = ContainerRequestUtils.createContainerRequest(req, response, jerseyHandler.getConfiguration());
+
+      // Set properties that may be used by Jersey filters downstream
+      containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);
+      containerRequest.setProperty(RequestContextConstants.CORE_CONTAINER_KEY, cores);

Review Comment:
   It holds nothing but keys currently, but it's easy to imagine it holding defaults or some other type of value down the road.  I'd prefer to keep 'KEY' in these names for now, as defense against that potential confusion.
   
   I'll change if you feel strongly though.



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -273,7 +278,7 @@ public static Api getApiInfo(
     }
 
     if (api == null) {
-      return getSubPathApi(requestHandlers, path, fullPath, new CompositeApi(null));

Review Comment:
   It ended up turning into dead code as I went through the PR, so this PR removes it.  On `main` it handles some especially nested introspect APIs, but some of the other changes to V2HttpCall made these invocations superfluous.
   
   (As a larger question, I wonder whether we still see "introspect" APIs as being valuable, or whether they could be replaced or reimplemented with some of the tooling that an OpenAPI integration would offer us.  But that's a discussion for another day I think...)



##########
solr/core/src/java/org/apache/solr/jersey/ApplicationEventLogger.java:
##########
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.ApplicationEvent;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out application-level information useful for troubleshooting Jersey development.
+ *
+ * @see RequestEventLogger
+ */
+public class ApplicationEventLogger implements ApplicationEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount = 0;

Review Comment:
   Yeah, that'd be a good idea.
   
   I actually only had this class (and its partner, RequestEventLogger) around for my own personal debugging.  I intended to delete them from the PR prior to merging.
   
   I'm happy to keep them around (and make the change you suggested above) if you think they'd be a helpful aid to devs though?



##########
solr/core/src/java/org/apache/solr/core/SolrCore.java:
##########
@@ -184,7 +185,7 @@
  * to make it work. When multi-core support was added to Solr way back in version 1.3, this class
  * was required so that the core functionality could be re-used multiple times.
  */
-public final class SolrCore implements SolrInfoBean, Closeable {
+public class SolrCore implements SolrInfoBean, Closeable {

Review Comment:
   To be mock-able in tests.
   
   See SchemaNameAPITest, as an example.  The simplicity of that API maybe doesn't show the value of being able to mock SolrCore's.  (Maybe I should've picked a more involved API to convert to Jersey as an example in this PR...)
   
   Anyway, simplicity aside, you can probably imagine how being able to mock SolrCores could be helpful for unit testing in a more involved API.
   
   



##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -192,6 +200,28 @@ public Category getCategory() {
     return Category.ADMIN;
   }
 
+  public Boolean registerV2() {
+    return true;
+  }
+
+  @Override
+  public Collection<Api> getApis() {

Review Comment:
   I'm going to skip `List.of` here - `AnnotatedApi.getApis` returns a `List<Api>` itself, so there's a flattening problem with using `List.of` that's more trouble than its worth.



##########
solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java:
##########
@@ -215,54 +215,59 @@ public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
         }
       }
     } catch (Exception e) {
-      if (req.getCore() != null) {
-        boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
-        if (isTragic) {
-          if (e instanceof SolrException) {
-            // Tragic exceptions should always throw a server error
-            assert ((SolrException) e).code() == 500;
-          } else {
-            // wrap it in a solr exception
-            e = new SolrException(SolrException.ErrorCode.SERVER_ERROR, e.getMessage(), e);
-          }
-        }
-      }
-      boolean incrementErrors = true;
-      boolean isServerError = true;
-      if (e instanceof SolrException) {
-        SolrException se = (SolrException) e;
-        if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
-          incrementErrors = false;
-        } else if (se.code() >= 400 && se.code() < 500) {
-          isServerError = false;
-        }
-      } else {
-        if (e instanceof SyntaxError) {
-          isServerError = false;
-          e = new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
-        }
-      }
-
+      e = normalizeReceivedException(req, e);
+      processErrorMetricsOnException(e, metrics);
       rsp.setException(e);
+    } finally {
+      long elapsed = timer.stop();
+      metrics.totalTime.inc(elapsed);
+    }
+  }
 
-      if (incrementErrors) {
-        SolrException.log(log, e);
+  public static void processErrorMetricsOnException(Exception e, HandlerMetrics metrics) {
+    boolean isClientError = false;
+    if (e instanceof SolrException) {
+      final SolrException se = (SolrException) e;
+      if (se.code() == SolrException.ErrorCode.CONFLICT.code) {
+        return;
+      } else if (se.code() >= 400 && se.code() < 500) {
+        isClientError = true;
+      }
+    }
+
+    SolrException.log(log, e);
+    metrics.numErrors.mark();
+    if (isClientError) {
+      metrics.numClientErrors.mark();
+    } else {
+      metrics.numServerErrors.mark();
+    }
+  }
 
-        metrics.numErrors.mark();
-        if (isServerError) {
-          metrics.numServerErrors.mark();
+  public static Exception normalizeReceivedException(SolrQueryRequest req, Exception e) {
+    if (req.getCore() != null) {
+      assert req.getCoreContainer() != null;
+      boolean isTragic = req.getCoreContainer().checkTragicException(req.getCore());
+      if (isTragic) {
+        if (e instanceof SolrException) {
+          // Tragic exceptions should always throw a server error
+          assert ((SolrException) e).code() == 500;

Review Comment:
   I'm happy to add this, but this code pre-exists my PR and might change pre-existing behavior.  Figured it might not've been clear given the diff.



##########
solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaNameResponse.java:
##########
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.solr.jersey.SolrJerseyResponse;
+
+public class GetSchemaNameResponse extends SolrJerseyResponse {
+  @JsonProperty("name")
+  public String name;

Review Comment:
   We could go that route if you think there are advantages, but there's at least one tradeoff.  See the javadocs on `JerseyResource.instantiateJerseyResponse` [here](https://github.com/apache/solr/pull/975/files#diff-dc8c81d35faf30ab32e71cf916a001181724ea496ae28e5928890894e938d890R35) for some context.
   
   To attempt to summarize: an immutable response object would prevent our v2 APIs from returning the sort of "mixed" responses that Solr returns today on some errors.  I don't love this current behavior of Solr's - in fact I'd call it a bug - but breaking compatibility with it would set us afoul of some tests and bloat the diff here.



##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigSetsAPI.java:
##########
@@ -16,34 +16,41 @@
  */
 package org.apache.solr.handler.configsets;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
 import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
 
-import java.util.List;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.cloud.OverseerSolrResponse;
-import org.apache.solr.common.util.NamedList;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import org.apache.solr.api.JerseyResource;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.jersey.PermissionName;
 
 /**
  * V2 API for adding or updating a single file within a configset.
  *
  * <p>This API (GET /v2/cluster/configs) is analogous to the v1 /admin/configs?action=LIST command.
  */
-public class ListConfigSetsAPI extends ConfigSetAPIBase {
+@Path("/cluster/configs")
+public class ListConfigSetsAPI extends JerseyResource {
+
+  @Context public HttpHeaders headers;
+
+  private final CoreContainer coreContainer;
+
+  @Inject
   public ListConfigSetsAPI(CoreContainer coreContainer) {
-    super(coreContainer);
+    this.coreContainer = coreContainer;
   }
 
-  @EndPoint(method = GET, path = "/cluster/configs", permission = CONFIG_READ_PERM)
-  public void listConfigSet(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    final NamedList<Object> results = new NamedList<>();
-    List<String> configSetsList = configSetService.listConfigs();
-    results.add("configSets", configSetsList);
-    SolrResponse response = new OverseerSolrResponse(results);
-    rsp.getValues().addAll(response.getResponse());
+  @GET
+  @Produces({"application/json", "application/javabin"})
+  @PermissionName(CONFIG_READ_PERM)
+  public ListConfigsetsResponse listConfigSet() throws Exception {
+    final ListConfigsetsResponse response = new ListConfigsetsResponse();
+    response.configSets = coreContainer.getConfigSetService().listConfigs();
+    return response;

Review Comment:
   See my reply to a similar comment [here](https://github.com/apache/solr/pull/975/files#r963069506).



##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigsetsResponse.java:
##########
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import org.apache.solr.jersey.SolrJerseyResponse;
+
+/** Response body POJO for the {@link ListConfigSetsAPI} resource. */
+public class ListConfigsetsResponse extends SolrJerseyResponse {

Review Comment:
   Let's continue the discussion about immutability on other threads where you mentioned it, but happy to move the class, sure.



##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -213,6 +237,24 @@ public PluginHolder<T> put(String name, PluginHolder<T> plugin) {
                 apiBag.register(api, nameSubstitutes);
               }
             }
+
+            // TODO Should we use <requestHandler name="/blah"> to override the path that each
+            //  resource registers under?
+            Collection<Class<? extends JerseyResource>> jerseyApis =
+                apiSupport.getJerseyResources();
+            if (!CollectionUtils.isEmpty(jerseyApis)) {
+              for (Class<? extends JerseyResource> jerseyClazz : jerseyApis) {
+                if (log.isDebugEnabled()) {
+                  log.debug("Registering jersey resource class: {}", jerseyClazz.getName());
+                }
+                jerseyResources.register(jerseyClazz);
+                // See MetricsBeanFactory javadocs for a better understanding of this resource->RH
+                // mapping
+                if (inst instanceof RequestHandlerBase) {

Review Comment:
   Yes to both your points: (1) that this is sketchy code, and (2) that this is related to the method-visibility change on RHB.  I'm all for a better approach here, but I struggled for some time to find one without any luck.  Let me give a little more context around what this code is trying to do, maybe you can see an approach that I missed...
   
   This code exists to serve our metrics integration.
   
   Historically, v2 APIs got metrics "for free" because most v2 APIs were "just" a translation layer around an existing requestHandler.  Since the v2 APIs called `handler.handleRequest` at some point, the metrics code in `RequestHandlerBase` would be invoked and metrics would "just work".  Of course, this only works for v2 APIs that have a v1 equivalent.  Newer v2 APIs (e.g. `ClusterAPI.roles`) never solved the metrics question afaict.
   
   I don't like relying on RequestHandler for this functionality, but I thought it _did_ made sense to have Jersey v2 APIs keep as close as possible to the existing metrics setup.  We'd be serving our users poorly if v1 and v2 requests for the same functionality were tracked under different metrics.  Or if the metric names produced by v2 changed anytime we made an internal refactor to move a v2 API over to Jersey.  What a pain that'd be to make a dashboard for!
   
   The way I thought to implement this for Jersey APIs was to give the Jersey "resource" some pointer back to its relevant request handler, so it can initialize its metrics.  But this ended up being tricky, for two main reasons:
   
   - In a sense, the `instanceof` check here is only necessary because we're using the same container (`PluginBag`) for many different types of plugins.  If the type-param 'T' was always a RequestHandler, this code wouldn't have to do nearly as much type-juggling.  I thought about maybe creating a PluginBag subclass specific to requestHandlers, but that seems to cut against the pretty explicit intention here.  It also steps on the toes of the `RequestHandlers` class which I don't fully understand.  IMO this is still the best option, but it seems like a large refactor to drag into this (already large) PR.
   - Other simpler solutions are off the table. For example, it'd be nice if `ApiSupport.getJerseyResources` returned a collection of actual instances instead of references to JerseyResource classes.  That'd give each RequestHandler a nice, strongly-typed place to give each resource instance the metrics-context that they need.  But this doesn't work for lifecycle reasons: RequestHandlers generally live as long as the SolrCore or CoreContainer they belong to, but Jersey generally instantiates a new resource instance for each incoming request.  (Jersey _does_ allow you to change this behavior, but doing so would impose some restrictions that aren't worth the hassle IMO.)  So `getJerseyResources` has to return class references instead of nice already-bootstrapped instances.
   
   ----
   
   Anyway, hope this wasn't too long of a response.  But I share your irritation at this section, and I wanted to give you the context needed to suggest an alternative if you can think of one.  Really hoping your fresh eyes will catch an approach I missed.  I'm going to spend some time this afternoon revisiting the issue as well.



##########
solr/core/src/java/org/apache/solr/handler/api/ApiRegistrar.java:
##########
@@ -79,12 +73,4 @@ public static void registerShardApis(ApiBag apiBag, CollectionsHandler collectio
     // here for simplicity.
     apiBag.registerObject(new DeleteReplicaAPI(collectionsHandler));
   }
-
-  public static void registerConfigsetApis(ApiBag apiBag, CoreContainer container) {

Review Comment:
   It was merely moved, but it's tough to spot as it's in a totally different file now: see `ConfigSetsHandler.getApis`.
   
   In short: I created this method in ApiRegistrar during the apispec-framework migration because at the time I thought container-level APIs couldn't be registered via `SomeRequestHandler.getApis()` lookup, but I was wrong.
   
   I plan to remove ApiRegistrar altogether in a subsequent commit, but since this PR converts one of the configset APIs to JAX-RS, I decided to move those APIs here-and-now. 



##########
solr/core/src/java/org/apache/solr/api/JerseyResource.java:
##########
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.api;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_JERSEY_RESPONSE_KEY;
+
+import java.util.function.Supplier;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Context;
+import org.apache.solr.jersey.CatchAllExceptionMapper;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.servlet.HttpSolrCall;
+
+/** A marker parent type for all Jersey resource classes */

Review Comment:
   Yes, it's a rough analog to v1's SolrRequestHandler (or v2's Api).
   
   I've added these comparisons to the Javadocs here.  Let me know if you think it should get into more detail.  It's definitely worth explaining, but at the same time it's hard to give a just-thorough-enough Jersey/JAX-RS overview in Javadocs.  So if I didn't find the right balance, let me know.



##########
solr/core/src/java/org/apache/solr/jersey/MetricBeanFactory.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.PluginBag;
+import org.glassfish.hk2.api.Factory;
+
+/**
+ * Factory to inject JerseyMetricsLookupRegistry instances into Jersey resources and filters.
+ *
+ * <p>Currently, Jersey resources that have a corresponding v1 API produce the same metrics as their
+ * v1 equivalent and rely on the v1 requestHandler instance to do so. Solr facilitates this by
+ * building a map of the Jersey resource to requestHandler mapping (a {@link
+ * org.apache.solr.core.PluginBag.JerseyMetricsLookupRegistry}), and injecting it into the pre- and
+ * post- Jersey filters that handle metrics.
+ *
+ * <p>This isn't ideal, as requestHandler's don't really "fit" conceptually here. But it's
+ * unavoidable while we want our v2 APIs to exactly match the metrics produced by v1 calls.

Review Comment:
   I'd need to do a bit more research on the metric side to better understand what'd make sense.  I don't have a ton of experience working with Solr's metrics, beyond setting up the prom exporter.  That's another reason I was reluctant to strike out and do something different with them in this PR.
   
   The biggest change I can imagine from a user perspective would be that Solr could provide metrics on a per-API granularity, instead of a per-RequestHandler level.
   
   e.g. Today, `CollectionsHandler` bundles together 15 or 20 different APIs, some of which are only loosely related to one another.  Since metrics are RH-based, the request rate, total time, etc. metrics associated with CollectionsHandler lumps together collection creation requests with clusterstatus calls with shard-splits, etc.  That needn't be the case if we split from v1, which could be really cool.
   
   In terms of the implementation, we'd still have the Pre- and Post- Jersey filters that this PR introduces.  But presumably the Post- filter would invoke some sort of `recordMetrics(MetricsContext)` method defined by each JerseyResource.



##########
solr/core/src/test/org/apache/solr/handler/configsets/ListConfigSetsAPITest.java:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.ConfigSetService;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.CoreContainerFactory;
+import org.apache.solr.jersey.SolrJacksonMapper;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ListConfigSetsAPITest extends JerseyTest {
+
+  private CoreContainer mockCoreContainer;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Override
+  protected Application configure() {
+    resetMocks();
+    final ResourceConfig config = new ResourceConfig();
+    config.register(ListConfigSetsAPI.class);
+    config.register(SolrJacksonMapper.class);
+    config.register(
+        new AbstractBinder() {
+          @Override
+          protected void configure() {
+            bindFactory(new CoreContainerFactory(mockCoreContainer))
+                .to(CoreContainer.class)
+                .in(Singleton.class);
+          }
+        });
+
+    return config;
+  }
+
+  private void resetMocks() {
+    mockCoreContainer = mock(CoreContainer.class);
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsRaw() throws Exception {
+    final String expectedJson =
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}";
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final Response response = target("/cluster/configs").request().get();
+    final String jsonBody = response.readEntity(String.class);
+
+    assertEquals(200, response.getStatus());
+    assertEquals("application/json", response.getHeaders().getFirst("Content-type"));
+    assertEquals(1, 1);
+    assertEquals(
+        expectedJson,
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}");
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsTyped() throws Exception {
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final ListConfigsetsResponse response =
+        target("/cluster/configs").request().get(ListConfigsetsResponse.class);
+
+    assertNotNull(response.configSets);
+    assertNull(response.error);
+    assertEquals(2, response.configSets.size());
+    assertTrue(response.configSets.contains("cs1"));
+    assertTrue(response.configSets.contains("cs2"));
+  }
+
+  /**
+   * Test the v2 to v1 response mapping for /cluster/configs
+   *
+   * <p>{@link org.apache.solr.handler.admin.ConfigSetsHandler} uses {@link ListConfigSetsAPI} (and
+   * its response class {@link ListConfigsetsResponse}) internally to serve the v1 version of this
+   * functionality. So it's important to make sure that the v2 response stays compatible with SolrJ
+   * - both because that's important in its own right and because that ensures we haven't
+   * accidentally changed the v1 response format.
+   */
+  @Test
+  public void testListConfigsetsV1Compatibility() throws Exception {

Review Comment:
   Hah, the old integration vs unit test debate.
   
   Each has a place at the table IMO.  Integration tests do give you better fidelity for high level functionality.  I wouldn't rely on unit tests alone.  And unit tests do often need to change with the code, which is a pain.
   
   But IMO unit tests have a lot of advantages: they're faster, more targeted, run less risk of unrelated environmental issues (such as cause many of Solr's flaky build issues), allow testing of otherwise hard-to-trigger codepaths, etc.
   
   To answer your specific question about this test, I thought a unit test would be a good addition for two reasons:
   
   First, Solr has lots of integration tests around configset-listing, and I trust those to flag issues with json/xml/javabin serialization if this were to break.  But none of them are very focused on serialization.  They each leave a pretty big gap between seeing the failure and understanding the root cause and fixing it.  This test addresses that by having something very narrowly focused on just the response conversions involved, hopefully making a failure much more actionable.
   
   Second, I wanted to create an example test case based on a Jersey test-application.  The relative simplicity of the list-configset API doesn't make the point very well, but more complex APIs will benefit a lot from Jersey-framework-aided unit testing.  And I wanted to include an example of that in this PR.



##########
solr/core/src/test/org/apache/solr/handler/configsets/package-info.java:
##########
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** Testing for the org.apache.solr.handler.configsets package. */
+package org.apache.solr.handler.configsets;

Review Comment:
   I only usually add these when `check` yells at me about it - so I fear it is mandatory?  I'll remove it and see though.



##########
solr/core/src/java/org/apache/solr/jersey/RequestContextConstants.java:
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.codahale.metrics.Timer;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.security.AuthorizationContext;
+
+/**
+ * Keys used to store and retrieve values from the Jersey request context.
+ *
+ * <p>Properties are generally set in V2HttpCall's 'invokeJerseyRequest' and retrieved in individual
+ * {@link javax.ws.rs.container.ContainerRequestFilter}s using {@link
+ * ContainerRequestContext#getProperty(String)}
+ */
+public class RequestContextConstants {

Review Comment:
   Neat, I'll try it out.  Does anything stop folks from extending/instantiating them the way the private-ctor does in a class?



##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   Yep, there's definitely stuff in Solr responses that's not covered here, yet. `echoParams` being a good example.  But my thought was that those gaps could be filled as we move forward, in our standard progress-not-perfection fashion.
   
   As we move v2 APIs to JAX-RS, we're going to hit tests that exercise e.g. echoParams, and that'll serve as a forcing function to get coverage for those additional fields here.
   
   I can imagine some rigidity issues: like if we had two APIs that used the same key within a responseHeader to store different types.  But there are tools/patterns for handling those as they come up, so IMO a strongly-typed response was still worth trying.
   
   But maybe I'm missing the specifics of your concern?  Was it primarily around incompleteness, or rigidity, or something else?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966121020


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   Turns out I had to fight SolrJ a bit to get this working.  I've pushed up a commit to get it working (see [here](https://github.com/apache/solr/pull/975/commits/565fb9cd3c37c5572d7ea9a4c9007dd623627c18) ), but I'm on the fence whether we should include it in this PR or whether it'd be better to stick with "application/octet-stream" for now and switch the mime type down the road.
   
   The root of the issue is that the `getContentType()` method on SolrJ's `ResponseParser` interface returns a single string.  That is, ResponseParsers declare a single content-type that they can handle, and SolrJ will throw an error if Solr's response comes back with any other 'Content-Type' value.  This is a problem for us since we want BinaryResponseParser to support the new media type while maintaining compatibility with existing v1 and v2 requests that return `application/octet-stream`.
   
   The linked commit works around this by adds a `ResponseParser.getContentTypes()` (note the plural) method for returning multiple content-types, deprecates the existing "single-string" `getContentType`, and updates the SolrClient usage to rely on the new method.  



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965949607


##########
solr/core/src/test/org/apache/solr/handler/configsets/ListConfigSetsAPITest.java:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.ConfigSetService;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.CoreContainerFactory;
+import org.apache.solr.jersey.SolrJacksonMapper;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ListConfigSetsAPITest extends JerseyTest {
+
+  private CoreContainer mockCoreContainer;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Override
+  protected Application configure() {
+    resetMocks();
+    final ResourceConfig config = new ResourceConfig();
+    config.register(ListConfigSetsAPI.class);
+    config.register(SolrJacksonMapper.class);
+    config.register(
+        new AbstractBinder() {
+          @Override
+          protected void configure() {
+            bindFactory(new CoreContainerFactory(mockCoreContainer))
+                .to(CoreContainer.class)
+                .in(Singleton.class);
+          }
+        });
+
+    return config;
+  }
+
+  private void resetMocks() {
+    mockCoreContainer = mock(CoreContainer.class);
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsRaw() throws Exception {
+    final String expectedJson =
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}";
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final Response response = target("/cluster/configs").request().get();
+    final String jsonBody = response.readEntity(String.class);
+
+    assertEquals(200, response.getStatus());
+    assertEquals("application/json", response.getHeaders().getFirst("Content-type"));
+    assertEquals(1, 1);
+    assertEquals(
+        expectedJson,
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}");
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsTyped() throws Exception {
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final ListConfigsetsResponse response =
+        target("/cluster/configs").request().get(ListConfigsetsResponse.class);
+
+    assertNotNull(response.configSets);
+    assertNull(response.error);
+    assertEquals(2, response.configSets.size());
+    assertTrue(response.configSets.contains("cs1"));
+    assertTrue(response.configSets.contains("cs2"));
+  }
+
+  /**
+   * Test the v2 to v1 response mapping for /cluster/configs
+   *
+   * <p>{@link org.apache.solr.handler.admin.ConfigSetsHandler} uses {@link ListConfigSetsAPI} (and
+   * its response class {@link ListConfigsetsResponse}) internally to serve the v1 version of this
+   * functionality. So it's important to make sure that the v2 response stays compatible with SolrJ
+   * - both because that's important in its own right and because that ensures we haven't
+   * accidentally changed the v1 response format.
+   */
+  @Test
+  public void testListConfigsetsV1Compatibility() throws Exception {

Review Comment:
   Ok, that makes sense I think.  I agree we don't want these tests all over the place when there's SolrJ level integration (or "integration-ish") tests that already validate the same thing.
   
   I'll add a comment on this class that indicates its role as an example/model.  I also plan on adding some dev-docs to cover our current API framework(s) and the Jersey integration.  So I can point to this class from there, but make it clear that this sort of testing should be reserved for situations that are hard to cover other ways.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on PR #975:
URL: https://github.com/apache/solr/pull/975#issuecomment-1240915352

   Found a buried question from @dsmiley that I'd failed to answer:
   
   > do you think your work here might be better characterized as a V3 API rather than changing V2? Of course we agreed to change V2 as we see fit but I'm just wondering if you are hampered by lots of code already existing for V2. 
   
   In some ways this work does _feel_ like a v3 effort.  Particularly because we're integrating a new (to Solr) API framework.  But from the user or API-consumer perspective I think this is "just" v2 hardening and refactoring.  We're not introducing new APIs that will exist alongside their v2 counterparts, etc.  So I personally tend to think of this work as "v2".
   
   In terms of the development, the existing v2 code hasn't done too much "hampering".  Of course, in terms of this specific PR, it's been a big pain to add JAX-RS support to V2HttpCall while still keeping the existing `Api` and introspect codepaths there working.  But I don't see that being much of a problem on an api-by-api basis as we add new or convert existing endpoints over to JAX-RS. 
   
   > Lots of V2 classes could be marked Deprecated to communicate our intent to not take it into the future. 
   
   I'm all for deprecating some of the existing (but now legacy?) v2 framework, especially: `Api`, `ApiBag`, `ApiSupport`, `Command`, `PayloadObj`, `AnnotatedApi`, etc.
   
   I'd probably wait on adding those deprecations until we have a bit more history converting things over to JAX-RS, but in a few month's time I'd love to push up a PR for that.  I don't want to put the "cart before the horse" there though.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] risdenk commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
risdenk commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r960818330


##########
solr/core/src/java/org/apache/solr/jersey/PostRequestDecorationFilter.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+
+/**
+ * Applies standard post-processing decorations to a {@link SolrJerseyResponse} that are needed on all responses.
+ *
+ * @see SolrCore#postDecorateResponse(SolrRequestHandler, SolrQueryRequest, SolrQueryResponse)
+ */
+public class PostRequestDecorationFilter implements ContainerResponseFilter {
+
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+        final SolrQueryRequest solrQueryRequest = (SolrQueryRequest) requestContext.getProperty(SOLR_QUERY_REQUEST_KEY);
+        if ( ! responseContext.hasEntity() || ! SolrJerseyResponse.class.isInstance(responseContext.getEntity())) {
+            log.debug("Skipping QTime assignment because response was not a SolrJerseyResponse");

Review Comment:
   `qtime` is definitely useful for some quick performance checks if you are running some queries. I also know I've seen it be helpful if there are query timeouts just to see how long the result took. Easier than trying to coordinate in the logs. Not sure outside of that.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] risdenk commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
risdenk commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r960824509


##########
solr/core/src/java/org/apache/solr/handler/SchemaHandler.java:
##########
@@ -333,6 +330,13 @@ public Collection<Api> getApis() {
     return apis;
   }
 
+  @Override
+  public Collection<Class<? extends JerseyResource>> getJerseyResources() {
+    final List<Class<? extends JerseyResource>> jerseyResources = new ArrayList<>();
+    jerseyResources.add(SchemaNameAPI.class);
+    return jerseyResources;

Review Comment:
   Possibly use `List.of` - https://docs.oracle.com/javase/9/docs/api/java/util/List.html#of-E-



##########
solr/core/src/test/org/apache/solr/handler/admin/api/SchemaNameAPITest.java:
##########
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.response.schema.SchemaResponse;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.SchemaHandler;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.schema.IndexSchema;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+//  These tests create SchemaNameAPI instances directly, which is valuable. But they don't test that
+// the JAX-RS annotations
+//  or resource-matching is correct.  Should we have other tests to exercise that, or is relying on
+// Solr's existing
+//  testing of this API sufficient?

Review Comment:
   nit: wrapping of the comment seems weird. most likely spotless reformatted this



##########
solr/core/build.gradle:
##########
@@ -182,6 +191,10 @@ dependencies {
   testImplementation 'junit:junit'
   testImplementation 'org.hamcrest:hamcrest'
 
+  testImplementation 'org.glassfish.jersey.test-framework:jersey-test-framework-core:2.35'
+  testImplementation 'org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:2.35'

Review Comment:
   Should these version specifications be here? 



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -362,14 +363,15 @@ private void invokeJerseyRequest(CoreContainer cores, SolrCore core, Application
 
       // Set properties that may be used by Jersey filters downstream
       containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
-      containerRequest.setProperty(SolrRequestAuthorizer.CORE_CONTAINER_PROP_NAME, cores);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_REQ_PROP_NAME, req);
-      containerRequest.setProperty(SolrRequestAuthorizer.REQUEST_TYPE_PROP_NAME, requestType);
-      containerRequest.setProperty(SolrRequestAuthorizer.SOLR_PARAMS_PROP_NAME, queryParams);
-      containerRequest.setProperty(SolrRequestAuthorizer.COLLECTION_LIST_PROP_NAME, collectionsList);
-      containerRequest.setProperty(SolrRequestAuthorizer.HTTP_SERVLET_RSP_PROP_NAME, response);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);

Review Comment:
   I think the point being for consistency with the lines below this?



##########
solr/core/src/java/org/apache/solr/jersey/ApplicationEventLogger.java:
##########
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.ApplicationEvent;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out application-level information useful for troubleshooting Jersey development.
+ *
+ * @see RequestEventLogger
+ */
+public class ApplicationEventLogger implements ApplicationEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount = 0;

Review Comment:
   Could use `AtomicLong` - https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicLong.html



##########
solr/core/src/java/org/apache/solr/jersey/RequestEventLogger.java:
##########
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out request-specific information useful for troubleshooting Jersey development.
+ *
+ * @see ApplicationEventLogger
+ */
+public class RequestEventLogger implements RequestEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount;

Review Comment:
   Could use `AtomicLong` - https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicLong.html



##########
solr/core/src/java/org/apache/solr/jersey/PostRequestDecorationFilter.java:
##########
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Applies standard post-processing decorations to a {@link SolrJerseyResponse} that are needed on
+ * all responses.
+ *
+ * @see SolrCore#postDecorateResponse(SolrRequestHandler, SolrQueryRequest, SolrQueryResponse)
+ */
+public class PostRequestDecorationFilter implements ContainerResponseFilter {
+
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  @Override
+  public void filter(
+      ContainerRequestContext requestContext, ContainerResponseContext responseContext)
+      throws IOException {
+    final SolrQueryRequest solrQueryRequest =
+        (SolrQueryRequest) requestContext.getProperty(SOLR_QUERY_REQUEST_KEY);
+    if (!responseContext.hasEntity()
+        || !SolrJerseyResponse.class.isInstance(responseContext.getEntity())) {
+      log.debug("Skipping QTime assignment because response was not a SolrJerseyResponse");
+      return;
+    }
+
+    log.info("JEGERLOW: Setting QTime");

Review Comment:
   Nit: leftover logging?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r957795657


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   interesting....    And maybe going to make me sad in the future?    Do we actually want a javabin version for this API????



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966259877


##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   Oh for sure - very much looking forward to seeing the strong-typing start to cut down on the NamedList/Map types that just absolutely abound across the codebase.
   
   How do you want to go forward on the rigidity issue?  Is that something you'd be fine deferring to a follow-up PR, or would you like to see that fixed here?  And either way, do you have a preference between the two potential solutions above?
   
   My preference would be to go the Jackson "additional properties" route on `ResponseHeader` - that'd allow us to at least keep strong typing for the few header entries we know about.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965992444


##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   Just to re-iterate my support for strong-typing, I'd say a huge aspect of the benefits / point of this big PR is for us to get strong typing!  A major win.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966312263


##########
solr/solrj/src/java/org/apache/solr/client/solrj/ResponseParser.java:
##########
@@ -34,11 +37,22 @@ public abstract class ResponseParser {
    * A well behaved ResponseParser will return its content-type.
    *
    * @return the content-type this parser expects to parse
+   * @deprecated use {@link #getContentTypes()} instead
    */
+  @Deprecated
   public String getContentType() {

Review Comment:
   *[InlineMeSuggester](https://errorprone.info/bugpattern/InlineMeSuggester):*  This deprecated API looks inlineable. If you'd like the body of the API to be inlined to its callers, please annotate it with @InlineMe.
   
   ---
   
   
   ```suggestion
     @InlineMe(replacement = "null")
   ```
   
   
   
   ---
   
   <details><summary><b>ℹī¸ Learn about @sonatype-lift commands</b></summary>
   
   You can reply with the following commands. For example, reply with ***@sonatype-lift ignoreall*** to leave out all findings.
   | **Command** | **Usage** |
   | ------------- | ------------- |
   | `@sonatype-lift ignore` | Leave out the above finding from this PR |
   | `@sonatype-lift ignoreall` | Leave out all the existing findings from this PR |
   | `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified `file\|issue\|path\|tool` from Lift findings by updating your config.toml file |
   
   **Note:** When talking to LiftBot, you need to **refresh** the page to see its response.
   <sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) to add LiftBot to another repo.</sub></details>
   
   
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=329346514&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=329346514&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=329346514&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=329346514&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=329346514&lift_comment_rating=5) ]



##########
solr/core/src/java/org/apache/solr/jersey/container/ContainerRequestUtils.java:
##########
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey.container;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.Principal;
+import java.util.Enumeration;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.SecurityContext;
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.internal.ContainerUtils;
+import org.glassfish.jersey.server.spi.ContainerResponseWriter;
+
+/**
+ * Utility methods for creating and populating a {@link
+ * org.glassfish.jersey.server.ContainerRequest} for use with Jersey {@link
+ * org.glassfish.jersey.server.ApplicationHandler}s
+ */
+public class ContainerRequestUtils {
+  private ContainerRequestUtils() {
+    /* Private ctor prevents instantiation */
+  }
+
+  // We don't rely on any of Jersey's authc/z features so we pass in this empty context for
+  // all requests.
+  public static final SecurityContext DEFAULT_SECURITY_CONTEXT =
+      new SecurityContext() {
+        public boolean isUserInRole(String role) {
+          return false;
+        }
+
+        public boolean isSecure() {
+          return false;
+        }
+
+        public Principal getUserPrincipal() {
+          return null;
+        }
+
+        public String getAuthenticationScheme() {
+          return null;
+        }
+      };
+
+  /**
+   * Creates a {@link ContainerRequest}
+   *
+   * <p>Implementation guided by code in 'jersey-container-jetty-http's JettyHttpContainer class.
+   */
+  public static ContainerRequest createContainerRequest(
+      HttpServletRequest httpServletRequest,
+      HttpServletResponse httpServletResponse,
+      Configuration appConfig) {
+    final ContainerResponseWriter responseWriter =
+        new JettyBridgeResponseWriter(httpServletResponse);
+    try {
+      final URI baseUri = getBaseUri(httpServletRequest);
+      final URI requestUri = getRequestUri(httpServletRequest, baseUri);
+      final ContainerRequest requestContext =
+          new ContainerRequest(
+              baseUri,
+              requestUri,
+              httpServletRequest.getMethod(),
+              DEFAULT_SECURITY_CONTEXT,
+              new MapPropertiesDelegate(),
+              appConfig);
+      requestContext.setEntityStream(httpServletRequest.getInputStream());
+      final Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
+      while (headerNames.hasMoreElements()) {
+        final String headerName = headerNames.nextElement();
+        String headerValue = httpServletRequest.getHeader(headerName);
+        requestContext.headers(headerName, headerValue == null ? "" : headerValue);
+      }
+      requestContext.setWriter(responseWriter);
+      return requestContext;
+    } catch (Exception e) {
+      // TODO Should we handle URISyntaxException any differently here?
+      throw new RuntimeException(e);
+    }
+  }
+
+  private static URI getBaseUri(HttpServletRequest httpServletRequest) {
+    try {
+      return new URI(
+          httpServletRequest.getScheme(),
+          null,
+          httpServletRequest.getServerName(),
+          httpServletRequest.getServerPort(),
+          getBasePath(httpServletRequest),
+          null,
+          null);
+    } catch (final URISyntaxException ex) {
+      throw new IllegalArgumentException(ex);
+    }
+  }
+
+  private static String getBasePath(HttpServletRequest httpServletRequest) {

Review Comment:
   *[UnusedVariable](https://errorprone.info/bugpattern/UnusedVariable):*  The parameter 'httpServletRequest' is never read.
   
   ---
   
   
   ```suggestion
     getBasePath(),
   ```
   
   
   
   ---
   
   <details><summary><b>ℹī¸ Learn about @sonatype-lift commands</b></summary>
   
   You can reply with the following commands. For example, reply with ***@sonatype-lift ignoreall*** to leave out all findings.
   | **Command** | **Usage** |
   | ------------- | ------------- |
   | `@sonatype-lift ignore` | Leave out the above finding from this PR |
   | `@sonatype-lift ignoreall` | Leave out all the existing findings from this PR |
   | `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified `file\|issue\|path\|tool` from Lift findings by updating your config.toml file |
   
   **Note:** When talking to LiftBot, you need to **refresh** the page to see its response.
   <sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) to add LiftBot to another repo.</sub></details>
   
   
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=329346832&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=329346832&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=329346832&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=329346832&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=329346832&lift_comment_rating=5) ]



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965970532


##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   Oh, no, not at all.  We've got a few options to handle cases like that:
   
   1. Individual APIs (e.g. `/select`) can still choose to return `NamedList<Object>` or other loosely typed objects instead of the "stronger" SolrJerseyResponse.  I think we should still strive to be strongly typed where-ever possible, but nothing about JAX-RS _requires_ this on any given API.  Loose-typing might be best for `/select`, which as you point out can have any number of custom SearchComponents that modify the response.
   2. Alternatively, there are ways to get some of this flexibility in a strongly-typed object.  e.g. [Jackson's support for "additional properties"](https://stackoverflow.com/questions/39156293/jackson-deserialize-extra-fields-as-map).  It might take some work to expand a solution of this sort out to xml, javabin, etc. but it seems do-able if this is an approach we like.  



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r968926308


##########
solr/solrj/src/java/org/apache/solr/client/solrj/ResponseParser.java:
##########
@@ -34,11 +37,22 @@ public abstract class ResponseParser {
    * A well behaved ResponseParser will return its content-type.
    *
    * @return the content-type this parser expects to parse
+   * @deprecated use {@link #getContentTypes()} instead
    */
+  @Deprecated
   public String getContentType() {

Review Comment:
   Please add or enhance your `.lift/config.toml` entry to include:
   
   ```
   ignoreRules = [ "InlineMeSuggester" ]
   ```
   
   See the [Lift documentation](https://help.sonatype.com/lift/configuring-lift/build-and-.toml-details) for more.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r969831939


##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   I just added some "additional properties" support, making use of the JsonAnyGetter/JsonAnySetter annotation pair described in the link we discussed above.  Jackson is able to use those annotations natively.
   
   Also needed a few changes to `Utils.reflectWrite` to actually get this working for XML, javabin, etc.  Which isn't ideal, but is a reality of the way our MapWriter/ResponseWriter stuff works today.  We already depend on Jackson on the server-side, and it supports other formats - I wonder if we couldn't just use it for XML, etc. at some point in the future.  But that's of course a large and very different task.  Just thinking aloud here I guess...



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r950237226


##########
solr/core/src/java/org/apache/solr/handler/api/SomeCoreResource.java:
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.api;
+
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.security.PermissionNameProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.lang.invoke.MethodHandles;
+
+@Path("/collections/{collectionName}/somecorepath")
+public class SomeCoreResource extends JerseyResource {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    @PermissionName(PermissionNameProvider.Name.READ_PERM)
+    public String helloPlainText(@PathParam("collectionName") String collectionName) {
+        log.info("Made it into SomeCoreResource.helloPlainText with collName {}", collectionName);

Review Comment:
   I've recorded this as ignored for this pull request.
   If you change your mind, just comment `@sonatype-lift unignore`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r952142394


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -157,20 +168,16 @@ public void call(SolrQueryRequest req, SolrQueryResponse rsp) {
         origCorename = pathSegments.get(1);
         core = cores.getCore(origCorename);
       }
+
+      // We didn't find a core, so we're either an error or a Jersey 'ADMIN' api
       if (core == null) {
-        log.error(">> path: '{}'", path);
-        if (path.endsWith(CommonParams.INTROSPECT)) {
-          initAdminRequest(path);
-          return;
-        } else {
-          throw new SolrException(
-              SolrException.ErrorCode.NOT_FOUND,
-              "no core retrieved for core name: " + origCorename + ". Path: " + path);
-        }
-      } else {
-        Thread.currentThread().setContextClassLoader(core.getResourceLoader().getClassLoader());
+        // This codepath needs to cover custom plugin Jersey APIs, as well as in-built ones
+        log.info("Hoping this path is covered by the Jersey-admin case: {}", path);

Review Comment:
   I recommend use of "nocommit" for this and anything else that's not supposed to be merged



##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigSetsAPI.java:
##########
@@ -16,34 +16,54 @@
  */
 package org.apache.solr.handler.configsets;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
-
-import java.util.List;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.cloud.OverseerSolrResponse;
-import org.apache.solr.common.util.NamedList;
+import org.apache.solr.api.JerseyResource;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.jersey.PermissionName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
 
 /**
  * V2 API for adding or updating a single file within a configset.
  *
  * <p>This API (GET /v2/cluster/configs) is analogous to the v1 /admin/configs?action=LIST command.
  */
-public class ListConfigSetsAPI extends ConfigSetAPIBase {
+
+@Path("/cluster/configs")

Review Comment:
   I love how this makes it clear how this handler is accessed.  Formerly, you'd have to cross your fingers that it might be documented (it was here but is maybe outdated soon).



##########
solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java:
##########
@@ -75,6 +77,18 @@ public static boolean isAutoGeneratedConfigSet(String configName) {
     return configName != null && configName.endsWith(AUTOCREATED_CONFIGSET_SUFFIX);
   }
 
+  private void squashIntoSolrResponse(SolrQueryResponse rsp, ReflectMapWriter mw) {
+    Map<String, Object> myMap = new HashMap<>();
+    myMap = mw.toMap(myMap);
+    if (myMap.isEmpty()) {
+      log.info("Hmm, map is empty after writing in values from {}", mw);
+    }
+    for (String key : myMap.keySet()) {
+      log.info("Adding key={}, value={} to rsp", key, myMap.get(key));

Review Comment:
   Good feedback



##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigsetsResponse.java:
##########
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class ListConfigsetsResponse extends SolrJerseyResponse {
+
+    //TODO We use both JsonProperty annotations here becaues the v2 serialization code expects Jackson, but
+    // ReflectMapWriter (which we use to squash the typed v2 response into a SolrQueryResponse for v1 code) relies on

Review Comment:
   Maybe it could use reflection to support both.  ReflectMapWriter is in SolrJ so it can't reference Jackson.  `CreateAliasPayload` and lots of other DTOs are in SolrJ with annotations.



##########
solr/core/src/java/org/apache/solr/handler/api/SomeCoreResource.java:
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.api;
+
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.security.PermissionNameProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.lang.invoke.MethodHandles;
+
+@Path("/collections/{collectionName}/somecorepath")
+public class SomeCoreResource extends JerseyResource {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    @PermissionName(PermissionNameProvider.Name.READ_PERM)
+    public String helloPlainText(@PathParam("collectionName") String collectionName) {
+        log.info("Made it into SomeCoreResource.helloPlainText with collName {}", collectionName);

Review Comment:
   This category of detection is not worth it IMO; I'll configure Lift to ignore it.



##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigSetsAPI.java:
##########
@@ -16,34 +16,54 @@
  */
 package org.apache.solr.handler.configsets;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
-
-import java.util.List;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.cloud.OverseerSolrResponse;
-import org.apache.solr.common.util.NamedList;
+import org.apache.solr.api.JerseyResource;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.jersey.PermissionName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
 
 /**
  * V2 API for adding or updating a single file within a configset.
  *
  * <p>This API (GET /v2/cluster/configs) is analogous to the v1 /admin/configs?action=LIST command.
  */
-public class ListConfigSetsAPI extends ConfigSetAPIBase {
+
+@Path("/cluster/configs")
+public class ListConfigSetsAPI extends JerseyResource {
+
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  @Context
+  public HttpHeaders headers;
+
+  private final CoreContainer coreContainer;
+
+  @Inject
   public ListConfigSetsAPI(CoreContainer coreContainer) {
-    super(coreContainer);
+    this.coreContainer = coreContainer;
   }
 
-  @EndPoint(method = GET, path = "/cluster/configs", permission = CONFIG_READ_PERM)
-  public void listConfigSet(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    final NamedList<Object> results = new NamedList<>();
-    List<String> configSetsList = configSetService.listConfigs();
-    results.add("configSets", configSetsList);
-    SolrResponse response = new OverseerSolrResponse(results);
-    rsp.getValues().addAll(response.getResponse());
+
+  @GET
+  @Produces({"application/json", "application/javabin"})
+  @PermissionName(CONFIG_READ_PERM)
+  public ListConfigsetsResponse listConfigSet() throws Exception {
+    log.info("CoreContainer={}, HttpHeaders.accept={}", coreContainer, (headers != null) ? headers.getAcceptableMediaTypes() : "null");

Review Comment:
   I'm doubtful we need to log for each of our API entry-points when we already have a catch-all approach.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on PR #975:
URL: https://github.com/apache/solr/pull/975#issuecomment-1234459810

   > I think this is looking great... Time to remove the "Draft" tag?
   
   Done 🎉 !  This should be getting pretty close.  I need to merge in `main` to resolve some conflicts and address some remaining review comments, but I've added tests for much of the Jersey functionality, have precommit passing, etc.
   
   I'd love to get this into shape and merged in time for a weekend of Jenkins feedback, but that might be pushing things a little too much.  We'll see.
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r959821515


##########
solr/core/src/java/org/apache/solr/jersey/PostRequestDecorationFilter.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+
+/**
+ * Applies standard post-processing decorations to a {@link SolrJerseyResponse} that are needed on all responses.
+ *
+ * @see SolrCore#postDecorateResponse(SolrRequestHandler, SolrQueryRequest, SolrQueryResponse)
+ */
+public class PostRequestDecorationFilter implements ContainerResponseFilter {
+
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+        final SolrQueryRequest solrQueryRequest = (SolrQueryRequest) requestContext.getProperty(SOLR_QUERY_REQUEST_KEY);
+        if ( ! responseContext.hasEntity() || ! SolrJerseyResponse.class.isInstance(responseContext.getEntity())) {
+            log.debug("Skipping QTime assignment because response was not a SolrJerseyResponse");

Review Comment:
   Having the field at all...    I tried to find a nice authoritative article that says "in rest design, QTime (or it's like), is a bad idea", but honestly, I didn't find it.   And it is nice to see which api calls take a long time to run!   So, I guess, this is cool feature of Solr!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r957747370


##########
solr/core/src/java/org/apache/solr/jersey/MessageBodyWriters.java:
##########
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.common.util.JavaBinCodec;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.QueryResponseWriterUtil;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.response.XMLResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Type;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_RESPONSE_KEY;
+
+
+public class MessageBodyWriters {
+
+    /**
+     * Registers a JAX-RS {@link MessageBodyWriter} that's used to return a javabin response when the request contains
+     * the "Accept: application/javabin" header.
+     */
+    @Produces("application/javabin")
+    public static class JavabinMessageBodyWriter implements MessageBodyWriter<JacksonReflectMapWriter> {
+
+        private final JavaBinCodec javaBinCodec;
+
+        public JavabinMessageBodyWriter() {
+            this.javaBinCodec = new JavaBinCodec();
+        }
+
+        @Override
+        public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+            return mediaType.equals(new MediaType("application", "javabin"));
+        }
+
+        @Override
+        public void writeTo(JacksonReflectMapWriter reflectMapWriter, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
+            javaBinCodec.marshal(reflectMapWriter, entityStream);
+        }
+    }
+
+    // TODO This pattern should be appropriate for any QueryResponseWriter supported elsewhere in Solr.  Write a base
+    //  class to remove all duplication from these content-specific implementations.
+    @Produces("application/xml")
+    public static class XmlMessageBodyWriter implements MessageBodyWriter<JacksonReflectMapWriter> {
+
+        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

Review Comment:
   *[UnusedVariable](https://errorprone.info/bugpattern/UnusedVariable):*  The field 'log' is never read.
   
   ---
   
   Reply with *"**@sonatype-lift help**"* for info about LiftBot commands.
   Reply with *"**@sonatype-lift ignore**"* to tell LiftBot to leave out the above finding from this PR.
   Reply with *"**@sonatype-lift ignoreall**"* to tell LiftBot to leave out all the findings from this PR and from the status bar in Github.
   
   When talking to LiftBot, you need to **refresh** the page to see its response. [Click here](https://help.sonatype.com/lift/talking-to-lift) to get to know more about LiftBot commands.
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=323967933&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=323967933&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=323967933&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=323967933&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=323967933&lift_comment_rating=5) ]



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r959815458


##########
solr/core/src/java/org/apache/solr/jersey/PostRequestDecorationFilter.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+
+/**
+ * Applies standard post-processing decorations to a {@link SolrJerseyResponse} that are needed on all responses.
+ *
+ * @see SolrCore#postDecorateResponse(SolrRequestHandler, SolrQueryRequest, SolrQueryResponse)
+ */
+public class PostRequestDecorationFilter implements ContainerResponseFilter {
+
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+        final SolrQueryRequest solrQueryRequest = (SolrQueryRequest) requestContext.getProperty(SOLR_QUERY_REQUEST_KEY);
+        if ( ! responseContext.hasEntity() || ! SolrJerseyResponse.class.isInstance(responseContext.getEntity())) {
+            log.debug("Skipping QTime assignment because response was not a SolrJerseyResponse");

Review Comment:
   Do you mean in terms of a field name?  Or it terms of having the field at all?
   
   I don't care for the name.  But having a field to return this info seems reasonable to me?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965280828


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -388,33 +335,65 @@ public CompositeApi add(Api api) {
     }
   }
 
+  // We don't rely on any of Jersey's authc/z features so we pass in this empty context for
+  // all requests.
+  public static final SecurityContext DEFAULT_SECURITY_CONTEXT = new SecurityContext() {
+    public boolean isUserInRole(String role) { return false; }
+    public boolean isSecure() { return false; }
+    public Principal getUserPrincipal() { return null; }
+    public String getAuthenticationScheme() { return null; }
+  };
+
+  private void invokeJerseyRequest(CoreContainer cores, SolrCore core, ApplicationHandler jerseyHandler, SolrQueryResponse rsp) {
+    try {
+      final ContainerRequest containerRequest = ContainerRequestUtils.createContainerRequest(req, response, jerseyHandler.getConfiguration());
+
+      // Set properties that may be used by Jersey filters downstream
+      containerRequest.setProperty(SOLR_QUERY_REQUEST_KEY, solrReq);
+      containerRequest.setProperty(SOLR_QUERY_RESPONSE_KEY, rsp);
+      containerRequest.setProperty(RequestContextConstants.CORE_CONTAINER_KEY, cores);

Review Comment:
   Then let's add a comment to say these are *only* for keys into this map?  Or even better, call this class RequestContextKeys



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -462,9 +462,10 @@ private String computeEndpointPath() {
   protected void writeResponse(
       SolrQueryResponse solrRsp, QueryResponseWriter responseWriter, Method reqMethod)
       throws IOException {
-    // JAX-RS has its own code that flushes out the Response to the relevant output stream, so we no-op here if the
+    // JAX-RS has its own code that flushes out the Response to the relevant output stream, so we
+    // no-op here if the
     // request was already handled via JAX-RS

Review Comment:
   reflow this (probably due to spotless)



##########
solr/core/src/test/org/apache/solr/handler/configsets/ListConfigSetsAPITest.java:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.ConfigSetService;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.CoreContainerFactory;
+import org.apache.solr.jersey.SolrJacksonMapper;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ListConfigSetsAPITest extends JerseyTest {
+
+  private CoreContainer mockCoreContainer;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Override
+  protected Application configure() {
+    resetMocks();
+    final ResourceConfig config = new ResourceConfig();
+    config.register(ListConfigSetsAPI.class);
+    config.register(SolrJacksonMapper.class);
+    config.register(
+        new AbstractBinder() {
+          @Override
+          protected void configure() {
+            bindFactory(new CoreContainerFactory(mockCoreContainer))
+                .to(CoreContainer.class)
+                .in(Singleton.class);
+          }
+        });
+
+    return config;
+  }
+
+  private void resetMocks() {
+    mockCoreContainer = mock(CoreContainer.class);
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsRaw() throws Exception {
+    final String expectedJson =
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}";
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final Response response = target("/cluster/configs").request().get();
+    final String jsonBody = response.readEntity(String.class);
+
+    assertEquals(200, response.getStatus());
+    assertEquals("application/json", response.getHeaders().getFirst("Content-type"));
+    assertEquals(1, 1);
+    assertEquals(
+        expectedJson,
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}");
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsTyped() throws Exception {
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final ListConfigsetsResponse response =
+        target("/cluster/configs").request().get(ListConfigsetsResponse.class);
+
+    assertNotNull(response.configSets);
+    assertNull(response.error);
+    assertEquals(2, response.configSets.size());
+    assertTrue(response.configSets.contains("cs1"));
+    assertTrue(response.configSets.contains("cs2"));
+  }
+
+  /**
+   * Test the v2 to v1 response mapping for /cluster/configs
+   *
+   * <p>{@link org.apache.solr.handler.admin.ConfigSetsHandler} uses {@link ListConfigSetsAPI} (and
+   * its response class {@link ListConfigsetsResponse}) internally to serve the v1 version of this
+   * functionality. So it's important to make sure that the v2 response stays compatible with SolrJ
+   * - both because that's important in its own right and because that ensures we haven't
+   * accidentally changed the v1 response format.
+   */
+  @Test
+  public void testListConfigsetsV1Compatibility() throws Exception {

Review Comment:
   I get the trade-offs!  Tests have a cost and I'm much more weary than you are of the quicksand/internals cost of testing Jersey specifics being a barrier for change.  I see this in other code bases too, e.g. testing low-level token-filters _too much_ and not enough at the high level capturing the effective impact.  I don't mind debugging higher level tests because tests _generally_ continue to pass forever until you do the one thing that breaks something, which is a massive clue.  Your second argument makes sense; let's just not repeat this test approach in lots of places for all APIs, please.  For example, this test might be named to reflect this is a how-to or testing Jersey.
   
   BTW when I said test XML/JSON, I should say, test via SolrJ (using Javabin) is great too especially because of Java deficiencies around multi-line string-literals (eventually solved in a later Java release).  My preference is generally at the SolrJ level when possible, not actually XML/JSON but these are very close layers to test at (still fairly integration-y).  SolrJ via EmbeddedSolrServer is fast, skipping Jetty/HTTP.
   



##########
solr/core/src/java/org/apache/solr/jersey/CatchAllExceptionMapper.java:
##########
@@ -93,10 +98,12 @@ public Response toResponse(Exception exception) {
       RequestHandlerBase.processErrorMetricsOnException(normalizedException, metrics);
     }
 
-    // Then, convert the exception into a SolrJerseyResponse (creating one as necessary if resource was matched, etc.)
-    final SolrJerseyResponse response = containerRequestContext.getProperty(SOLR_JERSEY_RESPONSE_KEY) == null ?
-            new SolrJerseyResponse() :
-            (SolrJerseyResponse) containerRequestContext.getProperty(SOLR_JERSEY_RESPONSE_KEY);
+    // Then, convert the exception into a SolrJerseyResponse (creating one as necessary if resource
+    // was matched, etc.)

Review Comment:
   more reflow



##########
solr/core/src/java/org/apache/solr/core/CoreContainer.java:
##########
@@ -16,12 +16,51 @@
  */
 package org.apache.solr.core;
 
+import static java.util.Objects.requireNonNull;

Review Comment:
   Apparently our import ordering is not yet standardized :-(



##########
solr/core/src/java/org/apache/solr/jersey/CatchAllExceptionMapper.java:
##########
@@ -52,26 +51,33 @@
 public class CatchAllExceptionMapper implements ExceptionMapper<Exception> {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  @Context
-  public ResourceContext resourceContext;
+  @Context public ResourceContext resourceContext;
 
   @Override
   public Response toResponse(Exception exception) {
-    final ContainerRequestContext containerRequestContext = resourceContext.getResource(ContainerRequestContext.class);
-
-    // Set the exception on the SolrQueryResponse.  Not to affect the actual response, but as SolrDispatchFiler and
-    // HttpSolrCall use the presence of an exception as a marker of success/failure for AuditLogging, and other logic.
-    final SolrQueryResponse solrQueryResponse = (SolrQueryResponse) containerRequestContext.getProperty(SOLR_QUERY_RESPONSE_KEY);
+    final ContainerRequestContext containerRequestContext =
+        resourceContext.getResource(ContainerRequestContext.class);
+
+    // Set the exception on the SolrQueryResponse.  Not to affect the actual response, but as
+    // SolrDispatchFiler and

Review Comment:
   more comment newline reflow



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966024055


##########
solr/core/src/java/org/apache/solr/handler/api/V2ApiUtils.java:
##########
@@ -40,4 +44,41 @@ public static void flattenToCommaDelimitedString(
     final String flattenedStr = String.join(",", toFlatten);
     destination.put(newKey, flattenedStr);
   }
+
+  /**
+   * Convert a JacksonReflectMapWriter (typically a {@link
+   * org.apache.solr.jersey.SolrJerseyResponse}) into the NamedList on a SolrQueryResponse
+   *
+   * @param rsp the response to attach the resulting NamedList to
+   * @param mw the input object to be converted into a NamedList
+   * @param trimHeader should the 'responseHeader' portion of the response be added to the
+   *     NamedList, or should populating that header be left to code elsewhere. This value should
+   *     usually be 'false' when called from v2 code, and 'true' when called from v1 code.
+   */
+  public static void squashIntoSolrResponse(
+      SolrQueryResponse rsp, JacksonReflectMapWriter mw, boolean trimHeader) {
+    squashIntoNamedList(rsp.getValues(), mw, trimHeader);
+  }
+
+  public static void squashIntoSolrResponse(SolrQueryResponse rsp, JacksonReflectMapWriter mw) {
+    squashIntoSolrResponse(rsp, mw, false);
+  }
+
+  public static void squashIntoNamedList(
+      NamedList<Object> destination, JacksonReflectMapWriter mw) {
+    squashIntoNamedList(destination, mw, false);
+  }
+
+  // TODO Come up with a better approach (maybe change Responses to be based on some class that can
+  // natively do this
+  //  without the intermediate map(s)?)

Review Comment:
   Hey, a belated thanks for fixing this; really appreciate it!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r967292221


##########
solr/core/src/java/org/apache/solr/jersey/RequestEventLogger.java:
##########
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.lang.invoke.MethodHandles;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs out request-specific information useful for troubleshooting Jersey development.
+ *
+ * @see ApplicationEventLogger
+ */
+public class RequestEventLogger implements RequestEventListener {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private volatile long requestCount;

Review Comment:
   Ended up removing these classes; see comment [here](https://github.com/apache/solr/pull/975#discussion_r967291913)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r968839919


##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   Definitely "additional properties" route.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on PR #975:
URL: https://github.com/apache/solr/pull/975#issuecomment-1244371524

   Definitely really close :-)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965990273


##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   I feel like the header stuff is metadata where we should be loose.  I'm all for strong typing everywhere else!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r953842424


##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigsetsResponse.java:
##########
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class ListConfigsetsResponse extends SolrJerseyResponse {
+
+    //TODO We use both JsonProperty annotations here becaues the v2 serialization code expects Jackson, but
+    // ReflectMapWriter (which we use to squash the typed v2 response into a SolrQueryResponse for v1 code) relies on

Review Comment:
   Yep, I think that's the way to go.  I think we should be able to create a ReflectMapWriter impl that can use the "real" Jackson annotations, though I'm only starting in on that now.  🤞 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r954969780


##########
solr/core/src/java/org/apache/solr/handler/configsets/ListConfigsetsResponse.java:
##########
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class ListConfigsetsResponse extends SolrJerseyResponse {
+
+    //TODO We use both JsonProperty annotations here becaues the v2 serialization code expects Jackson, but
+    // ReflectMapWriter (which we use to squash the typed v2 response into a SolrQueryResponse for v1 code) relies on

Review Comment:
   (To close the loop: this worked out surprisingly well, problem solved.)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r960599028


##########
solr/core/src/java/org/apache/solr/jersey/PostRequestDecorationFilter.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+
+/**
+ * Applies standard post-processing decorations to a {@link SolrJerseyResponse} that are needed on all responses.
+ *
+ * @see SolrCore#postDecorateResponse(SolrRequestHandler, SolrQueryRequest, SolrQueryResponse)
+ */
+public class PostRequestDecorationFilter implements ContainerResponseFilter {
+
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+        final SolrQueryRequest solrQueryRequest = (SolrQueryRequest) requestContext.getProperty(SOLR_QUERY_REQUEST_KEY);
+        if ( ! responseContext.hasEntity() || ! SolrJerseyResponse.class.isInstance(responseContext.getEntity())) {
+            log.debug("Skipping QTime assignment because response was not a SolrJerseyResponse");

Review Comment:
   Yeah, I can't say I've actually looked at the value in the response much.
   
   I use the value recorded in the solr logs frequently, to do performance analysis, etc.  But rarely (if ever) have I written code to pull the value out of individual SolrJ responses and do something with it.  Seems like a larger question though - I'd be curious what (if anything) people use this for.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] epugh commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
epugh commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r959893387


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -397,7 +399,7 @@ protected void handleAdmin(SolrQueryResponse solrResp) {
   @Override
   protected void executeCoreRequest(SolrQueryResponse rsp) {
     if (api == null) {
-      invokeJerseyRequest(cores, core, core.getApplicationHandler());
+      invokeJerseyRequest(cores, core, core.getApplicationHandler(), rsp);

Review Comment:
   ;-)   I see, before there was a rsp, so you kept the rsp..     so, you are probably right.  I think it's just my desire for consistency making me notice these nits.   And someone once said "Consistency is the hob goblin of little minds"...  ;-).    I think it's fine.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966177196


##########
solr/core/src/java/org/apache/solr/jersey/MessageBodyWriters.java:
##########
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_REQUEST_KEY;
+import static org.apache.solr.jersey.RequestContextConstants.SOLR_QUERY_RESPONSE_KEY;
+import static org.apache.solr.response.QueryResponseWriter.CONTENT_TYPE_TEXT_UTF8;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ResourceContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.BinaryResponseWriter;
+import org.apache.solr.response.CSVResponseWriter;
+import org.apache.solr.response.QueryResponseWriter;
+import org.apache.solr.response.QueryResponseWriterUtil;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.response.XMLResponseWriter;
+
+/**
+ * A collection of thin Jersey shims around Solr's existing {@link QueryResponseWriter} interface
+ */
+public class MessageBodyWriters {
+
+  // Jersey has a default MessageBodyWriter for JSON so we don't need to declare one here
+  // Which other response-writer formats are worth carrying forward into v2?
+
+  @Produces(MediaType.APPLICATION_XML)
+  public static class XmlMessageBodyWriter extends BaseMessageBodyWriter
+      implements MessageBodyWriter<JacksonReflectMapWriter> {
+    @Override
+    public QueryResponseWriter createResponseWriter() {
+      return new XMLResponseWriter();
+    }
+
+    @Override
+    public String getSupportedMediaType() {
+      return MediaType.APPLICATION_XML;
+    }
+  }
+
+  @Produces("application/javabin")

Review Comment:
   Fixed in a recent addition; more details on Jan's original thread.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966176044


##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -213,6 +237,24 @@ public PluginHolder<T> put(String name, PluginHolder<T> plugin) {
                 apiBag.register(api, nameSubstitutes);
               }
             }
+
+            // TODO Should we use <requestHandler name="/blah"> to override the path that each
+            //  resource registers under?
+            Collection<Class<? extends JerseyResource>> jerseyApis =
+                apiSupport.getJerseyResources();
+            if (!CollectionUtils.isEmpty(jerseyApis)) {
+              for (Class<? extends JerseyResource> jerseyClazz : jerseyApis) {
+                if (log.isDebugEnabled()) {
+                  log.debug("Registering jersey resource class: {}", jerseyClazz.getName());
+                }
+                jerseyResources.register(jerseyClazz);
+                // See MetricsBeanFactory javadocs for a better understanding of this resource->RH
+                // mapping
+                if (inst instanceof RequestHandlerBase) {

Review Comment:
   OK, I'll leave this as-is for now, but add exploring my first bullet-point above to my todo list for down the road.  If you think of a better approach, let me know!
   
   >  It remains to be seen if JAX-RS/Jersey works with that system
   
   I spent some time testing this out and was happily surprised to find that JAX-RS worked well for core-level packages/plugins, but didn't work at the container level because of some broad design decisions the package-manager makes at that level. (Specifically, we don't allow container-level "requestHandler" plugins, only 'Api' implementations.  More details [here](https://issues.apache.org/jira/browse/SOLR-16347?focusedCommentId=17586116&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-17586116))
   
   Anyway, bit of a mixed story there, but at least some good news.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r968884674


##########
solr/core/src/java/org/apache/solr/jersey/container/ContainerRequestUtils.java:
##########
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey.container;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.Principal;
+import java.util.Enumeration;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.SecurityContext;
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.internal.ContainerUtils;
+import org.glassfish.jersey.server.spi.ContainerResponseWriter;
+
+/**
+ * Utility methods for creating and populating a {@link
+ * org.glassfish.jersey.server.ContainerRequest} for use with Jersey {@link
+ * org.glassfish.jersey.server.ApplicationHandler}s
+ */
+public class ContainerRequestUtils {
+  private ContainerRequestUtils() {
+    /* Private ctor prevents instantiation */
+  }
+
+  // We don't rely on any of Jersey's authc/z features so we pass in this empty context for
+  // all requests.
+  public static final SecurityContext DEFAULT_SECURITY_CONTEXT =
+      new SecurityContext() {
+        public boolean isUserInRole(String role) {
+          return false;
+        }
+
+        public boolean isSecure() {
+          return false;
+        }
+
+        public Principal getUserPrincipal() {
+          return null;
+        }
+
+        public String getAuthenticationScheme() {
+          return null;
+        }
+      };
+
+  /**
+   * Creates a {@link ContainerRequest}
+   *
+   * <p>Implementation guided by code in 'jersey-container-jetty-http's JettyHttpContainer class.
+   */
+  public static ContainerRequest createContainerRequest(
+      HttpServletRequest httpServletRequest,
+      HttpServletResponse httpServletResponse,
+      Configuration appConfig) {
+    final ContainerResponseWriter responseWriter =
+        new JettyBridgeResponseWriter(httpServletResponse);
+    try {
+      final URI baseUri = getBaseUri(httpServletRequest);
+      final URI requestUri = getRequestUri(httpServletRequest, baseUri);
+      final ContainerRequest requestContext =
+          new ContainerRequest(
+              baseUri,
+              requestUri,
+              httpServletRequest.getMethod(),
+              DEFAULT_SECURITY_CONTEXT,
+              new MapPropertiesDelegate(),
+              appConfig);
+      requestContext.setEntityStream(httpServletRequest.getInputStream());
+      final Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
+      while (headerNames.hasMoreElements()) {
+        final String headerName = headerNames.nextElement();
+        String headerValue = httpServletRequest.getHeader(headerName);
+        requestContext.headers(headerName, headerValue == null ? "" : headerValue);
+      }
+      requestContext.setWriter(responseWriter);
+      return requestContext;
+    } catch (Exception e) {
+      // TODO Should we handle URISyntaxException any differently here?
+      throw new RuntimeException(e);
+    }
+  }
+
+  private static URI getBaseUri(HttpServletRequest httpServletRequest) {
+    try {
+      return new URI(
+          httpServletRequest.getScheme(),
+          null,
+          httpServletRequest.getServerName(),
+          httpServletRequest.getServerPort(),
+          getBasePath(httpServletRequest),
+          null,
+          null);
+    } catch (final URISyntaxException ex) {
+      throw new IllegalArgumentException(ex);
+    }
+  }
+
+  private static String getBasePath(HttpServletRequest httpServletRequest) {

Review Comment:
   Just inline this method, I think



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] sonatype-lift[bot] commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
sonatype-lift[bot] commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965305689


##########
solr/core/src/java/org/apache/solr/jersey/SolrRequestAuthorizer.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.Provider;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.security.AuthorizationContext;
+import org.apache.solr.security.AuthorizationUtils;
+import org.apache.solr.security.HttpServletAuthorizationContext;
+import org.apache.solr.security.PermissionNameProvider;
+import org.apache.solr.servlet.ServletUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A JAX-RS request filter that blocks or allows requests based on the authorization plugin
+ * configured in security.json.
+ */
+@Provider
+public class SolrRequestAuthorizer implements ContainerRequestFilter {
+
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  @Context private ResourceInfo resourceInfo;
+
+  public SolrRequestAuthorizer() {
+    log.info("Creating a new SolrRequestAuthorizer");
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public void filter(ContainerRequestContext requestContext) throws IOException {
+    final CoreContainer coreContainer =
+        (CoreContainer) requestContext.getProperty(RequestContextConstants.CORE_CONTAINER_KEY);
+    final HttpServletRequest servletRequest =
+        (HttpServletRequest)
+            requestContext.getProperty(RequestContextConstants.HTTP_SERVLET_REQ_KEY);
+    final HttpServletResponse servletResponse =
+        (HttpServletResponse)
+            requestContext.getProperty(RequestContextConstants.HTTP_SERVLET_RSP_KEY);
+    final AuthorizationContext.RequestType requestType =
+        (AuthorizationContext.RequestType)
+            requestContext.getProperty(RequestContextConstants.REQUEST_TYPE_KEY);
+    final List<String> collectionNames =
+        (List<String>) requestContext.getProperty(RequestContextConstants.COLLECTION_LIST_KEY);
+    final SolrParams solrParams =
+        (SolrParams) requestContext.getProperty(RequestContextConstants.SOLR_PARAMS_KEY);
+
+    /*
+     * HttpSolrCall has more involved logic to check whether a request requires authorization, but most of that
+     * revolves around checking for (1) static paths (e.g. index.html) or (2) HttpSolrCall 'action's that don't need
+     * authorization (e.g. request-forwarding)
+     *
+     * Since we don't invoke Jersey code in those particular cases we can ignore those checks here.
+     */
+    if (coreContainer.getAuthorizationPlugin() == null) {
+      return;
+    }
+    final AuthorizationContext authzContext =
+        getAuthzContext(servletRequest, requestType, collectionNames, solrParams, coreContainer);
+    log.debug("Attempting authz with context {}", authzContext);
+    AuthorizationUtils.AuthorizationFailure authzFailure =
+        AuthorizationUtils.authorize(servletRequest, servletResponse, coreContainer, authzContext);
+    if (authzFailure != null) {
+      final Response failureResponse =
+          Response.status(authzFailure.getStatusCode()).entity(authzFailure.getMessage()).build();
+      requestContext.abortWith(failureResponse);
+    }
+  }
+
+  private AuthorizationContext getAuthzContext(
+      HttpServletRequest servletRequest,
+      AuthorizationContext.RequestType reqType,
+      List<String> collectionNames,
+      SolrParams solrParams,
+      CoreContainer cores) {

Review Comment:
   *[UnusedVariable](https://errorprone.info/bugpattern/UnusedVariable):*  The parameter 'cores' is never read.
   
   ---
   
   
   ```suggestion
         getAuthzContext(servletRequest, requestType, collectionNames, solrParams);
   ```
   
   
   
   ---
   
   <details><summary><b>ℹī¸ Learn about @sonatype-lift commands</b></summary>
   
   You can reply with the following commands. For example, reply with ***@sonatype-lift ignoreall*** to leave out all findings.
   | **Command** | **Usage** |
   | ------------- | ------------- |
   | `@sonatype-lift ignore` | Leave out the above finding from this PR |
   | `@sonatype-lift ignoreall` | Leave out all the existing findings from this PR |
   | `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified `file\|issue\|path\|tool` from Lift findings by updating your config.toml file |
   
   **Note:** When talking to LiftBot, you need to **refresh** the page to see its response.
   <sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) to add LiftBot to another repo.</sub></details>
   
   
   
   ---
   
   Was this a good recommendation?
   [ [🙁 Not relevant](https://www.sonatype.com/lift-comment-rating?comment=328914606&lift_comment_rating=1) ] - [ [😕 Won't fix](https://www.sonatype.com/lift-comment-rating?comment=328914606&lift_comment_rating=2) ] - [ [😑 Not critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=328914606&lift_comment_rating=3) ] - [ [🙂 Critical, will fix](https://www.sonatype.com/lift-comment-rating?comment=328914606&lift_comment_rating=4) ] - [ [😊 Critical, fixing now](https://www.sonatype.com/lift-comment-rating?comment=328914606&lift_comment_rating=5) ]



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965987977


##########
solr/core/src/test/org/apache/solr/handler/configsets/ListConfigSetsAPITest.java:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.handler.configsets;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.ConfigSetService;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.CoreContainerFactory;
+import org.apache.solr.jersey.SolrJacksonMapper;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ListConfigSetsAPITest extends JerseyTest {
+
+  private CoreContainer mockCoreContainer;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Override
+  protected Application configure() {
+    resetMocks();
+    final ResourceConfig config = new ResourceConfig();
+    config.register(ListConfigSetsAPI.class);
+    config.register(SolrJacksonMapper.class);
+    config.register(
+        new AbstractBinder() {
+          @Override
+          protected void configure() {
+            bindFactory(new CoreContainerFactory(mockCoreContainer))
+                .to(CoreContainer.class)
+                .in(Singleton.class);
+          }
+        });
+
+    return config;
+  }
+
+  private void resetMocks() {
+    mockCoreContainer = mock(CoreContainer.class);
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsRaw() throws Exception {
+    final String expectedJson =
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}";
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final Response response = target("/cluster/configs").request().get();
+    final String jsonBody = response.readEntity(String.class);
+
+    assertEquals(200, response.getStatus());
+    assertEquals("application/json", response.getHeaders().getFirst("Content-type"));
+    assertEquals(1, 1);
+    assertEquals(
+        expectedJson,
+        "{\"responseHeader\":{\"status\":0,\"QTime\":0},\"configSets\":[\"cs1\",\"cs2\"]}");
+  }
+
+  @Test
+  public void testSuccessfulListConfigsetsTyped() throws Exception {
+    final ConfigSetService configSetService = mock(ConfigSetService.class);
+    when(mockCoreContainer.getConfigSetService()).thenReturn(configSetService);
+    when(configSetService.listConfigs()).thenReturn(List.of("cs1", "cs2"));
+
+    final ListConfigsetsResponse response =
+        target("/cluster/configs").request().get(ListConfigsetsResponse.class);
+
+    assertNotNull(response.configSets);
+    assertNull(response.error);
+    assertEquals(2, response.configSets.size());
+    assertTrue(response.configSets.contains("cs1"));
+    assertTrue(response.configSets.contains("cs2"));
+  }
+
+  /**
+   * Test the v2 to v1 response mapping for /cluster/configs
+   *
+   * <p>{@link org.apache.solr.handler.admin.ConfigSetsHandler} uses {@link ListConfigSetsAPI} (and
+   * its response class {@link ListConfigsetsResponse}) internally to serve the v1 version of this
+   * functionality. So it's important to make sure that the v2 response stays compatible with SolrJ
+   * - both because that's important in its own right and because that ensures we haven't
+   * accidentally changed the v1 response format.
+   */
+  @Test
+  public void testListConfigsetsV1Compatibility() throws Exception {

Review Comment:
   > I'll add a comment on this class that indicates its role as an example/model. I also plan on adding some dev-docs to cover our current API framework(s) and the Jersey integration. So I can point to this class from there, but make it clear that this sort of testing should be reserved for situations that are hard to cover other ways.
   
   Thanks; that's very thorough of you.  You are really doing some heroics in this PR and it's an inspiration to me.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r966015071


##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -273,7 +278,7 @@ public static Api getApiInfo(
     }
 
     if (api == null) {
-      return getSubPathApi(requestHandlers, path, fullPath, new CompositeApi(null));

Review Comment:
   That's how I lean as well.  I think OpenAPI would get much of the benefits that we'd originally hoped to get from "introspect", with much less associated maintenance on our part.
   
   Once this gets in and I start making further progress on the OpenAPI ticket (SOLR-16346), I'll raise a dev@ thread to discuss.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] dsmiley commented on a diff in pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
dsmiley commented on code in PR #975:
URL: https://github.com/apache/solr/pull/975#discussion_r965317709


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java:
##########
@@ -46,7 +46,7 @@ public SchemaNameAPI(SolrCore solrCore) {
   }
 
   @GET
-  @Produces("application/json")
+  @Produces({"application/json", "application/xml", "application/javabin"})

Review Comment:
   (pending @gerlowskija )



##########
solr/core/src/java/org/apache/solr/api/V2HttpCall.java:
##########
@@ -273,7 +278,7 @@ public static Api getApiInfo(
     }
 
     if (api == null) {
-      return getSubPathApi(requestHandlers, path, fullPath, new CompositeApi(null));

Review Comment:
   I agree we should jettison introspect for OpenAPI integration



##########
solr/core/src/java/org/apache/solr/jersey/RequestContextConstants.java:
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.codahale.metrics.Timer;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.security.AuthorizationContext;
+
+/**
+ * Keys used to store and retrieve values from the Jersey request context.
+ *
+ * <p>Properties are generally set in V2HttpCall's 'invokeJerseyRequest' and retrieved in individual
+ * {@link javax.ws.rs.container.ContainerRequestFilter}s using {@link
+ * ContainerRequestContext#getProperty(String)}
+ */
+public class RequestContextConstants {

Review Comment:
   No, but such a strange act would nonetheless be harmless.



##########
solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java:
##########
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Base response-body POJO to be used by Jersey resources.
+ *
+ * <p>Contains fields common to all Solr API responses, particularly the 'responseHeader' and
+ * 'error' fields.
+ */
+public class SolrJerseyResponse implements JacksonReflectMapWriter {
+
+  @JsonProperty("responseHeader")
+  public ResponseHeader responseHeader = new ResponseHeader();
+
+  @JsonProperty("error")
+  public ErrorInfo error;
+
+  public static class ResponseHeader implements JacksonReflectMapWriter {

Review Comment:
   Rigidity.  I've seen and probably written plugins that add to the header as a map of whatever info you want from, say, a SearchComponent.  Will JAX-RS prevent such plugins from doing so?



##########
solr/core/src/java/org/apache/solr/core/PluginBag.java:
##########
@@ -213,6 +237,24 @@ public PluginHolder<T> put(String name, PluginHolder<T> plugin) {
                 apiBag.register(api, nameSubstitutes);
               }
             }
+
+            // TODO Should we use <requestHandler name="/blah"> to override the path that each
+            //  resource registers under?
+            Collection<Class<? extends JerseyResource>> jerseyApis =
+                apiSupport.getJerseyResources();
+            if (!CollectionUtils.isEmpty(jerseyApis)) {
+              for (Class<? extends JerseyResource> jerseyClazz : jerseyApis) {
+                if (log.isDebugEnabled()) {
+                  log.debug("Registering jersey resource class: {}", jerseyClazz.getName());
+                }
+                jerseyResources.register(jerseyClazz);
+                // See MetricsBeanFactory javadocs for a better understanding of this resource->RH
+                // mapping
+                if (inst instanceof RequestHandlerBase) {

Review Comment:
   I really appreciate your deeply thoughtful response!
   Any way, this is just a smell; and there was some smell before to this effect, albeit less.
   
   FYI note that the package management system can dynamically add/change handlers without even reloading the core.  It remains to be seen if JAX-RS/Jersey works with that system but I wouldn't invest time in that now.



##########
solr/core/src/java/org/apache/solr/jersey/MetricBeanFactory.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.jersey;
+
+import org.apache.solr.core.PluginBag;
+import org.glassfish.hk2.api.Factory;
+
+/**
+ * Factory to inject JerseyMetricsLookupRegistry instances into Jersey resources and filters.
+ *
+ * <p>Currently, Jersey resources that have a corresponding v1 API produce the same metrics as their
+ * v1 equivalent and rely on the v1 requestHandler instance to do so. Solr facilitates this by
+ * building a map of the Jersey resource to requestHandler mapping (a {@link
+ * org.apache.solr.core.PluginBag.JerseyMetricsLookupRegistry}), and injecting it into the pre- and
+ * post- Jersey filters that handle metrics.
+ *
+ * <p>This isn't ideal, as requestHandler's don't really "fit" conceptually here. But it's
+ * unavoidable while we want our v2 APIs to exactly match the metrics produced by v1 calls.

Review Comment:
   > CollectionsHandler lumps together collection creation requests with clusterstatus calls with shard-splits, etc. That needn't be the case if we split from v1, which could be really cool.
   
   Awesome!
   
   Perhaps this is for Solr 10 then.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija merged pull request #975: SOLR-16347: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija merged PR #975:
URL: https://github.com/apache/solr/pull/975


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr] gerlowskija commented on pull request #975: Allow JAX-RS v2 API definition

Posted by GitBox <gi...@apache.org>.
gerlowskija commented on PR #975:
URL: https://github.com/apache/solr/pull/975#issuecomment-1218414038

   > can we get more javadoc on the newly introduced methods and interfaces so that folks coming in later will better understand the shape and relationship between everything?
   
   Good idea; I've added some already but will add more over the next day or two.
    
   > Also, I saw a bunch of logging added that looks like it should probably be debug rather than info, but I didn't bother commenting on it individually because this is still a draft and I'm not sure how much you need it for working out control flow at this point.
   
   I intend to get rid of most of that logging as this gets closer to committing.  As you guessed, most of it is just leftover "personal debugging" I did while still trying to understand control flow and lifecycle.  No intention of committing without removing that stuff.  
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org