OPENJPA-174 : Remove legacy code throwing an exception when attempting to

construct an oid instance for an abstract persistent type.  Improve error
message in ApplicationIds when attempting to create a new id instance when the
id class is abstract.



git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@520117 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2007-03-19 21:46:45 +00:00
parent 4ce16ed9d3
commit 229f24547a
7 changed files with 180 additions and 28 deletions

View File

@ -1080,37 +1080,27 @@ public class BrokerImpl
try { try {
ClassMetaData meta = _conf.getMetaDataRepositoryInstance(). ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
getMetaData(cls, _loader, true); getMetaData(cls, _loader, true);
switch (meta.getIdentityType()) {
// delegate to store manager for datastore ids case ClassMetaData.ID_DATASTORE:
if (meta.getIdentityType() == ClassMetaData.ID_DATASTORE) { // delegate to store manager for datastore ids
if (val instanceof String if (val instanceof String
&& ((String) val).startsWith(StateManagerId.STRING_PREFIX)) && ((String) val).startsWith(StateManagerId.STRING_PREFIX))
return new StateManagerId((String) val); return new StateManagerId((String) val);
return _store.newDataStoreId(val, meta); return _store.newDataStoreId(val, meta);
} else if (meta.getIdentityType() == ClassMetaData.ID_UNKNOWN) case ClassMetaData.ID_APPLICATION:
if (ImplHelper.isAssignable(meta.getObjectIdType(),
val.getClass())) {
if (!meta.isOpenJPAIdentity()
&& meta.isObjectIdTypeShared())
return new ObjectId(cls, val);
return val;
}
Object[] arr = (val instanceof Object[]) ? (Object[]) val
: new Object[]{ val };
return ApplicationIds.fromPKValues(arr, meta);
default:
throw new UserException(_loc.get("meta-unknownid", cls)); throw new UserException(_loc.get("meta-unknownid", cls));
if (val instanceof String
&& !_conf.getCompatibilityInstance().getStrictIdentityValues())
{
// bug #958: section 9.6 of the JDO 1.0.1 specification states
// that a fatal internal exception should be thrown when
// invoking this method on an abstract class
if (Modifier.isAbstract(cls.getModifiers()))
throw new InternalException(_loc.get("objectid-abstract",
cls));
return PCRegistry.newObjectId(cls, (String) val);
} }
if (ImplHelper.isAssignable(meta.getObjectIdType(), val.getClass()))
{
if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared())
return new ObjectId(cls, val);
return val;
}
Object[] arr = (val instanceof Object[]) ? (Object[]) val
: new Object[]{ val };
return ApplicationIds.fromPKValues(arr, meta);
} catch (OpenJPAException ke) { } catch (OpenJPAException ke) {
throw ke; throw ke;
} catch (ClassCastException cce) { } catch (ClassCastException cce) {

View File

@ -27,6 +27,7 @@ import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.kernel.ObjectIdStateManager; import org.apache.openjpa.kernel.ObjectIdStateManager;
import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.StoreManager; import org.apache.openjpa.kernel.StoreManager;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.JavaTypes;
@ -41,6 +42,9 @@ import serp.util.Numbers;
*/ */
public class ApplicationIds { public class ApplicationIds {
private static final Localizer _loc = Localizer.forPackage
(ApplicationIds.class);
/** /**
* Return the primary key values for the given object id. The values * Return the primary key values for the given object id. The values
* will be returned in the same order as the metadata primary key fields. * will be returned in the same order as the metadata primary key fields.
@ -165,6 +169,8 @@ public class ApplicationIds {
// default to reflection // default to reflection
Class oidType = meta.getObjectIdType(); Class oidType = meta.getObjectIdType();
if (Modifier.isAbstract(oidType.getModifiers()))
throw new UserException(_loc.get("objectid-abstract", meta));
Object copy = null; Object copy = null;
try { try {
copy = oidType.newInstance(); copy = oidType.newInstance();

View File

@ -180,8 +180,6 @@ dup-load: Cannot load object with id "{0}". Instance "{1}" with the same id \
already exists in the L1 cache. This can occur when you \ already exists in the L1 cache. This can occur when you \
assign an existing id to a new instance, and before flushing attempt to \ assign an existing id to a new instance, and before flushing attempt to \
load the existing instance for that id. load the existing instance for that id.
objectid-abstract: Cannot create new application identity instance for \
abstract class "{0}".
bad-id-value: The given value "{0}" cannot be converted into an identity \ bad-id-value: The given value "{0}" cannot be converted into an identity \
for "{2}". The value is the wrong type ({1}). for "{2}". The value is the wrong type ({1}).
factory-init: Starting OpenJPA {0} factory-init: Starting OpenJPA {0}

View File

@ -16,7 +16,8 @@ failed: Failed:
nested: Nested: nested: Nested:
null-oid: Null id value encountered while creating datastore identity for "{0}". null-oid: Null id value encountered while creating datastore identity for "{0}".
unknown-oid: While creating datastore identity for "{0}", unknown id value \ unknown-oid: While creating datastore identity for "{0}", unknown id value \
"{1}" of type "{2}" encountered. Cannot convert to org.apache.openjpa.util.Id. "{1}" of type "{2}" encountered. Cannot convert to \
org.apache.openjpa.util.Id.
bad-ser-oid: Encountered object id "{0}" in serialized data, but the \ bad-ser-oid: Encountered object id "{0}" in serialized data, but the \
corresponding persistent object no longer exists. Substituting null into \ corresponding persistent object no longer exists. Substituting null into \
the deserialization stream. the deserialization stream.
@ -67,3 +68,5 @@ dup-oid: A duplicate object id exception has occurred. Each object you \
unique: A unique constraint violation has occurred. unique: A unique constraint violation has occurred.
ref-integrity: A referential integrity constraint has occurred. ref-integrity: A referential integrity constraint has occurred.
no-store-exts: No store-specific facade found matching "{0}". Using default. no-store-exts: No store-specific facade found matching "{0}". Using default.
objectid-abstract: Cannot create new application identity instance for \
abstract class "{0}".

View File

@ -0,0 +1,38 @@
/*
* Copyright 2006 The Apache Software Foundation.
*
* Licensed 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.openjpa.persistence.inheritance;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class AbstractBase {
@Id
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2006 The Apache Software Foundation.
*
* Licensed 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.openjpa.persistence.inheritance;
import javax.persistence.Entity;
@Entity
public class ConcreteSubclass
extends AbstractBase {
private int subclassData;
public int getSubclassData() {
return subclassData;
}
public void setSubclassData(int subclassData) {
this.subclassData = subclassData;
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2006 The Apache Software Foundation.
*
* Licensed 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.openjpa.persistence.inheritance;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import junit.framework.TestCase;
import junit.textui.TestRunner;
/**
* Test that you can find a concrete subclass record when passing in its
* abstract base class to EntityManager.find().
*
* @author Abe White
*/
public class TestFindAbstractClass
extends TestCase {
private EntityManagerFactory emf;
public void setUp() {
String types = AbstractBase.class.getName() + ";"
+ ConcreteSubclass.class.getName();
Map props = new HashMap(System.getProperties());
props.put("openjpa.MetaDataFactory", "jpa(Types=" + types + ")");
emf = Persistence.createEntityManagerFactory("test", props);
ConcreteSubclass e = new ConcreteSubclass();
e.setId("id");
e.setSubclassData(1);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
em.getTransaction().commit();
em.close();
}
public void tearDown() {
if (emf == null)
return;
try {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.createQuery("delete from ConcreteSubclass").executeUpdate();
em.getTransaction().commit();
em.close();
emf.close();
} catch (Exception e) {
}
}
public void testFind() {
EntityManager em = emf.createEntityManager();
AbstractBase e = em.find(AbstractBase.class, "id");
assertNotNull(e);
assertTrue(e instanceof ConcreteSubclass);
assertEquals(1, ((ConcreteSubclass) e).getSubclassData());
em.close();
}
public static void main(String[] args) {
TestRunner.run(TestFindAbstractClass.class);
}
}