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