Hi,

I've submitted a issue [1].

in prior versions you could define an array type as the unmarshalType in a dataformat in the Java DSL as follows:

from("direct:beginArray").unmarshal().json(JsonLibrary.Jackson, String[].class).to("mock:endArray");

This now throws an exception see [1].


It appears is due to the code in JsonDataFormatReifier [2] that converts the unmarshalType into unmarshalTypeName and then the data format (in my case JacksonDataFormat) tries to resolve the class via the camel ClassResolver

camelContext.getClassResolver().resolveClass(unmarshalType);

Given this delegates to a classloader loadClass method see [3]. Classloaders can't load array types this way. Also it fails the check on the original unmarshalType because the original unmarshalType in the definition is not copied to the created DataFormat object so the check

if (unmarshalTypeName != null && (unmarshalType == null || unmarshalType == Object.class)) {

does not help here.


If arrays are to be supported I see a couple of options.

1) org.apache.camel.util.ObjectHelper could have a fall back to use something like the Apache Commons ClassUtil.getClass(). This would also allow folks using unmarshalTypeName to specify java.lang.String[] and get a result. However it does make the ClassResolver act less like a classloader which may be undesirable.

2) Detect that the unmarshalTypeName is an array and resolve the base class then convert to an array. Array.newInstance(..).getClass() may be replaced with class.arrayType() in Java 12+. Might be a little ugly but leaves ObjectHelper alone.

Ex
@Override
    protected void doInit() throws Exception {
if (unmarshalTypeName != null && (unmarshalType == null || unmarshalType == Object.class)) {

            String baseUnmarshalType = unmarshalTypeName;
            if (baseUnmarshalType.startsWith("[L")) {
baseUnmarshalType = baseUnmarshalType.substring(2, baseUnmarshalType.length() - 1); Class<?> baseUnmarshalTypeClass = camelContext.getClassResolver().resolveClass(baseUnmarshalType); unmarshalType = Array.newInstance(baseUnmarshalTypeClass, 0).getClass();
            } else {
unmarshalType = camelContext.getClassResolver().resolveClass(baseUnmarshalType);
            }

......
}

3) Allow the unmarshalType to be passed directly to the newly created DataFormat. I know these fields are transient currently (and have been for a long time) but if it were pass the check to do the class resolution would not need to run and it could just use the unmarshalType directly.

4) Don't allow array types and throw an exception. Seems a bit opinionated but better than the null error.


Other options?

Sincerely,

Bob

[1] https://issues.apache.org/jira/browse/CAMEL-16114
[2] https://github.com/apache/camel/blob/7a58c2b0f9612c205ddbafbe30a8487f46021d14/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/JsonDataFormatReifier.java#L46 [3] https://github.com/apache/camel/blob/7a58c2b0f9612c205ddbafbe30a8487f46021d14/core/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java#L474

Reply via email to