0

I have a situation where one of our applications is getting decommissioned shortly. However, there is another application that is built from it (in spring boot) which is already created. The problem is, that the upstream system sends us an XML request and the new application only consumes JSON. However, the upstream system doesn't have the bandwidth now to change their code to align to our new JSON service before the dead line of decommissioning occurs, so I need to create a XML JSON wrapper.


My question:

What ways can spring boot handle this scenario? For example, in the Controller class validate to see first if the request is XML, if it is then convert it as a JSON request which will hit my new service. What other options are there for this scenario?


@Validated
@RestController
@RequestMapping(path="/ccc")
public class CustomerCommGatewayInterface {
    @Autowired
    CCCatewayService gatewayService;

    @RequestMapping(method=RequestMethod.POST, value="/comm-history")
    public HistoryResponse getCustomerCommunicationHistory(@Valid 
          @RequestBody HistoryRequest request) {
        return gatewayService.getHistory(request);
    }
}

POJO Class

public class ServiceRequest {

    @NotNull(message = "{error.application.id.invalid}")
    @NotBlank(message = "{error.application.id.invalid}")
    private String applicationId;

    @NotNull(message = "{error.requestTypes.null}")
    @RequestTypes(acceptedValues={"Stuff", "More stuff"})
    private List<String> requestTypes;

    @Pattern(regexp = "(Retrieve)|(Contacts)|(Documents)$", message = "{error.subService.invalid}")
    private String subService;

    @Pattern(regexp = "(\\d{1,10})", message = "{error.customer.id.invalid}")
    private String customerId;

    @Pattern(regexp = "(\\d{5})", message = "{error.account.number.invalid}")
    private String accountNumber;

    @Pattern(regexp = "(\\d{10})", message = "{error.mtn.invalid}")
    private String number;

    @EmailId()
    private String emailAddress;

    private String category;
    private String categoryKeyword;
    private String preOrderNumber;
    private String requestCategory;
    private String channelType;
    private String ecpdId;
    private String subscriberId;
    private String returnCountLimit;

    @Pattern(regexp = "((0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/(19|20)\\d\\d)|(^()$)", message = "{error.date.invalid}")
    private String startDate;

    @Pattern(regexp = "((0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/(19|20)\\d\\d)|(^()$)", message = "{error.date.invalid}")
    private String endDate;
    private String includeDismissedCards;

    ...

    //getters and setters
}
Robin
  • 575
  • 2
  • 10
  • 26
  • Should be as easy as providing an identical endpoint that accepts xml instead of application/json – Daisy Day Aug 09 '18 at 19:47
  • @DaisyDay Yes, but i was wondering if there is another way instead of creating another subservice. – Robin Aug 09 '18 at 19:49
  • As far as I'm aware you would need 2 different endpoints. If it's possible you'd need an endpoint that will accept anything (security risk) and you'd need some convoluted class casting to figure out what is being sent to you. I think it would be a mess. – Daisy Day Aug 09 '18 at 19:54

1 Answers1

1

You don't need new endpoint definition. A single endpoint can read multiple request body types based on Content-Type request header and write different response body types based on Accept request header.

Spring will convert the request body using the registered converter beans e.g. MappingJackson2HttpMessageConverter. Converter bean is selected based on Content-Type request header. The conversion won't be dynamic if you restricted the endpoint to support only JSON e.g. by annotating the @Controller with @RequestMapping(consumes = "application/json").

If you configure additional converter supporting XML e.g. org.springframework.http.converter.xml.MarshallingHttpMessageConverter the request body will be processed as XML, provided that Marshaller bean is configured to map the XML to the right POJO type. As per class javadoc:

By default, this converter supports text/xml and application/xml. This can be overridden by setting the supportedMediaTypes property.

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • If you do this please be aware of XXE security risk and switch it off! – Daisy Day Aug 09 '18 at 20:23
  • 1
    @DaisyDay you are confusing specific parser features (XEE can be prevented with `XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES=false`) with Spring glue code for handling requests. See https://stackoverflow.com/a/28418763/1602555. – Karol Dowbecki Aug 09 '18 at 20:25
  • Thanks , I have it tried that way but I get org.springframework.web.HttpMediaTypeNotSupportedException. I have updated my question to include my controller and pojo class – Robin Aug 09 '18 at 21:00