Claus Ibsen created CAMEL-26025:
-----------------------------------

             Summary: camel-support - API components do not convert the inBody 
body, and an unknown operation of a header-selected producer does nothing
                 Key: CAMEL-26025
                 URL: https://issues.apache.org/jira/browse/CAMEL-26025
             Project: Camel
          Issue Type: Bug
          Components: camel-support
    Affects Versions: 4.18.0, 4.22.0, 4.23.0
            Reporter: Claus Ibsen
             Fix For: 4.24.0


Found while checking the body types of the spring-redis and fhir components for 
the catalog (CAMEL-24961).

h4. 1. API components do not convert the body to the type of the inBody 
parameter

An API component passes the message body to the method parameter that 
{{inBody}} names. {{AbstractApiProducer.processInBody}} converts the body to 
the type of that parameter only when the endpoint configurer of the component 
knows the type ({{AbstractApiProducer}}, main 07d2e7a987bc, lines 178-183). The 
configurer knows only the shared options, not the parameters of the API 
methods, so it returns null and the body is passed as it is; the reflection 
fallback (lines 184-189) is never reached. A body of another type then fails in 
{{Method.invoke}} with "argument type mismatch". This is since 96034dd0f964 
(2020, "Api component avoid using reflection in api producer"), and applies to 
all 13 API components: as2, box, braintree, dhis2, fhir, google-calendar, 
google-drive, google-mail, google-sheets, olingo2, olingo4, twilio and zendesk.

Checked on 4.24.0-SNAPSHOT with {{camel run}} against {{camel infra run fhir}}: 
{{fhir://create/resource?inBody=resourceAsString}} with the JSON of a Patient 
as a byte array failed with "Error invoking resource with {... 
resourceAsString=[B@635d54e6 ...}: argument type mismatch"; a stream and a file 
failed the same way, and the same JSON as a String created the Patient.

*Proposed change*: take the type of the inBody parameter from the method helper 
of the endpoint (the argument types of its methods), and convert the body to it.

h4. 2. A producer that picks its method by a header does nothing for an unknown 
value

A producer that extends {{HeaderSelectorProducer}} picks its method by a header 
or an option, through a generated {{InvokeOnHeaderStrategy}}. For a value that 
has no method, the generated strategy returns null ({{default: return null;}}), 
which is also what a void method returns, so {{HeaderSelectorProducer.process}} 
cannot tell them apart ({{HeaderSelectorProducer}}, main 07d2e7a987bc, lines 
145-155): the exchange completes with no error and the body as it was. This 
applies to caffeine, consul, dynamic-router, ehcache, infinispan, servicenow, 
spring-redis and web3j.

Checked on 4.24.0-SNAPSHOT with {{camel run}}: {{CamelCaffeineAction=NOSUCH}} 
before {{caffeine-cache:survey}}, and {{CamelRedis.Command=NOSUCH}} before 
{{spring-redis:localhost:6379}}, both completed with no error and the body 
unchanged.

*Proposed change*: let the generated strategy tell an unknown value from a void 
method (a marker value, or an exception), so the producer fails with an error 
that names the value and the ones it supports.

h4. 3. A header named as the prefix of an API component fails every call

A header named exactly as the camel case prefix of an API component, such as 
{{CamelFhir}}, makes every call of that producer fail with 
{{StringIndexOutOfBoundsException: Index 9 out of bounds for length 9}}: 
{{ApiMethodPropertiesHelper}} reads the character after the prefix with 
{{key.charAt(prefixLength - 1)}} ({{ApiMethodPropertiesHelper}}, main 
07d2e7a987bc, line 97) without checking the length of the key.

Checked on 4.24.0-SNAPSHOT with {{camel run}}: a {{CamelFhir}} header before 
{{fhir://read/resourceById}} gave that exception.

*Proposed change*: skip a header that is not longer than the prefix.

h4. Also read in the code, not run

* {{AbstractApiConfiguration.splitResult}} is documented with {{defaultValue = 
"true"}}, but the field is false ({{AbstractApiConfiguration}}, lines 22-26); 
google-sheets, whose configuration extends it, does not split results by 
default.
* {{BodyFacts.kindOf}} checks for an Iterable before a Map ({{BodyFacts}}, 
lines 417 and 439-441), so a Map that is also Iterable, such as the response of 
solr (a {{SimpleOrderedMap}}), is recorded as a collection, while 
{{BodyFacts.describe}} calls it a Map.

_Claude Code on behalf of davsclaus_



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to