This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/CXF-8927 in repository https://gitbox.apache.org/repos/asf/cxf.git
commit e529d9637426f3952d57673215488b3655806700 Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Wed Oct 14 06:31:05 2026 +0100 CXF-8297 - Fix NPE in Aegis for generic array properties (e.g. T[]) --- .../java/org/apache/cxf/aegis/type/TypeUtil.java | 22 +++++++- .../cxf/aegis/type/java5/GenericArrayTest.java | 66 ++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java b/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java index 47842fb455c..86d3099ba9a 100644 --- a/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java +++ b/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java @@ -22,6 +22,8 @@ import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; import java.util.logging.Logger; import javax.xml.namespace.QName; @@ -251,7 +253,10 @@ public final class TypeUtil { if (type instanceof GenericArrayType) { GenericArrayType gat = (GenericArrayType) type; Type compType = gat.getGenericComponentType(); - Class<?> arrayBaseType = getTypeRelatedClass(compType); + Class<?> arrayBaseType = getTypeRelatedClass(getErasedType(compType)); + if (arrayBaseType == null) { + arrayBaseType = Object.class; + } // believe it or not, this seems to be the only way to get the // Class object for an array of primitive type. Object instance = Array.newInstance(arrayBaseType, 0); @@ -259,4 +264,19 @@ public final class TypeUtil { } return null; } + + /** + * Replace a type variable or wildcard by its (first) upper bound, e.g. so that + * the component type of a generic array such as T[] can be resolved to a class. + */ + private static Type getErasedType(Type type) { + Type erased = type; + while (erased instanceof TypeVariable || erased instanceof WildcardType) { + Type[] bounds = erased instanceof TypeVariable + ? ((TypeVariable<?>) erased).getBounds() + : ((WildcardType) erased).getUpperBounds(); + erased = bounds.length > 0 ? bounds[0] : Object.class; + } + return erased; + } } diff --git a/rt/databinding/aegis/src/test/java/org/apache/cxf/aegis/type/java5/GenericArrayTest.java b/rt/databinding/aegis/src/test/java/org/apache/cxf/aegis/type/java5/GenericArrayTest.java new file mode 100644 index 00000000000..ef29ca33bdb --- /dev/null +++ b/rt/databinding/aegis/src/test/java/org/apache/cxf/aegis/type/java5/GenericArrayTest.java @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.aegis.type.java5; + +import org.w3c.dom.Document; + +import org.apache.cxf.aegis.AbstractAegisTest; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; + +/** + * A bean property whose type is a generic array of a type variable (e.g. T[]) + * used to cause a NullPointerException in TypeUtil.getTypeRelatedClass. + */ +public class GenericArrayTest extends AbstractAegisTest { + + @Before + public void setUp() throws Exception { + super.setUp(); + createService(GenericArrayService.class, "GenericArrayService"); + } + + @Test + public void testGenericArrayProperty() throws Exception { + Document doc = getWSDLDocument("GenericArrayService"); + assertNotNull(doc); + assertValid("//xsd:complexType[@name='Page']", doc); + } + + public static class Page<T> { + private T[] items; + + public T[] getItems() { + return items; + } + + public void setItems(T[] items) { + this.items = items; + } + } + + public static class GenericArrayService { + public Page<String> getPage() { + return new Page<>(); + } + } +}
