You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2008/01/23 19:15:13 UTC

svn commit: r614606 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ openjpa-kernel/src/main/resources/org/apache/openjpa/meta/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/ openjpa-pe...

Author: pcl
Date: Wed Jan 23 10:15:09 2008
New Revision: 614606

URL: http://svn.apache.org/viewvc?rev=614606&view=rev
Log:
Improve error message when checking metadata access types; correct recursive method to always include superclass information.

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestMixedAccess.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedInappropriateTransient.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedMixedAccess.java
Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
    openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java?rev=614606&r1=614605&r2=614606&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java Wed Jan 23 10:15:09 2008
@@ -24,6 +24,7 @@
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
+import java.util.List;
 
 import org.apache.openjpa.enhance.PCRegistry;
 import org.apache.openjpa.enhance.Reflection;
@@ -153,9 +154,17 @@
             // the same time
             access = getAccessType(meta);
             if ((access & ClassMetaData.ACCESS_FIELD) != 0
-                && (access & ClassMetaData.ACCESS_PROPERTY) != 0)
-                throw new UserException(_loc.get("access-field-and-prop",
-                    meta.getDescribedType().getName()));
+                && (access & ClassMetaData.ACCESS_PROPERTY) != 0) {
+                List fields = getFieldAccessNames(meta);
+                List props = getPropertyAccessNames(meta);
+                if (fields != null || props != null)
+                    throw new UserException(_loc.get(
+                        "access-field-and-prop-hints",
+                        meta.getDescribedType().getName(), fields, props));
+                else
+                    throw new UserException(_loc.get("access-field-and-prop",
+                        meta.getDescribedType().getName()));
+            }
         }
         meta.setAccessType(access);
 
@@ -261,6 +270,34 @@
      */
     protected int getAccessType(ClassMetaData meta) {
         return ClassMetaData.ACCESS_FIELD;
+    }
+
+    /**
+     * Return the list of fields in <code>meta</code> that use field access,
+     * or <code>null</code> if a list of fields is unobtainable. An empty list
+     * should be returned if the list of fields is obtainable, but there
+     * happens to be no field access in <code>meta</code>.
+     *
+     * This is used for error reporting purposes only, so need not be efficient.
+     *
+     * This implementation returns <code>null</code>.
+     */
+    protected List getFieldAccessNames(ClassMetaData meta) {
+        return null;
+    }
+
+    /**
+     * Return the list of methods in <code>meta</code> that use property access,
+     * or <code>null</code> if a list of methods is unobtainable. An empty list
+     * should be returned if the list of methods is obtainable, but there
+     * happens to be no property access in <code>meta</code>.
+     *
+     * This is used for error reporting purposes only, so need not be efficient.
+     *
+     * This implementation returns <code>null</code>.
+     */
+    protected List getPropertyAccessNames(ClassMetaData meta) {
+        return null;
     }
 
     /**

Modified: openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties?rev=614606&r1=614605&r2=614606&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties (original)
+++ openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties Wed Jan 23 10:15:09 2008
@@ -267,6 +267,10 @@
 	the lifecycle metadata is already resolved: {1}
 access-field-and-prop: Type "{0}" attempts to use both field and property \
 	access. Only one access method is permitted.
+access-field-and-prop-hints: Type "{0}" attempts to use both field and \
+	property access. Only one access method is permitted. Field access is used \
+    on the following fields: {1}. Property access is used on the following \
+    methods: {2}.
 unsupported-id-type: Type "{0}" declares field "{1}" as a primary key, but \
 	keys of type "{2}" are not supported.
 empty-fg-name: Attempt to add an unnamed fetch group to "{0}".

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestMixedAccess.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestMixedAccess.java?rev=614606&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestMixedAccess.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestMixedAccess.java Wed Jan 23 10:15:09 2008
@@ -0,0 +1,52 @@
+/*
+ * 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.openjpa.persistence.jdbc.annotations;
+
+import javax.persistence.PersistenceException;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.openjpa.persistence.test.PersistenceTestCase;
+
+public class TestMixedAccess extends PersistenceTestCase {
+
+    public void testMixedAccessEntityError() {
+        try {
+            EntityManagerFactory emf = createEMF(UnenhancedMixedAccess.class);
+            emf.createEntityManager().close();
+        } catch (RuntimeException e) {
+            String msg = e.getMessage();
+            if (!(msg.contains("UnenhancedMixedAccess.id") &&
+                msg.contains("UnenhancedMixedAccess.getStringField")))
+                throw e;
+        }
+    }
+
+    public void testInappropriateTransientError() {
+        try {
+            EntityManagerFactory emf = createEMF(
+                UnenhancedInappropriateTransient.class);
+            emf.createEntityManager().close();
+         } catch (RuntimeException e) {
+            String msg = e.getMessage();
+            if (!(msg.contains("UnenhancedInappropriateTransient.id") &&
+                msg.contains("UnenhancedInappropriateTransient.prePersist")))
+                throw e;
+        }
+    }
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedInappropriateTransient.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedInappropriateTransient.java?rev=614606&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedInappropriateTransient.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedInappropriateTransient.java Wed Jan 23 10:15:09 2008
@@ -0,0 +1,34 @@
+/*
+ * 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.openjpa.persistence.jdbc.annotations;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Transient;
+import javax.persistence.PrePersist;
+
+@Entity
+public class UnenhancedInappropriateTransient {
+
+    @Id private int id;
+
+    @Transient @PrePersist public void prePersist() {
+        throw new UnsupportedOperationException();
+    }
+}
\ No newline at end of file

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedMixedAccess.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedMixedAccess.java?rev=614606&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedMixedAccess.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/UnenhancedMixedAccess.java Wed Jan 23 10:15:09 2008
@@ -0,0 +1,37 @@
+/*
+ * 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.openjpa.persistence.jdbc.annotations;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Transient;
+
+@Entity
+public class UnenhancedMixedAccess {
+
+    @Id private int id;
+
+    @Transient public String getStringField() {
+        throw new UnsupportedOperationException();
+    }
+
+    public void setStringField(String str) {
+        throw new UnsupportedOperationException();
+    }
+}

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java?rev=614606&r1=614605&r2=614606&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java Wed Jan 23 10:15:09 2008
@@ -30,6 +30,8 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
 import javax.persistence.Basic;
 import javax.persistence.Embeddable;
 import javax.persistence.Embedded;
@@ -257,22 +259,36 @@
             return ClassMetaData.ACCESS_UNKNOWN;
 
         int access = 0;
-        if (usesAccess((Field[]) AccessController.doPrivileged(
-            J2DoPriv5Helper.getDeclaredFieldsAction(cls))))
+        if (annotated((Field[]) AccessController.doPrivileged(
+            J2DoPriv5Helper.getDeclaredFieldsAction(cls))).size() > 0)
             access |= ClassMetaData.ACCESS_FIELD;
-        if (usesAccess((Method[]) AccessController.doPrivileged(
-            J2DoPriv5Helper.getDeclaredMethodsAction(cls)))
+        if (annotated((Method[]) AccessController.doPrivileged(
+            J2DoPriv5Helper.getDeclaredMethodsAction(cls))).size() > 0
             || cls.isInterface()) // OpenJPA managed ifaces must use prop access
             access |= ClassMetaData.ACCESS_PROPERTY;
-        return (access == 0) ? getAccessType(cls.getSuperclass()) : access;
+        return getAccessType(cls.getSuperclass()) | access;
+    }
+
+    @Override
+    protected List getFieldAccessNames(ClassMetaData meta) {
+        return annotated((Field[]) AccessController.doPrivileged(
+            J2DoPriv5Helper.getDeclaredFieldsAction(meta.getDescribedType())));
+    }
+
+    @Override
+    protected List getPropertyAccessNames(ClassMetaData meta) {
+        return annotated((Method[]) AccessController.doPrivileged(
+            J2DoPriv5Helper.getDeclaredMethodsAction(meta.getDescribedType())));
     }
 
     /**
-     * Return whether the given members have persistence annotations.
+     * Return the members of <code>members</code> that have persistence
+     * annotations.
      */
-    private static boolean usesAccess(AnnotatedElement[] members) {
+    private static List annotated(AnnotatedElement[] members) {
         Annotation[] annos;
         String name;
+        List annotated = new ArrayList(members.length);
         for (int i = 0; i < members.length; i++) {
             annos = (Annotation[]) AccessController.doPrivileged(J2DoPriv5Helper
                 .getAnnotationsAction(members[i]));
@@ -281,10 +297,10 @@
                 if ((name.startsWith("javax.persistence.")
                     || name.startsWith("org.apache.openjpa.persistence."))
                     && !_ignoredAnnos.contains(name))
-                    return true;
+                    annotated.add(members[i]);
             }
         }
-        return false;
+        return annotated;
     }
 
     protected boolean isDefaultPersistent(ClassMetaData meta, Member member,