diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/results/TestMultiselect.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/results/TestMultiselect.java index a84d36831..e4a85cd95 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/results/TestMultiselect.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/results/TestMultiselect.java @@ -379,6 +379,26 @@ public class TestMultiselect extends CriteriaTest { assertEquals(String.class, tuple4.get(0).getClass()); } + public void testConstructorFailsFast() { + CriteriaQuery q = cb.createQuery(Tuple.class); + Root foo = q.from(Foo.class); + try { + q.multiselect(cb.construct(Foo.class, foo.get(Foo_.flong))); + fail("Expected IllegalArgumentException becuase Foo(long) is not a valid constructor"); + } catch (IllegalArgumentException e) { + // good -- but print the error message to check it is informative enough + System.err.println(e); + } + try { + q.multiselect(cb.construct(Foo.class)); + fail("Expected IllegalArgumentException becuase Foo() is not a valid constructor"); + } catch (IllegalArgumentException e) { + // good -- but print the error message to check it is informative enough + System.err.println(e); + } + + } + // =============== assertions by result types ======================== void assertResult(CriteriaQuery q, Class resultClass) { diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java index 04d810e3b..fdf80e912 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java @@ -18,6 +18,7 @@ */ package org.apache.openjpa.persistence.criteria; +import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -30,6 +31,7 @@ import javax.persistence.criteria.Selection; import org.apache.openjpa.kernel.FillStrategy; import org.apache.openjpa.kernel.ResultShape; +import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.persistence.TupleFactory; import org.apache.openjpa.persistence.TupleImpl; @@ -42,6 +44,7 @@ import org.apache.openjpa.persistence.TupleImpl; * */ public class CompoundSelections { + private static Localizer _loc = Localizer.forPackage(CompoundSelections.class); /** * Gets the strategy to fill a given compound selection. * @@ -118,12 +121,29 @@ public class CompoundSelections { * @param type of the constructed instance */ public static class NewInstance extends CompoundSelectionImpl { + private FillStrategy.NewInstance strategy; public NewInstance(Class cls, Selection... selections) { super(cls, selections); + strategy = new FillStrategy.NewInstance(findConstructor(cls, selections)); } public FillStrategy getFillStrategy() { - return new FillStrategy.NewInstance(getJavaType()); + return strategy; + } + + private Constructor findConstructor(Class cls, Selection... selections) { + Class[] types = selections == null ? null : new Class[selections.length]; + if (selections != null) { + for (int i = 0; i < selections.length; i++) { + types[i] = selections[i].getJavaType(); + } + } + try { + return cls.getConstructor(types); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException(_loc.get("select-no-ctor", cls, + types == null ? "[]" : Arrays.toString(types)).getMessage()); + } } } diff --git a/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/criteria/localizer.properties b/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/criteria/localizer.properties index bcdea649a..5da0b9a24 100644 --- a/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/criteria/localizer.properties +++ b/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/criteria/localizer.properties @@ -21,4 +21,7 @@ root-undefined: No root is defined for criteria query. \ Use CriteriaQuery.from(Class) to define a root. select-undefined: No terms is selected for criteria query. \ Use CriteriaQuery.select() or multiselect() to select \ - projection terms for the query. \ No newline at end of file + projection terms for the query. +select-no-ctor: You have specified selection term to construct an instance of \ + "{0}" with argument types "{1}". But "{0}" has no constructor with such \ + argument types. \ No newline at end of file