IdentifiableTypeImpl throws IllegalArgumentException with EmbeddedId and relations - bugfix + unit test (#1355)
* IdentifiableTypeImpl throws IllegalArgumentException with EmbeddedId and relations - bugfix + unit test
Because there are four new objects (java classes) in org.eclipse.persistence.testing.models.jpa.metamodel package MetamodelMetamodelTest.METAMODEL_ALL_TYPES is increased into 56.
These four objects have eights new attributes. This is why MetamodelMetamodelTest.METAMODEL_ALL_ATTRIBUTES_SIZE is increased into 158.
fixes #1228
Signed-off-by: Radek Felcman <radek.felcman@oracle.com>
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/localization/i18n/ExceptionLocalizationResource.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/localization/i18n/ExceptionLocalizationResource.java
index 2aa7455..d293928 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/localization/i18n/ExceptionLocalizationResource.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/localization/i18n/ExceptionLocalizationResource.java
@@ -148,7 +148,7 @@
{ "metamodel_managed_type_attribute_not_present", "The attribute [{0}] is not present in the managed type [{1}]." },
{ "metamodel_managed_type_attribute_type_incorrect", "Expected attribute type [{2}] on the existing attribute [{0}] on the managed type [{1}] but found attribute type [{3}]." },
{ "metamodel_identifiable_version_attribute_type_incorrect", "Expected version attribute type [{2}] on the existing version attribute [{0}] on the identifiable type [{1}] but found attribute type [{3}]." },
- { "metamodel_identifiable_id_attribute_type_incorrect", "Expected id attribute type [{2}] on the existing id attribute [{0}] on the identifiable type [{1}] but found attribute type [{3}]." },
+ { "metamodel_identifiable_id_attribute_type_incorrect", "Expected id attribute type [{2}] in the existing id attributes [{0}] on the identifiable type [{1}] but found attribute types [{3}]." },
{ "metamodel_managed_type_declared_attribute_not_present_but_is_on_superclass", "The declared attribute [{0}] from the managed type [{1}] is not present - however, it is declared on a superclass." },
{ "metamodel_managed_type_attribute_return_type_incorrect", "Expected attribute return type [{2}] on the existing attribute [{0}] on the managed type [{1}] but found attribute return type [{3}]." },
{ "metamodel_incompatible_persistence_config_for_getIdType", "Incompatible persistence configuration getting Metamodel Id Type for the ManagedType [{0}]." },
diff --git a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/Bar.java b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/Bar.java
new file mode 100644
index 0000000..be7fc6f
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/Bar.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation from Oracle
+package org.eclipse.persistence.testing.models.jpa.metamodel;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
+@Entity
+@Table(name="CMP3_MM_BAR")
+public class Bar {
+
+ @Id
+ private Long id;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+}
diff --git a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/Foo.java b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/Foo.java
new file mode 100644
index 0000000..926d5fa
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/Foo.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation from Oracle
+package org.eclipse.persistence.testing.models.jpa.metamodel;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import java.util.List;
+
+@Entity
+@Table(name="CMP3_MM_FOO")
+public class Foo {
+
+ @Id
+ private Long id;
+
+ @OneToMany(mappedBy = "foo")
+ private List<FooBar> fooBars;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public List<FooBar> getFooBars() {
+ return fooBars;
+ }
+
+ public void setFooBars(List<FooBar> fooBars) {
+ this.fooBars = fooBars;
+ }
+
+}
diff --git a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/FooBar.java b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/FooBar.java
new file mode 100644
index 0000000..e64f220
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/FooBar.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation from Oracle
+package org.eclipse.persistence.testing.models.jpa.metamodel;
+
+import jakarta.persistence.EmbeddedId;
+import jakarta.persistence.Entity;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.MapsId;
+import jakarta.persistence.Table;
+
+@Entity
+@Table(name="CMP3_MM_FOOBAR")
+public class FooBar {
+
+ @EmbeddedId
+ private FooBarId id;
+
+ @ManyToOne
+ @JoinColumn(name = "bar_id")
+ @MapsId("barId")
+ private Bar bar;
+
+ @ManyToOne
+ @JoinColumn(name = "foo_id")
+ @MapsId("fooId")
+ private Foo foo;
+
+ public FooBarId getId() {
+ return id;
+ }
+
+ public void setId(FooBarId id) {
+ this.id = id;
+ }
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(Bar bar) {
+ this.bar = bar;
+ }
+
+ public Foo getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Foo foo) {
+ this.foo = foo;
+ }
+
+}
diff --git a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/FooBarId.java b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/FooBarId.java
new file mode 100644
index 0000000..1d55506
--- /dev/null
+++ b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/models/jpa/metamodel/FooBarId.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation from Oracle
+package org.eclipse.persistence.testing.models.jpa.metamodel;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import java.io.Serializable;
+import java.util.Objects;
+
+@Embeddable
+public class FooBarId implements Serializable {
+
+ @Column(name = "foo_id")
+ private Long fooId;
+
+ @Column(name = "bar_id")
+ private Long barId;
+
+ public Long getFooId() {
+ return fooId;
+ }
+
+ public void setFooId(Long fooId) {
+ this.fooId = fooId;
+ }
+
+ public Long getBarId() {
+ return barId;
+ }
+
+ public void setBarId(Long barId) {
+ this.barId = barId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ FooBarId fooBarId = (FooBarId) o;
+ return fooId.equals(fooBarId.fooId) && barId.equals(fooBarId.barId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(fooId, barId);
+ }
+}
diff --git a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelMetamodelTest.java b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelMetamodelTest.java
index 57f60af..80e205e 100644
--- a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelMetamodelTest.java
+++ b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelMetamodelTest.java
@@ -82,6 +82,8 @@
import org.eclipse.persistence.testing.models.jpa.metamodel.EmbeddedPK;
import org.eclipse.persistence.testing.models.jpa.metamodel.Enclosure;
import org.eclipse.persistence.testing.models.jpa.metamodel.EnclosureIdClassPK;
+import org.eclipse.persistence.testing.models.jpa.metamodel.FooBar;
+import org.eclipse.persistence.testing.models.jpa.metamodel.FooBarId;
import org.eclipse.persistence.testing.models.jpa.metamodel.GalacticPosition;
import org.eclipse.persistence.testing.models.jpa.metamodel.HardwareDesigner;
import org.eclipse.persistence.testing.models.jpa.metamodel.MSRootPropertyAccess;
@@ -125,9 +127,9 @@
*/
public class MetamodelMetamodelTest extends MetamodelTest {
- public static final int METAMODEL_ALL_ATTRIBUTES_SIZE = 150;//6;
+ public static final int METAMODEL_ALL_ATTRIBUTES_SIZE = 158;//6;
// Note: Since BasicTypes are lazy - loaded into the metamodel-types Map - this test must preceed any test that verifies all BasicType objects like "testIdentifiableType_getIdType_Method"
- public static final int METAMODEL_ALL_TYPES = 52;
+ public static final int METAMODEL_ALL_TYPES = 56;
public static final int METAMODEL_MANUFACTURER_DECLARED_TYPES = 28;
// Get # of processor cores (hard cores + hyperthreaded cores)
public static final int numberProcessingUnits = Runtime.getRuntime().availableProcessors();
@@ -202,6 +204,7 @@
suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getVersion_Method"));
suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_Method"));
suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getId_Method"));
+ suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getId_with_EmbeddedId_Method"));
suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_normal_execution_attribute_is_declared"));
suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_variant_execution_attribute_is_declared_above"));
suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_variant_execution_attribute_is_not_declared_at_all"));
@@ -1700,6 +1703,42 @@
}
}
+ public void testIdentifiableType_getId_with_EmbeddedId_Method() {
+ EntityManager em = null;
+ boolean expectedIAExceptionThrown = false;
+ try {
+ em = privateTestSetup();
+ assertNotNull(em);
+ Metamodel metamodel = em.getMetamodel();
+ assertNotNull(metamodel);
+ EntityType<FooBar> fooBarEntityType = metamodel.entity(FooBar.class);
+ assertNotNull(fooBarEntityType);
+ assertTrue(fooBarEntityType.hasSingleIdAttribute());
+
+ // Actual Test Case
+ /**
+ * Return the attribute that corresponds to the id attribute of
+ * the entity or mapped superclass.
+ * @param type the type of the represented id attribute
+ * @return id attribute
+ * @throws IllegalArgumentException if id attribute of the given
+ * type is not present in the identifiable type or if
+ * the identifiable type has an id class
+ */
+ //<Y> SingularAttribute<? super X, Y> getId(Class<Y> type);
+
+ SingularAttribute<? super FooBar, FooBarId> fooBarId = fooBarEntityType.getId(FooBarId.class);
+ //FooBarId declared by @EmbeddedId
+ assertNotNull(fooBarId);
+ } catch (IllegalArgumentException iae) {
+ iae.printStackTrace();
+ expectedIAExceptionThrown = true;
+ } finally {
+ cleanup(em);
+ assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
+ }
+ }
+
public void testIdentifiableType_getVersion_Method() {
EntityManager em = null;
boolean expectedIAExceptionThrown = false;
diff --git a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelTableCreator.java b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelTableCreator.java
index b1e0850..1005a62 100644
--- a/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelTableCreator.java
+++ b/jpa/eclipselink.jpa.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/metamodel/MetamodelTableCreator.java
@@ -98,6 +98,9 @@
addTableDefinition(buildCMP3_MM_BOARD_SEQTable());
addTableDefinition(buildCMP3_MM_PERSON_SEQTable());
addTableDefinition(buildCMP3_MM_MANUF_CMP3_MM_MANUFTable());
+ addTableDefinition(buildCMP3_MM_BARTable());
+ addTableDefinition(buildCMP3_MM_FOOTable());
+ addTableDefinition(buildCMP3_MM_FOOBARTable());
}
@@ -2355,5 +2358,65 @@
return table;
}
+ public static TableDefinition buildCMP3_MM_BARTable() {
+ TableDefinition table = new TableDefinition();
+ table.setName("CMP3_MM_BAR");
+
+ FieldDefinition field = new FieldDefinition();
+ field.setName("ID");
+ field.setTypeName("NUMERIC");
+ field.setSize(15);
+ field.setShouldAllowNull(false);
+ field.setIsPrimaryKey(true);
+ field.setUnique(false);
+ field.setIsIdentity(true);
+ table.addField(field);
+
+ return table;
+ }
+
+ public static TableDefinition buildCMP3_MM_FOOTable() {
+ TableDefinition table = new TableDefinition();
+ table.setName("CMP3_MM_FOO");
+
+ FieldDefinition field = new FieldDefinition();
+ field.setName("ID");
+ field.setTypeName("NUMERIC");
+ field.setSize(15);
+ field.setShouldAllowNull(false);
+ field.setIsPrimaryKey(true);
+ field.setUnique(false);
+ field.setIsIdentity(true);
+ table.addField(field);
+
+ return table;
+ }
+
+ public static TableDefinition buildCMP3_MM_FOOBARTable() {
+ TableDefinition table = new TableDefinition();
+ table.setName("CMP3_MM_FOOBAR");
+
+ FieldDefinition field = new FieldDefinition();
+ field.setName("bar_id");
+ field.setTypeName("NUMERIC");
+ field.setSize(15);
+ field.setShouldAllowNull(false);
+ field.setIsPrimaryKey(true);
+ field.setUnique(false);
+ field.setIsIdentity(true);
+ table.addField(field);
+
+ FieldDefinition field2 = new FieldDefinition();
+ field2.setName("foo_id");
+ field2.setTypeName("NUMERIC");
+ field2.setSize(15);
+ field2.setShouldAllowNull(false);
+ field2.setIsPrimaryKey(true);
+ field2.setUnique(false);
+ field2.setIsIdentity(true);
+ table.addField(field2);
+
+ return table;
+ }
}
diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metamodel/IdentifiableTypeImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metamodel/IdentifiableTypeImpl.java
index 4d26e06..8e4d9fb 100644
--- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metamodel/IdentifiableTypeImpl.java
+++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metamodel/IdentifiableTypeImpl.java
@@ -26,6 +26,7 @@
// 08/06/2010-2.2 mobrien 322018 - reduce protected instance variables to private to enforce encapsulation
package org.eclipse.persistence.internal.jpa.metamodel;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -195,6 +196,8 @@
"metamodel_identifiable_id_attribute_is_incorrect_idclass",
new Object[] { this }));
} else {
+ List<String> anAttributesMsg = new ArrayList<>();
+ List<String> anAttributesJavaTypeMsg = new ArrayList<>();
// verify single id attribute type
for(SingularAttribute<? super X, ?> anAttribute : idAttributes) {
// Verify type is correct - relax restriction on null and Object.class (from same classLoader)
@@ -202,11 +205,15 @@
type.getCanonicalName().equals(anAttribute.getJavaType().getCanonicalName())) {
idAttribute = (SingularAttribute<? super X, Y>) anAttribute;
} else {
- throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
- "metamodel_identifiable_id_attribute_type_incorrect",
- new Object[] { anAttribute, this, type, anAttribute.getJavaType() }));
+ anAttributesMsg.add(anAttribute.toString());
+ anAttributesJavaTypeMsg.add(anAttribute.getJavaType().toString());
}
}
+ if (idAttribute == null) {
+ throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
+ "metamodel_identifiable_id_attribute_type_incorrect",
+ new Object[] { anAttributesMsg, this, type, anAttributesJavaTypeMsg }));
+ }
}
return idAttribute;
}