Home > Net >  Why do I get random Http 404 from server between same requests with only one change in any field?
Why do I get random Http 404 from server between same requests with only one change in any field?

Time:10-28

I haven an endpoint POST /api/marketplace/add that accepts a DTO object as request body. When I send the body below with platformName field set , server accepts request and processes it with no problem. But when I only try to change field platformName to null I get Http 404 error from server. I debugged the request and found out that it even can not reach controller method. I also got no trace from that error. What might be the cause that makes API respond differently to same request?

below

{
"platformName": "Trendyol",
"commissionAmounts": [
 {
  "amount": 23.45,
  "categoryInfos": [
    {
      "categoryName": "Game"
    }
  ],
  "isCategoryBasedPricing": true
}
],
 "shipmentAmounts": [
{
  "amount": 23.45,
  "scaleInfo": {
    "order": 0,
    "lowerBound": 0,
    "upperBound": 0
  },
  "volumeInfo": {
    "order": 0,
    "lowerBound": 0,
    "upperBound": 0
  },
  "isVolumeBasedPricing": true
}]
 }

EDIT: dto model is

@Generated
public class MarketPlaceDTO {

 @JsonProperty("platformName")
 private String platformName;

 @JsonProperty("commissionAmounts")
 @Valid
 private List<CommissionInfoDTO> commissionAmounts = new ArrayList<>();

 @JsonProperty("shipmentAmounts")
 @Valid
 private List<ShipmentInfoDTO> shipmentAmounts = new ArrayList<>();

Controller is implementing swagger generated api interface. with postmapping and requestbody annotations.

@RequiredArgsConstructor
@RestController
public class MarketPlaceApiController implements MarketplaceApi {

private final MarketPlaceDAOService marketPlaceDAOService;


@Override
public ResponseEntity<BaseResponseDTO> addMarketPlace(MarketPlaceDTO 
 marketPlaceDTO) {
    BaseResponseDTO dto = 
 marketPlaceDAOService.addMarketPlace(marketPlaceDTO);
    return ResponseEntity.ok(dto);
 }
}

Swagger generated api interface

      @RequestMapping(
      method = RequestMethod.POST,
      value = "/marketplace/add",
      produces = { "application/json", "application/xml" },
      consumes = { "application/json" })
      default ResponseEntity<BaseResponseDTO> _addMarketPlace( 
      @Parameter(name = "MarketPlaceDTO", description = "Add new 
      marketplace with given request body", required = true) @Valid 
      @RequestBody MarketPlaceDTO marketPlaceDTO) {
     return addMarketPlace(marketPlaceDTO);
     }

Response is

{
"timestamp": 1666866382906,
"status": 404,
"error": "Not Found",
"path": "/marketplace/add"
}

CodePudding user response:

Obviously, that you use an endpoint with @RequestBody where body is a DTO.

And on trying to call this endpoint Spring Web first should match that a model in your request payload matches a require object in @RequestBody argument.

Ideally, using DTO as a request model is not a good idea. But I don't see your structure and cannot say if it's a problem or not.

The simple solution in your case is preparation (annotating) your DTO with specific JSON annotations:

@JsonInclude
@JsonIgnoreProperties(ignoreUnknown = true)
public class YourDTO {

  private String platformName;
}

and for Controller add class annotation @Validated; for @RequestBody add @Valid annotation.

Recommendation: use request models for incoming objects, and later converters to DTO/entities with ability to response them with filtering (or in complex cases add also response model - usually it's overhead).

CodePudding user response:

My problem was global exception handler component annotated with @ControllerAdvice. I tried to handle validation exceptions and forgot to add @ResponseBody to my handler methods which is in my case probabaly required. That somehow caused server to send http 404 message when any input validation exception was thrown. After I made changes , Exceptions was handled correctly by handler component.

@ControllerAdvice
@ResponseBody // this resolved my issue.
public class MVCExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseErrorResponse 
 methodArgumentExceptions(MethodArgumentNotValidException e){
    return BaseErrorResponse.builder()
            
.errorMessage(AppError.INVALID_OR_MISSING_USER_INPUT.getErrorMessage())
            .errorCode(AppError.INVALID_OR_MISSING_USER_INPUT.getErrorCode())
            .errorTime(Date.from(Instant.now())).build();
 }
  • Related