2

I have a rest controller

@RestController
@RequestMapping(APIConstants.API_BASE_URI + APIConstants.MYCONTROLLER)
public class MyController extends APIRESTResource {

   @Context
   UriInfo uriInfo;

   @GetMapping({"/activate"})
   public ResponseEntity<String> activateAccount(@PathVariable("service") String srvc, @Context UriInfo info) {
      HttpStatus status = HttpStatus.OK;
      MediaType type = MediaType.TEXT_PLAIN;
      String payload = "Activated";

      try {
         List<Long> accountIdList = extractAccountIdsAsList(info);

         String datasource = getDatasourceForService(srvc);
         AccountsServiceImpl mgr = new AccountsServiceImpl(datasource);
         mgr.activateAccounts(accIdList);

         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(type);
         return new ResponseEntity<>(payload, headers, status);
      }
      catch (Exception ex) {
         return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
      }
   }

}

where

   private List<Long> extractAccountIdsAsList(UriInfo info) throws Exception {
      String fieldName = "accId";
      String accIdStr = info.getQueryParameters().getFirst(fieldName);
      validateRequiredField(fieldName, accIdStr);

      accIdStr = accIdStr.replace(" ", ""); // remove any spaces...

      String[] accIds = null;
      if (accIdStr.contains(",")) {
         accIds = accIdStr.split("\\,");
      }
      else {
         accIds = new String[1];
         accIds[0] = accIdStr;
      }

      List<Long> accIdList = new ArrayList<Long>();
      for (int i = 0; i < accIds.length; i++) {
         validateFieldValueType(fieldName, accIds[i], Long.TYPE);
         Long accId = new Long(accIds[i]);
         accIdList.add(accId);
      }

      return accIdList;
   }

but that will fail with an error

No primary or single public constructor found for interface javax.ws.rs.core.UriInfo - and no default constructor found either

not even making it to that controller. Any other controller for @GetMapping works fine but only that one with @Context is failing.

JackTheKnife
  • 3,795
  • 8
  • 57
  • 117
  • Don't mix Spring MVC with JAX-RS. Period. Simple as that. – Paul Samsotha Jul 14 '22 at 14:00
  • @PaulSamsotha This is an old app (legacy code) so I'm curious how it was able to work then? – JackTheKnife Jul 14 '22 at 19:10
  • In theory, this should NOT work. The two frameworks are not compatible. Could you create a hack to make the provided code work? Sure. But generally, it should NOT work AT ALL. – Paul Samsotha Jul 14 '22 at 19:23
  • @PaulSamsotha OK, so now I'm sure that I'm not crazy as someone got it to work because using Java6/7 when I have tried to run it on Java11. So I assume move out of the `@Context` and replace it with another `@PathVariable` and then use it in the `extractAccountIdsAsList` instead of `UriInfo`? (Added more content to the OP) – JackTheKnife Jul 14 '22 at 19:51
  • 1
    https://stackoverflow.com/q/34690109/2587435 – Paul Samsotha Jul 15 '22 at 09:26
  • 1
    Or just use RequestParam as the code only needs query parameters – Paul Samsotha Jul 15 '22 at 09:27
  • @PaulSamsotha Refactored code using `RequestParam` and the problem got solved. Once again thanks for bringing the mix-up to my attention. – JackTheKnife Jul 15 '22 at 14:17

1 Answers1

1

As Paul mentioned above in the comments legacy code has mixed up JAX-RS and Spring MVC in the controller code and I have no clue how it was working so far (maybe because running on Java6/7?) but the solution in my case was to use @RequestParam instead of @Context, as there is no equivalent of URIInfo in the Spring MVC, and the code will looks like this:

@RestController
@RequestMapping(APIConstants.API_BASE_URI + APIConstants.MYCONTROLLER)
public class MyController extends APIRESTResource {

   @Context
   UriInfo uriInfo;

   @GetMapping({"/activate"})
   public ResponseEntity<String> activateAccount(@PathVariable("service") String srvc, @RequestParam String accId) {
      HttpStatus status = HttpStatus.OK;
      MediaType type = MediaType.TEXT_PLAIN;
      String payload = "Activated";

      try {
         List<Long> accountIdList = extractAccountIdsAsList(accId);

         String datasource = getDatasourceForService(srvc);
         AccountsServiceImpl mgr = new AccountsServiceImpl(datasource);
         mgr.activateAccounts(accIdList);

         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(type);
         return new ResponseEntity<>(payload, headers, status);
      }
      catch (Exception ex) {
         return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
      }
   }

}

where

   private List<Long> extractAccountIdsAsList(String accIdStr) throws Exception {
      String fieldName = "accId";
      validateRequiredField(fieldName, accIdStr);

      accIdStr = accIdStr.replace(" ", ""); // remove any spaces...

      String[] accIds = null;
      if (accIdStr.contains(",")) {
         accIds = accIdStr.split("\\,");
      }
      else {
         accIds = new String[1];
         accIds[0] = accIdStr;
      }

      List<Long> accIdList = new ArrayList<Long>();
      for (int i = 0; i < accIds.length; i++) {
         validateFieldValueType(fieldName, accIds[i], Long.TYPE);
         Long accId = new Long(accIds[i]);
         accIdList.add(accId);
      }

      return accIdList;
   }
JackTheKnife
  • 3,795
  • 8
  • 57
  • 117