Hi Bob, Cameleers
just to note, this got marked as spam in my mail client (for whatever
reason), so you might have missed this also. Some comments inline:

On Fri, Jan 29, 2021 at 3:50 PM Bob Paulin <b...@bobpaulin.com> wrote:
>
> 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.

In addition to that, with the efforts on making Camel core lighter, I
don't think we want to add a new dependency to `camel-util`.

> 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.

This looks like the best option to me, we should not be loosing type
information.

>
> 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



-- 
Zoran Regvart

Reply via email to