Search code examples
spring-integrationspring-xdspring-elspring-cloud-dataflow

spring XD - http-client add application/json header


I've installed Spring XD in my PaaS environment and for legacy issue I'm stuck with version 1.0.0.M1. ( see reference doc). My goal is to call a http rest API using the http-client module. My stream definition is:

http | httpclient --url='''<my_url>''' --http-method=POST --mappedRequestHeaders=HTTP_REQUEST_HEADERS | log --expression=#root

Unfortunately, since the http module only sends the payload to the httpclient, the httpclient returns a 415 error due to the absence of the content-type header.

Considering that I can neither add new modules nor modify existing ones (in such a version you can only reference to the spring repository), I would like to use a tranform module to inject the content-type header.

How can I achieve such a goal?

Many thanks for your help.

EDIT:

I just found that httpclient processor (link) supports headersExpression A SpEL expression used to derive the http headers map to use. However:

--headers-expression='{Content-Type:'application/json'}'

Gives the following parse exception:

    org.springframework.expression.spel.SpelEvaluationException: EL1008E:
(pos 1): Property or field 'Content' cannot be found on object of type 'org.springframework.messaging.support.GenericMessage' - maybe not public?

Solution

  • See GH issue for more StackTrace.

    First of all it isn't Spring XD any more. Spring Cloud Dataflow is different product and its behavior maybe not that which you had with Spring XD before.

    Second: it is in version 1.0.0.RC1 already. So, consider to upgrade.

    Now on the problem. Look:

    headersExpression

     A SpEL expression used to derive the http headers map to use.
    

    So, this expression must return a Map and it is confirmed by the code:

    if (properties.getHeadersExpression() != null) {
        Map<?, ?> headersMap = properties.getHeadersExpression().getValue(message, Map.class);
    

    Now let's take a look into the problem:

    org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 1): Property or field 'Content' cannot be found on object of type 'org.springframework.messaging.support.GenericMessage' - maybe not public?
     org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
     org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
     org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:81) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
     org.springframework.expression.spel.ast.OpMinus.getValueInternal(OpMinus.java:98) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
    

    OpMinus is a root of cause. So, SpEL treats Content-Type expression as a minus operator.

    Sad, of course, but the workaround is like wrapping the key into quotes as well:

    --headers-expression={'Content-Type':'application/json'}