| /* |
| * 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.datacache; |
| |
| import java.util.ArrayList; |
| |
| import javax.persistence.EntityManager; |
| |
| import org.apache.openjpa.persistence.ArgumentException; |
| import org.apache.openjpa.persistence.test.SingleEMFTestCase; |
| import org.apache.openjpa.util.UserException; |
| |
| public class TestJPACache extends SingleEMFTestCase { |
| |
| @Override |
| public void setUp() { |
| super.setUp(CachedPerson.class, CachedManager.class, CachedEmployee.class, "openjpa.DataCache", "true", |
| "openjpa.RemoteCommitProvider", "sjvm"); |
| } |
| |
| private void populate() { |
| EntityManager em = emf.createEntityManager(); |
| |
| em.getTransaction().begin(); |
| |
| CachedPerson p = new CachedPerson(); |
| p.setFirstName("John"); |
| p.setLastName("Doe"); |
| p.setId(10); |
| em.persist(p); |
| |
| p = new CachedPerson(); |
| p.setFirstName("Jane"); |
| p.setLastName("Doe"); |
| p.setId(11); |
| em.persist(p); |
| |
| CachedManager m = new CachedManager(); |
| m.setFirstName("Joan"); |
| m.setLastName("Baker"); |
| m.setId(12); |
| m.setEmployees(new ArrayList<>()); |
| em.persist(m); |
| |
| CachedEmployee e = new CachedEmployee(); |
| e.setFirstName("Jim"); |
| e.setFirstName("Smith"); |
| e.setManager(m); |
| e.setId(13); |
| m.getEmployees().add(e); |
| em.persist(e); |
| |
| e = new CachedEmployee(); |
| e.setFirstName("Jeff"); |
| e.setFirstName("Parker"); |
| e.setId(14); |
| e.setManager(m); |
| m.getEmployees().add(e); |
| em.persist(e); |
| |
| em.getTransaction().commit(); |
| |
| em.close(); |
| } |
| |
| /** |
| * Ensure the cached returned by emf.getCache supports the JPA and OpenJPA interfaces. Expected interfaces are |
| * <ul> |
| * <li>javax.persistence.Cache</li> |
| * <li>org.apache.openjpa.persistence.StoreCache</li> |
| * </ul> |
| */ |
| public void testInterfacesReturned() { |
| Object cache = emf.getCache(); |
| assertNotNull("Cache is not enabled", cache); |
| assertTrue(cache instanceof javax.persistence.Cache); |
| assertTrue(cache instanceof org.apache.openjpa.persistence.StoreCache); |
| } |
| |
| /** |
| * Ensure that an Entity is not inserted in the cache until the transaction commits. |
| */ |
| public void testContains() { |
| EntityManager em = emf.createEntityManager(); |
| em.getTransaction().begin(); |
| |
| CachedPerson p = new CachedPerson(); |
| p.setFirstName("John"); |
| p.setLastName("Doe"); |
| p.setId(1); |
| |
| assertNotInCache(CachedPerson.class, 1); |
| em.persist(p); |
| assertNotInCache(CachedPerson.class, 1); |
| |
| em.flush(); |
| assertNotInCache(CachedPerson.class, 1); |
| |
| em.getTransaction().commit(); |
| assertInCache(CachedPerson.class, 1); |
| |
| em.close(); |
| } |
| |
| /** |
| * Evict a single entity instance of type CachedPerson from the cache. Testcase will fail if |
| * <ul> |
| * <li>CachedPerson id:10 and 11 are not in the cache when the test starts.</li> |
| * <li>CachedPerson id:1 <b>is</b> found in the cache when the test starts.</li> |
| * <li>CachedPerson id:10 is not found in the cache after evicting CachedPerson id:11</li> |
| * <li>CachedPerson id:11 is found in the cache after evicting CachedPerson id:11</li> |
| * <li>CachedPerson id:1 is found in the cache after evicting CachedPerson id:11</li> |
| * </ul> |
| */ |
| public void testEvictInstance() { |
| populate(); |
| assertInCache(CachedPerson.class, 10); |
| assertInCache(CachedPerson.class, 11); |
| assertNotInCache(CachedPerson.class, 1); |
| |
| emf.getCache().evict(CachedPerson.class, 11); |
| |
| assertInCache(CachedPerson.class, 10); |
| assertNotInCache(CachedPerson.class, 11); |
| assertNotInCache(CachedPerson.class, 1); |
| } |
| |
| /** |
| * Ensure that evict(Class cls) evicts the specified class and any subclasses. This test will fail if |
| * <ul> |
| * <li>Any of the entites created in populate() are not found in the cache before calling evict()</li> |
| * <li>Any instance of CachedPerson from populate() is found in the cache after |
| * calling evict(CachedPerson.class)</li> |
| * <li>Any instance of CachedManager or CachedEmployee is found in the cache after calling evict()</li> |
| * </ul> |
| */ |
| public void testEvictClass() { |
| populate(); |
| assertInCache(CachedPerson.class, 10); |
| assertInCache(CachedPerson.class, 11); |
| assertInCache(CachedEmployee.class, 13); |
| assertInCache(CachedEmployee.class, 14); |
| assertInCache(CachedManager.class, 12); |
| |
| emf.getCache().evict(CachedPerson.class); |
| |
| assertNotInCache(CachedPerson.class, 10); |
| assertNotInCache(CachedPerson.class, 11); |
| assertNotInCache(CachedEmployee.class, 13); |
| assertNotInCache(CachedEmployee.class, 14); |
| assertNotInCache(CachedManager.class, 12); |
| |
| } |
| |
| /** |
| * Ensure the cache is cleared after calling evictAll. This test will fail if : |
| * <ul> |
| * <li>Any of the entities created in populate() are not found in the cache</li> |
| * <li>Any of the entities which were in the cache before calling evictAll() are still in the cache after calling |
| * evictAll()</li> |
| * </ul> |
| * |
| */ |
| public void testEvictAll() { |
| populate(); |
| |
| assertInCache(CachedPerson.class, 10); |
| assertInCache(CachedPerson.class, 11); |
| assertInCache(CachedEmployee.class, 13); |
| assertInCache(CachedEmployee.class, 14); |
| assertInCache(CachedManager.class, 12); |
| |
| emf.getCache().evictAll(); |
| |
| assertNotInCache(CachedPerson.class, 10); |
| assertNotInCache(CachedPerson.class, 11); |
| assertNotInCache(CachedEmployee.class, 13); |
| assertNotInCache(CachedEmployee.class, 14); |
| assertNotInCache(CachedManager.class, 12); |
| } |
| |
| // test methods for bad input. |
| public void testContainsNullEntity() { |
| try { |
| emf.getCache().contains(null, 1); |
| fail("Expected ArgumentException when calling " + "contains(<null>, <nonNull>)"); |
| } catch (ArgumentException ae) { |
| // normal |
| } |
| } |
| |
| public void testContainsNonEntityClass() { |
| try { |
| emf.getCache().contains(Object.class, 1); |
| fail("Expected ArgumentException when calling " + "contains(<nonEntityClass>, <nonNull>"); |
| } catch (ArgumentException ae) { |
| // expected exception |
| } |
| } |
| |
| public void testContainsNullPrimaryKey() { |
| assertFalse(emf.getCache().contains(CachedPerson.class, null)); |
| } |
| |
| public void testContainsNegativePrimaryKey() { |
| assertFalse(emf.getCache().contains(CachedPerson.class, -1)); |
| } |
| |
| public void testContainsInvalidPrimaryKeyType() { |
| try{ |
| emf.getCache().contains(CachedPerson.class, "abcd"); |
| fail(); |
| }catch(UserException ue){ |
| //expected |
| } |
| } |
| |
| public void testEvictNullInstance() { |
| try { |
| emf.getCache().evict(null, 1); |
| fail("Expected ArgumentException when calling " + "evict(<null>, <id"); |
| } catch (ArgumentException ae) { |
| // expected exception |
| } |
| } |
| |
| public void testEvictNonEntityInstance() { |
| try { |
| emf.getCache().evict(Object.class, 1); |
| fail("Expected ArgumentException when calling " + "evict(<null>, <id"); |
| } catch (ArgumentException ae) { |
| // expected exception |
| } |
| } |
| |
| public void testEvictNullPrimaryKey() { |
| emf.getCache().evict(CachedPerson.class, null); |
| } |
| |
| public void testEvictNegativePrimaryKey() { |
| emf.getCache().evict(CachedPerson.class, -1); |
| } |
| |
| public void testEvictInvalidPrimaryKeyType() { |
| try{ |
| emf.getCache().evict(CachedPerson.class, "abcd"); |
| fail(); |
| }catch(UserException ue){ |
| //expected |
| } |
| } |
| |
| public void testEvictNullClass() { |
| try { |
| emf.getCache().evict(null); |
| fail("Expected ArgumentException when calling " + "evict(<null>"); |
| } catch (ArgumentException ae) { |
| // expected exception |
| } |
| } |
| |
| public void testEvictNonEntity() { |
| try { |
| emf.getCache().evict(Object.class); |
| fail("Expected ArgumentException when calling " + "evict(<nonEntity>"); |
| } catch (ArgumentException ae) { |
| // expected exception |
| } |
| } |
| |
| public void testIllegalStateExceptionAfterClose() { |
| emf.close(); |
| try { |
| emf.getCache(); |
| fail("Expected IllegalStateException"); |
| } |
| catch(IllegalStateException ise) { |
| // expected |
| } |
| } |
| public void testIllegalStateExceptionGetAfterClose() { |
| emf.getCache(); // populate the EntityManagerFactoryImpl's wrapper for the StoreCache. |
| emf.close(); |
| try { |
| emf.getCache(); |
| fail("Expected IllegalStateException"); |
| } |
| catch(IllegalStateException ise) { |
| // expected |
| } |
| } |
| |
| /** |
| * Convenience method. Asserts that the class & primary key do exist in the cache |
| * |
| * @param cls |
| * Entity class. |
| * @param primaryKey |
| * PrimaryKey of the entity. |
| */ |
| private void assertInCache(Class<?> cls, Object primaryKey) { |
| assertTrue(String.format("%s:%s should exist in cache", cls.toString(), primaryKey.toString()), emf.getCache() |
| .contains(cls, primaryKey)); |
| } |
| |
| /** |
| * Convenience method. Assert that the class and primary key do not exist in the cache |
| * |
| * @param cls |
| * Entity class. |
| * @param primaryKey |
| * PrimaryKey of the entity. |
| */ |
| private void assertNotInCache(Class<?> cls, Object primaryKey) { |
| assertFalse(String.format("%s:%s should not exist in cache", cls.toString(), primaryKey.toString()), emf |
| .getCache().contains(cls, primaryKey)); |
| } |
| |
| } |