Spring Integration webflux - validate input JSON body

Viewed 607

Following is my application configuration

@SpringBootApplication
class DemoApplication {

    static void main(String[] args) {
        SpringApplication.run(DemoApplication, args)
    }


    @Bean
    IntegrationFlow startHeatToJiraFlow() {
        IntegrationFlows
                .from(WebFlux.inboundGateway("/input1")
                .requestMapping { m -> m.methods(HttpMethod.POST).consumes(MediaType.APPLICATION_JSON_VALUE) }
                .requestPayloadType(ResolvableType.forClassWithGenerics(Mono, ServiceInput))
        )
                .channel("inputtestchannel")
                .get()
    }

    @ServiceActivator(inputChannel = "inputtestchannel")
    Map replyMessage() {
        return [success: true]
    }


    class ServiceInput {
        @NotBlank
        String input1
        @NotBlank
        String input2
    }
}

I expect the following curl request to give me an error since I am not giving an input JSON in the body.

curl  -X POST localhost:8080/input1 -H "Content-Type:application/json"

Instead I am receiving a 200 response

{"success":true}

What am I doing wrong here ?

1 Answers

The WebFlux DSL does not support validation. You can validate the response as part of your processing sequence, as outlined in the validation section of the webflux docs.

An example of plugging it into Spring Integration can look something like this:

@EnableIntegration
@Configuration
class ValidatingFlowConfiguration {

  @Autowired
  Validator validator

  @Bean
  Publisher<Message<String>> helloFlow() {
    IntegrationFlows
        .from(
            WebFlux
                .inboundGateway("/greet")
                .requestMapping { m ->
                  m
                      .methods(HttpMethod.POST)
                      .consumes(MediaType.APPLICATION_JSON_VALUE)
                }
                .requestPayloadType(ResolvableType.forClassWithGenerics(Flux, HelloRequest))
                .requestChannel(greetingInputChannel())
        )
        .toReactivePublisher()
  }

  @Bean
  MessageChannel greetingInputChannel() {
    return new FluxMessageChannel()
  }

  @ServiceActivator(
      inputChannel = "greetingInputChannel"
  )
  Flux<String> greetingHandler(Flux<HelloRequest> seq) {
    seq
        .doOnNext { HelloRequest it -> validate(it) }
        .log()
        .map { "Hello, ${it.name}" as String }
  }

  void validate(HelloRequest request) {
    Errors errors = new BeanPropertyBindingResult(request, "request")
    validator.validate(request, errors);
    if (errors.hasErrors()) {
      throw new ServerWebInputException(errors.toString());
    }
  }
}

@ToString(includeNames = true)
@Validated
class HelloRequest {

  @NotEmpty
  String name
}

See gist if you want imports.

Related