You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2009/11/04 22:18:39 UTC
svn commit: r832874 - in /openjpa/trunk:
openjpa-kernel/src/main/java/org/apache/openjpa/conf/
openjpa-kernel/src/main/java/org/apache/openjpa/datacache/
openjpa-kernel/src/main/java/org/apache/openjpa/enhance/
openjpa-kernel/src/main/resources/org/apa...
Author: ppoddar
Date: Wed Nov 4 21:18:38 2009
New Revision: 832874
URL: http://svn.apache.org/viewvc?rev=832874&view=rev
Log:
OPENJPA-1334: Refresh should ignore cache.retrieve.mode settings. Assorted changes in property processing for usability
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestRefresh.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/JPAProperties.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java
openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java Wed Nov 4 21:18:38 2009
@@ -374,6 +374,8 @@
* The entities are never refreshed from DataCache if lock is being applied
* (e.g. in a pessimistic transaction) and hence this setting only refers
* to behavior when not locking.
+ * This flag can be used to overwrite RetrieveMode.BYPASS.
+ * By default, however, this falg is false.
*
* @since 1.2.0
*/
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java Wed Nov 4 21:18:38 2009
@@ -387,8 +387,7 @@
public boolean load(OpenJPAStateManager sm, BitSet fields,
FetchConfiguration fetch, int lockLevel, Object edata) {
DataCache cache = _mgr.selectCache(sm);
- if (cache == null || sm.isEmbedded()
- || _ctx.getFetchConfiguration().getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS)
+ if (cache == null || sm.isEmbedded() || bypass(_ctx.getFetchConfiguration(), StoreManager.FORCE_LOAD_NONE))
return super.load(sm, fields, fetch, lockLevel, edata);
DataCachePCData data = cache.get(sm.getObjectId());
@@ -410,11 +409,8 @@
public Collection<Object> loadAll(Collection<OpenJPAStateManager> sms, PCState state, int load,
FetchConfiguration fetch, Object edata) {
- if (isLocking(fetch) ||
- (!isLocking(fetch) &&
- (load == StoreManager.FORCE_LOAD_REFRESH)
- && !_ctx.getConfiguration().getRefreshFromDataCache())) {
- return super.loadAll(sms, state, load, fetch, edata);
+ if (bypass(fetch, load)) {
+ return super.loadAll(sms, state, load, fetch, edata);
}
Map<OpenJPAStateManager, BitSet> unloaded = null;
@@ -528,7 +524,7 @@
}
return failed;
}
-
+
/**
* Helper method to add an unloaded instance to the given map.
*/
@@ -691,6 +687,24 @@
}
/**
+ * Affirms if a load operation must bypass the L2 cache.
+ * If lock is active, always bypass.
+ *
+ */
+ boolean bypass(FetchConfiguration fetch, int load) {
+ // Order of checks are important
+ if (isLocking(fetch))
+ return true;
+ if (_ctx.getConfiguration().getRefreshFromDataCache())
+ return false;
+ if (fetch.getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS)
+ return true;
+ if (load == StoreManager.FORCE_LOAD_REFRESH)
+ return true;
+ return false;
+ }
+
+ /**
* Return whether the context is locking loaded data.
*/
private boolean isLocking(FetchConfiguration fetch) {
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java Wed Nov 4 21:18:38 2009
@@ -34,6 +34,7 @@
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.ReferenceMap;
import org.apache.openjpa.lib.util.Reflectable;
+import org.apache.openjpa.lib.util.Localizer.Message;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.UserException;
@@ -282,7 +283,7 @@
try {
return field.get(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -327,9 +328,10 @@
/**
* Wrap the given reflection exception as a runtime exception.
*/
- private static RuntimeException wrapReflectionException(Throwable t) {
+ private static RuntimeException wrapReflectionException(Throwable t, Message message) {
if (t instanceof InvocationTargetException)
- t = ((InvocationTargetException) t).getTargetException();
+ t = ((InvocationTargetException) t).getTargetException();
+ t.initCause(new IllegalArgumentException(message.getMessage()));
if (t instanceof RuntimeException)
return (RuntimeException) t;
return new GeneralException(t);
@@ -345,7 +347,7 @@
try {
return field.getBoolean(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -359,7 +361,7 @@
try {
return field.getByte(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -373,7 +375,7 @@
try {
return field.getChar(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -387,7 +389,7 @@
try {
return field.getDouble(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -401,7 +403,7 @@
try {
return field.getFloat(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -415,7 +417,7 @@
try {
return field.getInt(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -429,7 +431,7 @@
try {
return field.getLong(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -443,7 +445,7 @@
try {
return field.getShort(target);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-field", target, field));
}
}
@@ -457,7 +459,7 @@
try {
return getter.invoke(target, (Object[]) null);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("get-method", target, getter));
}
}
@@ -535,7 +537,8 @@
try {
field.set(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value,
+ value == null ? "" : value.getClass()}));
}
}
@@ -549,7 +552,7 @@
try {
field.setBoolean(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "boolean"}));
}
}
@@ -563,7 +566,7 @@
try {
field.setByte(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "byte"}));
}
}
@@ -577,7 +580,7 @@
try {
field.setChar(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "char"}));
}
}
@@ -591,7 +594,7 @@
try {
field.setDouble(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "double"}));
}
}
@@ -605,7 +608,7 @@
try {
field.setFloat(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "float"}));
}
}
@@ -619,7 +622,7 @@
try {
field.setInt(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "int"}));
}
}
@@ -633,7 +636,7 @@
try {
field.setLong(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "long"}));
}
}
@@ -647,7 +650,7 @@
try {
field.setShort(target, value);
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-field", new Object[]{target, field, value, "short"}));
}
}
@@ -760,7 +763,8 @@
try {
setter.invoke(target, new Object[] { value });
} catch (Throwable t) {
- throw wrapReflectionException(t);
+ throw wrapReflectionException(t, _loc.get("set-method", new Object[]{target, setter, value,
+ value == null ? "" : value.getClass()}));
}
}
@@ -831,16 +835,16 @@
* it is ignored.
*
*/
- public static Set<String> getBeanStylePropertyNames(Class c) {
+ public static Set<String> getBeanStylePropertyNames(Class<?> c) {
if (c == null)
- return Collections.EMPTY_SET;
+ return Collections.emptySet();
Set<String> result = beanPropertiesNameCache.get(c);
if (result != null) {
return result;
}
Method[] methods = c.getMethods();
if (methods == null || methods.length < 2)
- return Collections.EMPTY_SET;
+ return Collections.emptySet();
result = new TreeSet<String>();
for (Method m : methods) {
if (m.getName().startsWith("get")) {
@@ -848,9 +852,9 @@
continue;
String prop = StringUtils.capitalize(m.getName()
.substring("get".length()));
- Class rtype = m.getReturnType();
+ Class<?> rtype = m.getReturnType();
try {
- Method setter = c.getMethod("set"+prop, new Class[]{rtype});
+ Method setter = c.getMethod("set"+prop, new Class<?>[]{rtype});
if (setter.getReturnType() == void.class ||
setter.getReturnType().isAssignableFrom(c))
result.add(prop);
Modified: openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties (original)
+++ openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties Wed Nov 4 21:18:38 2009
@@ -211,4 +211,7 @@
to creating any Entities.
temp-file-creation: The temporary file "{0}" was created and it may not get \
cleaned up properly.
-
+get-field: Error while getting value of field {1} from instance {0} by reflection.
+get-method: Error while getting value by getter method {1} on instance {0} by reflection.
+set-field: Error while setting value {2} of {3} on field {1} of instance {0} by reflection.
+set-method: Error while setting value {2} of {3} by setter method {1} of instance {0} by reflection.
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheBehavesIdentical.java Wed Nov 4 21:18:38 2009
@@ -56,9 +56,8 @@
private static final boolean DIRTY = true;
private static final boolean REFRESH_FROM_DATACACHE = true;
private static final LockModeType NOLOCK = null;
- private static final Class ENTITY_NOT_FOUND_ERROR =
- EntityNotFoundException.class;
- private static final Class NO_ERROR = null;
+ private static final Class<?> ENTITY_NOT_FOUND_ERROR = EntityNotFoundException.class;
+ private static final Class<?> NO_ERROR = null;
private static final String MARKER_DATACACHE = "in DataCache";
private static final String MARKER_DATABASE = "in Database";
@@ -376,7 +375,7 @@
public void testDirtyRefreshWithNoLockHitsDatabase() {
verifyRefresh(WITH_DATACACHE, NOLOCK, DIRTY, !REFRESH_FROM_DATACACHE,
- MARKER_DATACACHE);
+ MARKER_DATABASE);
}
public void testDirtyRefreshWithNoLockHitsDataCache() {
@@ -464,7 +463,7 @@
* @param lock
*/
public void verifyDeleteDetectionOnRefresh(boolean useDataCache,
- boolean dirty, LockModeType lock, Class expectedExceptionType) {
+ boolean dirty, LockModeType lock, Class<?> expectedExceptionType) {
OpenJPAEntityManagerFactorySPI emf = (useDataCache)
? emfWithDataCache : emfWithoutDataCache;
@@ -522,49 +521,36 @@
}
}
- public void testDeleteIsNotDetectedOnCleanRefreshWithoutLockWithDataCache()
- {
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY, NOLOCK,
- NO_ERROR);
+ public void testDeleteIsNotDetectedOnCleanRefreshWithoutLockWithDataCache() {
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY, NOLOCK, NO_ERROR);
}
public void testDeleteIsDetectedOnCleanRefreshWithLockWithDataCache() {
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY,
- LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY,
- LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
- public void testDeleteIsNotDetectedOnDirtyRefreshWithoutLockWithDataCache()
- {
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, NOLOCK, NO_ERROR);
+ public void testDeleteIsDetectedOnDirtyRefreshWithoutLockWithDataCache() {
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, NOLOCK, ENTITY_NOT_FOUND_ERROR);
}
public void testDeleteIsDetectedOnDirtyRefreshWithLockWithDataCache() {
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.READ,
- ENTITY_NOT_FOUND_ERROR);
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY,
- LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
public void testDeleteIsDetectedOnDirtyRefreshWitDataCache() {
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.READ,
- ENTITY_NOT_FOUND_ERROR);
- verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY,
- LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
- public void testDeleteIsDetectedOnCleanRefreshWithoutLockWithoutDataCache()
- {
- verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, !DIRTY, NOLOCK,
- ENTITY_NOT_FOUND_ERROR);
+ public void testDeleteIsDetectedOnCleanRefreshWithoutLockWithoutDataCache() {
+ verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, !DIRTY, NOLOCK, ENTITY_NOT_FOUND_ERROR);
}
public void testDeleteIsDetectedOnCleanRefreshWithLockWithoutDataCache() {
- verifyDeleteDetectionOnRefresh(!WITH_DATACACHE,
- !DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
- verifyDeleteDetectionOnRefresh(!WITH_DATACACHE,
- !DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, !DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
+ verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, !DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestRefresh.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestRefresh.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestRefresh.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestRefresh.java Wed Nov 4 21:18:38 2009
@@ -18,12 +18,26 @@
*/
package org.apache.openjpa.persistence.simple;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Map;
+
+import javax.persistence.CacheRetrieveMode;
+import javax.persistence.CacheStoreMode;
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.persistence.JPAProperties;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.test.SingleEMTestCase;
public class TestRefresh extends SingleEMTestCase {
public void setUp() {
- super.setUp(CLEAR_TABLES, Item.class, "openjpa.AutoDetach", "commit");
+ super.setUp(CLEAR_TABLES, Item.class,
+ "openjpa.AutoDetach", "commit",
+ "openjpa.DataCache", "true",
+ "openjpa.RemoteCommitProvider", "sjvm");
}
public void testFlushRefreshNewInstance() {
@@ -36,4 +50,79 @@
em.getTransaction().commit();
assertEquals("Test Data", item.getItemData());
}
+
+ /**
+ * Refresh always bypass L2 cache.
+ * According to JPA 2.0 Spec Section 3.7.2:
+ * "The retrieveMode property is ignored for the refresh method,
+ * which always causes data to be retrieved from the database, not the cache."
+ */
+ public void testRefreshBypassL2Cache() {
+ String original = "Original L2 Cached Data";
+ String sneakUpdate = "Sneak Update";
+ em.getTransaction().begin();
+ Item item = new Item();
+ item.setItemData(original);
+ em.persist(item);
+ em.getTransaction().commit();
+ assertCached(Item.class, item.getItemId());
+
+ // Sneakily update with SQL
+ String sql = "UPDATE I_ITEM SET I_DATA=?1 WHERE I_ID=?2";
+ em.getTransaction().begin();
+ int updateCount = em.createNativeQuery(sql)
+ .setParameter(1, sneakUpdate)
+ .setParameter(2, item.getItemId())
+ .executeUpdate();
+ assertEquals(1, updateCount);
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ // Find will find the L2 cached data
+ item = em.find(Item.class, item.getItemId());
+ assertEquals(original, item.getItemData());
+ // But refresh will get the actual database record
+ em.refresh(item);
+ assertEquals(sneakUpdate, item.getItemData());
+
+ // Even if cache retrieve mode is set to USE
+ em.setProperty(JPAProperties.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
+ em.refresh(item);
+ assertEquals(sneakUpdate, item.getItemData());
+ em.getTransaction().rollback();
+ }
+
+ public void testCacheRetrieveModeSetting() {
+ OpenJPAEntityManager em = emf.createEntityManager();
+ em.setProperty(JPAProperties.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
+ Map<String, Object> properties = em.getProperties();
+ if (!properties.containsKey(JPAProperties.CACHE_RETRIEVE_MODE)) {
+ System.err.println(properties);
+ fail("Expected " + JPAProperties.CACHE_RETRIEVE_MODE + " properties be returned");
+ }
+ Object mode = properties.get(JPAProperties.CACHE_RETRIEVE_MODE);
+ assertEquals(mode, CacheRetrieveMode.USE);
+ }
+
+ public void testCacheStoreModeSetting() {
+ OpenJPAEntityManager em = emf.createEntityManager();
+ em.setProperty(JPAProperties.CACHE_STORE_MODE, CacheStoreMode.USE);
+ Map<String, Object> properties = em.getProperties();
+ if (!properties.containsKey(JPAProperties.CACHE_STORE_MODE)) {
+ System.err.println(properties);
+ fail("Expected " + JPAProperties.CACHE_STORE_MODE + " properties be returned");
+ }
+ Object mode = properties.get(JPAProperties.CACHE_STORE_MODE);
+ assertEquals(mode, CacheStoreMode.USE);
+ }
+
+
+ void assertCached(Class<?> cls, Object oid) {
+ assertTrue(cls + ":" + oid + " should be in L2 cache, but not", emf.getCache().contains(cls, oid));
+ }
+
+ void assertNotCached(Class<?> cls, Object oid) {
+ assertTrue(cls + ":" + oid + " should not be in L2 cache, but is", !emf.getCache().contains(cls, oid));
+ }
+
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Wed Nov 4 21:18:38 2009
@@ -33,6 +33,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
@@ -49,6 +50,7 @@
import javax.persistence.metamodel.Metamodel;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.LogFactory;
import org.apache.openjpa.conf.Compatibility;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.ee.ManagedRuntime;
@@ -105,11 +107,7 @@
private DelegatingBroker _broker;
private EntityManagerFactoryImpl _emf;
private Map<FetchConfiguration,FetchPlan> _plans = new IdentityHashMap<FetchConfiguration,FetchPlan>(1);
-
private RuntimeExceptionTranslator _ret = PersistenceExceptions.getRollbackTranslator(this);
-
- protected final String RETRIEVE_MODE_PROP = "javax.persistence.cache.retrieveMode";
- protected final String STORE_MODE_PROP = "javax.persistence.cache.storeMode";
public EntityManagerImpl() {
// for Externalizable
@@ -732,10 +730,7 @@
}
public void refresh(Object entity) {
- assertNotCloseInvoked();
- assertValidAttchedEntity(entity);
- _broker.assertWriteOperation();
- _broker.refresh(entity, this);
+ refresh(entity, null, null);
}
public void refresh(Object entity, LockModeType mode) {
@@ -748,11 +743,19 @@
public void refresh(Object entity, LockModeType mode, Map<String, Object> properties) {
assertNotCloseInvoked();
- assertValidAttchedEntity(entity);
+ assertValidAttchedEntity("refresh", entity);
_broker.assertWriteOperation();
-
configureCurrentFetchPlan(pushFetchPlan(), properties, mode, true);
+ DataCacheRetrieveMode rmode = getFetchPlan().getCacheRetrieveMode();
+ if (DataCacheRetrieveMode.USE.equals(rmode) || rmode == null) {
+ getFetchPlan().setCacheRetrieveMode(DataCacheRetrieveMode.BYPASS);
+ if (rmode != null) {
+ Log log = _broker.getConfiguration().getConfigurationLog();
+ log.warn(_loc.get("cache-retrieve-override", Exceptions.toString(entity)));
+ }
+
+ }
try {
_broker.refresh(entity, this);
} finally {
@@ -1121,7 +1124,7 @@
public LockModeType getLockMode(Object entity) {
assertNotCloseInvoked();
_broker.assertActiveTransaction();
- assertValidAttchedEntity(entity);
+ assertValidAttchedEntity("getLockMode", entity);
return MixedLockLevelsHelper.fromLockLevel(
_broker.getLockLevel(entity));
}
@@ -1132,13 +1135,13 @@
public void lock(Object entity) {
assertNotCloseInvoked();
- assertValidAttchedEntity(entity);
+ assertValidAttchedEntity("lock", entity);
_broker.lock(entity, this);
}
public void lock(Object entity, LockModeType mode, int timeout) {
assertNotCloseInvoked();
- assertValidAttchedEntity(entity);
+ assertValidAttchedEntity("lock", entity);
configureCurrentFetchPlan(pushFetchPlan(), null, mode, false);
try {
@@ -1150,7 +1153,7 @@
public void lock(Object entity, LockModeType mode, Map<String, Object> properties) {
assertNotCloseInvoked();
- assertValidAttchedEntity(entity);
+ assertValidAttchedEntity("lock", entity);
_broker.assertActiveTransaction();
configureCurrentFetchPlan(pushFetchPlan(), properties, mode, false);
@@ -1315,11 +1318,11 @@
* Throw IllegalArgumentExceptionif if entity is not a valid entity or
* if it is detached.
*/
- void assertValidAttchedEntity(Object entity) {
+ void assertValidAttchedEntity(String call, Object entity) {
OpenJPAStateManager sm = _broker.getStateManager(entity);
if (sm == null || !sm.isPersistent() || sm.isDetached()) {
- throw new IllegalArgumentException(_loc.get(
- "invalid_entity_argument").getMessage());
+ throw new IllegalArgumentException(_loc.get("invalid_entity_argument",
+ call, entity == null ? "null" : Exceptions.toString(entity)).getMessage());
}
}
@@ -1556,12 +1559,36 @@
return createQuery(jpql);
}
+ /**
+ * Get the properties used currently by this entity manager.
+ * The property keys and their values are harvested from kernel artifacts namely
+ * the Broker and FetchPlan by reflection.
+ * These property keys and values that denote the bean properties/values of the kernel artifacts
+ * are converted to the original keys/values that user used to set the properties.
+ *
+ */
public Map<String, Object> getProperties() {
- Map props = _broker.getProperties();
+ Map<String,Object> props = _broker.getProperties();
for (String s : _broker.getSupportedProperties()) {
- Method getter = Reflection.findGetter(this.getClass(), getBeanPropertyName(s), false);
- if (getter != null)
- props.put(s, Reflection.get(this, getter));
+ String kernelKey = getBeanPropertyName(s);
+ Method getter = Reflection.findGetter(this.getClass(), kernelKey, false);
+ if (getter != null) {
+ String userKey = JPAProperties.getUserName(kernelKey);
+ Object kvalue = Reflection.get(this, getter);
+ props.put(userKey.equals(kernelKey) ? s : userKey, JPAProperties.convertToUserValue(userKey, kvalue));
+ }
+ }
+ FetchPlan fetch = getFetchPlan();
+ Class<?> fetchType = fetch.getClass();
+ Set<String> fProperties = Reflection.getBeanStylePropertyNames(fetchType);
+ for (String s : fProperties) {
+ String kernelKey = getBeanPropertyName(s);
+ Method getter = Reflection.findGetter(fetchType, kernelKey, false);
+ if (getter != null) {
+ String userKey = JPAProperties.getUserName(kernelKey);
+ Object kvalue = Reflection.get(fetch, getter);
+ props.put(userKey.equals(kernelKey) ? s : userKey, JPAProperties.convertToUserValue(userKey, kvalue));
+ }
}
return props;
}
@@ -1621,17 +1648,17 @@
private void configureCurrentCacheModes(FetchPlan fetch, Map<String, Object> properties) {
if (properties == null)
return;
- CacheRetrieveMode rMode = JPAProperties.get(CacheRetrieveMode.class, JPAProperties.CACHE_RETRIEVE_MODE,
- properties);
+ CacheRetrieveMode rMode = JPAProperties.getEnumValue(CacheRetrieveMode.class,
+ JPAProperties.CACHE_RETRIEVE_MODE, properties);
if (rMode != null) {
- fetch.setCacheRetrieveMode(JPAProperties.convertValue(DataCacheRetrieveMode.class,
+ fetch.setCacheRetrieveMode(JPAProperties.convertToKenelValue(DataCacheRetrieveMode.class,
JPAProperties.CACHE_RETRIEVE_MODE, rMode));
properties.remove(JPAProperties.CACHE_RETRIEVE_MODE);
}
- CacheStoreMode sMode = JPAProperties.get(CacheStoreMode.class, JPAProperties.CACHE_STORE_MODE,
- properties);
+ CacheStoreMode sMode = JPAProperties.getEnumValue(CacheStoreMode.class,
+ JPAProperties.CACHE_STORE_MODE, properties);
if (sMode != null) {
- fetch.setCacheStoreMode(JPAProperties.convertValue(DataCacheStoreMode.class,
+ fetch.setCacheStoreMode(JPAProperties.convertToKenelValue(DataCacheStoreMode.class,
JPAProperties.CACHE_STORE_MODE, sMode));
properties.remove(JPAProperties.CACHE_STORE_MODE);
}
@@ -1670,6 +1697,7 @@
*/
private boolean setKernelProperty(Object target, String original, Object value) {
String beanProp = getBeanPropertyName(original);
+ JPAProperties.record(beanProp, original);
Class<?> kType = null;
Object kValue = null;
Method setter = Reflection.findSetter(target.getClass(), beanProp, false);
@@ -1694,20 +1722,25 @@
* Extract a bean-style property name from the given string.
* If the given string is <code>"a.b.xyz"</code> then returns <code>"xyz"</code>
*/
- String getBeanPropertyName(String s) {
- if (JPAProperties.isValidKey(s)) {
- return JPAProperties.getBeanProperty(s);
+ String getBeanPropertyName(String user) {
+ String result = user;
+ if (JPAProperties.isValidKey(user)) {
+ result = JPAProperties.getBeanProperty(user);
+ } else {
+ int dot = user.lastIndexOf('.');
+ if (dot != -1)
+ result = user.substring(dot+1);
}
- int dot = s.lastIndexOf('.');
- return dot == -1 ? s : s.substring(dot+1);
+ return result;
}
+
/**
* Convert the given value to a value consumable by OpenJPA kernel constructs.
*/
Object convertUserValue(String key, Object value, Class<?> targetType) {
if (JPAProperties.isValidKey(key))
- return JPAProperties.convertValue(targetType, key, value);
+ return JPAProperties.convertToKenelValue(targetType, key, value);
if (value instanceof String) {
if ("null".equals(value)) {
return null;
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/JPAProperties.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/JPAProperties.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/JPAProperties.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/JPAProperties.java Wed Nov 4 21:18:38 2009
@@ -18,6 +18,7 @@
*/
package org.apache.openjpa.persistence;
+import java.util.HashMap;
import java.util.Map;
import javax.persistence.CacheRetrieveMode;
@@ -68,13 +69,29 @@
public static final String VALIDATE_PRE_PERSIST = PREFIX + "validation.group.pre-persist";
public static final String VALIDATE_PRE_REMOVE = PREFIX + "validation.group.pre-remove";
public static final String VALIDATE_PRE_UPDATE = PREFIX + "validation.group.pre-update";
-
public static final String VALIDATE_GROUP_DEFAULT = "javax.validation.groups.Default";
+ private static Map<String,String> _names = new HashMap<String, String>();
+
+ /**
+ * Record the given kernel property key (which is a bean property name without any suffix)
+ * corresponding to the given original JPA/OpenJPA property used by the user to set the values.
+ */
+ static void record(String kernel, String user) {
+ _names.put(kernel, user);
+ }
+
+ /**
+ * Gets the original JPA Property name corresponding to the kernel property key
+ * (which is a bean property name without any suffix).
+ */
+ static String getUserName(String beanProperty) {
+ return _names.containsKey(beanProperty) ? _names.get(beanProperty) : beanProperty;
+ }
+
/**
* Is the given key appears to be a valid JPA specification defined key?
*
- * @param key
* @return true if the given string merely prefixed with <code>javax.persistence.</code>.
* Does not really check all the keys defined in the specification.
*/
@@ -101,16 +118,12 @@
return buf.toString();
}
- static <E extends Enum<E>> E get(Class<E> type, String key, Map<String,Object> prop) {
- return getEnumValue(type, null, key, prop);
- }
-
/**
* Convert the given user value to a value consumable by OpenJPA kernel constructs.
*
* @return the same value if the given key is not a valid JPA property key or the value is null.
*/
- public static <T> T convertValue(Class<T> resultType, String key, Object value) {
+ public static <T> T convertToKenelValue(Class<T> resultType, String key, Object value) {
if (value == null)
return null;
if (JPAProperties.isValidKey(key)) {
@@ -124,7 +137,29 @@
return (T)value;
}
+ /**
+ * Convert the given kernel value to a value visible to the user.
+ *
+ * @return the same value if the given key is not a valid JPA property key or the value is null.
+ */
+ public static Object convertToUserValue(String key, Object value) {
+ if (value == null)
+ return null;
+ if (JPAProperties.isValidKey(key)) {
+ // works because enum values are identical String
+ if (value instanceof DataCacheRetrieveMode) {
+ return CacheRetrieveMode.valueOf(value.toString());
+ } else if (value instanceof DataCacheStoreMode) {
+ return CacheStoreMode.valueOf(value.toString());
+ }
+ }
+ return value;
+ }
+ /**
+ * Get the value of the given key from the given properties after converting it to the given
+ * enumerated value.
+ */
public static <E extends Enum<E>> E getEnumValue(Class<E> type, String key, Map<String,Object> prop) {
return getEnumValue(type, null, key, prop);
}
@@ -140,14 +175,28 @@
public static <E extends Enum<E>> E getEnumValue(Class<E> type, E[] values, String key, Map<String,Object> prop) {
if (prop == null)
return null;
- return getEnumValue(type, values, key, prop.get(key));
+ return getEnumValue(type, values, prop.get(key));
}
- public static <E extends Enum<E>> E getEnumValue(Class<E> type, String key, Object val) {
- return getEnumValue(type, null, key, val);
+ /**
+ * Gets a enum value of the given type from the given value.
+ * Converts the original value from a String, if necessary.
+ *
+ * @return null if the key does not exist in the given properties.
+ */
+ public static <E extends Enum<E>> E getEnumValue(Class<E> type, Object val) {
+ return getEnumValue(type, null, val);
}
- public static <E extends Enum<E>> E getEnumValue(Class<E> type, E[] values, String key, Object val) {
+ /**
+ * Gets a enum value of the given type from the given value.
+ * Converts the original value from a String or ordinal number, if necessary.
+ * Conversion from an integral number to enum value is only attempted if the allowed enum values
+ * are provided as non-null, non-empty array.
+ *
+ * @return null if the key does not exist in the given properties.
+ */
+ public static <E extends Enum<E>> E getEnumValue(Class<E> type, E[] values, Object val) {
if (val == null)
return null;
if (type.isInstance(val))
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java Wed Nov 4 21:18:38 2009
@@ -525,8 +525,7 @@
/**
* Return whether the given persistence unit uses an OpenJPA provider.
*/
- private static boolean isOpenJPAPersistenceProvider
- (PersistenceUnitInfo pinfo, ClassLoader loader) {
+ private static boolean isOpenJPAPersistenceProvider(PersistenceUnitInfo pinfo, ClassLoader loader) {
String provider = pinfo.getPersistenceProviderClassName();
if (StringUtils.isEmpty(provider) || PersistenceProviderImpl.class.getName().equals(provider))
return true;
@@ -742,11 +741,7 @@
// startPersistenceUnit()
// case 'property' for 'properties' is handled in startElement()
case 'c': // class
- if ("class".equals(name))
- _info.addManagedClassName(currentText());
- else // FIXME - caching
- throw new javax.persistence.PersistenceException(
- "Not implemented yet");
+ _info.addManagedClassName(currentText());
break;
case 'e': // exclude-unlisted-classes
setExcludeUnlistedClasses(currentText());
@@ -754,8 +749,7 @@
case 'j':
if ("jta-data-source".equals(name))
_info.setJtaDataSourceName(currentText());
- else // jar-file
- {
+ else { // jar-file
try {
_info.addJarFileName(currentText());
} catch (IllegalArgumentException iae) {
@@ -774,12 +768,10 @@
_info.setPersistenceProviderClassName(currentText());
break;
case 's' : // shared-cache-mode
- _info.setSharedCacheMode(JPAProperties.getEnumValue(SharedCacheMode.class,
- JPAProperties.CACHE_MODE, currentText()));
+ _info.setSharedCacheMode(JPAProperties.getEnumValue(SharedCacheMode.class, currentText()));
break;
case 'v': // validation-mode
- _info.setValidationMode(JPAProperties.getEnumValue(ValidationMode.class,
- JPAProperties.VALIDATE_MODE, currentText()));
+ _info.setValidationMode(JPAProperties.getEnumValue(ValidationMode.class, currentText()));
break;
}
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java Wed Nov 4 21:18:38 2009
@@ -307,8 +307,7 @@
if (JPAProperties.PROVIDER.equals(key))
setPersistenceProviderClassName((String) val);
else if (JPAProperties.TRANSACTION_TYPE.equals(key)) {
- setTransactionType(JPAProperties.getEnumValue(PersistenceUnitTransactionType.class,
- JPAProperties.TRANSACTION_TYPE, key));
+ setTransactionType(JPAProperties.getEnumValue(PersistenceUnitTransactionType.class, key));
} else if (JPAProperties.DATASOURCE_JTA.equals(key)) {
if (val instanceof String) {
setJtaDataSourceName((String) val);
@@ -322,9 +321,9 @@
setNonJtaDataSource((DataSource) val);
}
} else if (JPAProperties.VALIDATE_MODE.equals(key)) {
- setValidationMode(JPAProperties.getEnumValue(ValidationMode.class, JPAProperties.VALIDATE_MODE, val));
+ setValidationMode(JPAProperties.getEnumValue(ValidationMode.class, val));
} else if (JPAProperties.CACHE_MODE.equals(key)) {
- setSharedCacheMode(JPAProperties.getEnumValue(SharedCacheMode.class, JPAProperties.CACHE_MODE, val));
+ setSharedCacheMode(JPAProperties.getEnumValue(SharedCacheMode.class, val));
} else {
_props.put(key, val);
}
Modified: openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties?rev=832874&r1=832873&r2=832874&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties (original)
+++ openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties Wed Nov 4 21:18:38 2009
@@ -173,8 +173,8 @@
non-unique-result: Query "{0}" selected {1} results, but expected unique result.
unwrap-em-invalid: EntityManager can not be unwrapped to an instance of "{0}".
unwrap-query-invalid: Query can not be unwrapped to an instance of "{0}".
-invalid_entity_argument: Object being locked must be an valid and not detached \
- entity.
+invalid_entity_argument: {0} can not be invoked on "{1}". This entity is either \
+ detached or not persistent or null.
dup-pu: The persistence unit "{0}" was found multiple times in the following \
resources "{1}", but persistence unit names should be unique. The first \
persistence unit matching the provided name in "{2}" is being used.
@@ -223,3 +223,4 @@
create-emf-error: Failed to create a provider for "{0}".
invalid-version-attribute: Persistence version attribute value "{0}" is not valid. Using version "{1}" by default.
not-jpql-or-criteria-query: Query is neither a JPQL SELECT nor a Criteria API query.
+cache-retrieve-override: The setting of CacheRetrieveMode.USE is ignored and set to BYPASS for refresh operation.
\ No newline at end of file