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