Travis - Good catch. The test should work as of revision 1356259.
Thanks, Rick On Thu, Jun 28, 2012 at 10:07 AM, Travis Bischel <[email protected]> wrote: > Pinake, > > Your commit causes a test failure in TestResultClsXml: > > javax.persistence.PersistenceException: No persistence providers > available for "query-result" after trying the following discovered > implementations: > org.apache.openjpa.persistence.PersistenceProviderImpl > at > javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:182) > at > org.apache.openjpa.persistence.test.AbstractPersistenceTestCase.createNamedEMF(AbstractPersistenceTestCase.java:118) > at > org.apache.openjpa.persistence.test.AbstractCachedEMFTestCase.createNamedEMF(AbstractCachedEMFTestCase.java:55) > at > org.apache.openjpa.persistence.test.AbstractPersistenceTestCase.createEMF(AbstractPersistenceTestCase.java:94) > at > org.apache.openjpa.persistence.test.SingleEMFTestCase.setUp(SingleEMFTestCase.java:70) > at > org.apache.openjpa.persistence.test.SQLListenerTestCase.setUp(SQLListenerTestCase.java:45) > at > org.apache.openjpa.persistence.results.cls.TestResultClsXml.setUp(TestResultClsXml.java:32) > > Your modification to presistence.xml removed a persistence-unit mapping. > > -Travis Bischel > > On Tue, Jun 26, 2012 at 5:16 PM, <[email protected]> wrote: > > > Author: ppoddar > > Date: Tue Jun 26 22:16:03 2012 > > New Revision: 1354266 > > > > URL: http://svn.apache.org/viewvc?rev=1354266&view=rev > > Log: > > OPENJPA-2030: Add a test for audit > > > > Added: > > > > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/ > > > > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/AuditedEntry.java > > (with props) > > > > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/InplaceAuditor.java > > (with props) > > > > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/TestAudit.java > > (with props) > > > > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/X.java > > (with props) > > Modified: > > > > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml > > > > Added: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/AuditedEntry.java > > URL: > > > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/AuditedEntry.java?rev=1354266&view=auto > > > > > ============================================================================== > > --- > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/AuditedEntry.java > > (added) > > +++ > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/AuditedEntry.java > > Tue Jun 26 22:16:03 2012 > > @@ -0,0 +1,119 @@ > > +/* > > + * 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.audit; > > + > > +import java.sql.Timestamp; > > +import java.util.Arrays; > > +import java.util.Date; > > +import java.util.List; > > + > > +import javax.persistence.CascadeType; > > +import javax.persistence.ElementCollection; > > +import javax.persistence.Entity; > > +import javax.persistence.EnumType; > > +import javax.persistence.Enumerated; > > +import javax.persistence.GeneratedValue; > > +import javax.persistence.Id; > > +import javax.persistence.ManyToOne; > > +import javax.persistence.Temporal; > > +import javax.persistence.TemporalType; > > + > > +import org.apache.openjpa.enhance.PersistenceCapable; > > +import org.apache.openjpa.kernel.Audited; > > +import org.apache.openjpa.persistence.Type; > > + > > +/** > > + * An example of an immutable persistent entity that holds a reference > to > > the entity being audited. > > + * <br> > > + * This entity holds the reference to the entity being audited in a > > <em>generic</em> > > + * sense i.e. it does not know the exact type of the audited entity, but > > merely that > > + * it is a {@link PersistenceCapable} instance. > > + * <br> > > + * OpenJPA supports such reference by annotating with the {@link > #audited > > reference field} as > > + * <tt>@Type(PersistenceCapable.class)</tt>. > > + * <br> > > + * The audit operation is also represented as a {@link #operation > > enumerated field}. > > + * > > + * @author Pinaki Poddar > > + * > > + */ > > +@Entity > > +public class AuditedEntry { > > + @Id > > + @GeneratedValue > > + private long id; > > + > > + @ManyToOne(cascade=CascadeType.MERGE) > > + @Type(PersistenceCapable.class) > > + private Object audited; > > + > > + @Enumerated(EnumType.STRING) > > + private AuditableOperation operation; > > + > > + @Temporal(TemporalType.TIMESTAMP) > > + private Timestamp ts; > > + > > + @ElementCollection > > + private List<String> updatedFields; > > + > > + /** > > + * Constructs using an {@link Audited audited} instance. > > + * <br> > > + * An audited instances are supplied to the {@link > > Auditor#audit(Broker, Collection, Collection, Collection) > > + * auditor} by OpenJPA runtime within the transaction just before > > it is going to commit. > > + * <br> > > + * An audited instance carries the managed instance being audited > > in two <em>separate</em> references. > > + * The {link {@link Audited#getManagedObject()} first reference} > > is to the actual persistence instance > > + * being audited. The {link {@link Audited#getOriginalObject() > > second reference} is a <em>transient</em> > > + * copy of the actual persistence instance but in a state as it > > were when it entered the managed context > > + * i.e. when it was persisted or loaded from the database. > > + * <br> > > + * The {@link Audited} instance also knows the fields that were > > updated. > > + * @param a an audited instance. > > + */ > > + public AuditedEntry(Audited a) { > > + audited = a.getManagedObject(); > > + ts = new Timestamp(new Date().getTime()); > > + operation = a.getType(); > > + if (operation == AuditableOperation.UPDATE) { > > + updatedFields = > > Arrays.asList(a.getUpdatedFields()); > > + } > > + > > + } > > + > > + public Object getAudited() { > > + return audited; > > + } > > + > > + public AuditableOperation getOperation() { > > + return operation; > > + } > > + > > + public Timestamp getTimestamp() { > > + return ts; > > + } > > + > > + public long getId() { > > + return id; > > + } > > + > > + public List<String> getUpdatedFields() { > > + return updatedFields; > > + } > > +} > > > > Propchange: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/AuditedEntry.java > > > > > ------------------------------------------------------------------------------ > > svn:eol-style = native > > > > Added: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/InplaceAuditor.java > > URL: > > > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/InplaceAuditor.java?rev=1354266&view=auto > > > > > ============================================================================== > > --- > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/InplaceAuditor.java > > (added) > > +++ > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/InplaceAuditor.java > > Tue Jun 26 22:16:03 2012 > > @@ -0,0 +1,80 @@ > > +/* > > + * 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.audit; > > + > > +import java.util.Collection; > > + > > +import org.apache.openjpa.kernel.Audited; > > +import org.apache.openjpa.kernel.Broker; > > +import org.apache.openjpa.lib.conf.Configuration; > > + > > +/** > > + * Example of an {@link Auditor auditor} that records the audit entries > > in the same database > > + * of the managed entities being audited. > > + * > > + * @author Pinaki Poddar > > + * > > + */ > > +public class InplaceAuditor implements Auditor { > > + > > + @Override > > + public void audit(Broker broker, Collection<Audited> newObjects, > > Collection<Audited> updates, > > + Collection<Audited> deletes) { > > + recordAudits(broker, newObjects); > > + recordAudits(broker, updates); > > + recordAudits(broker, deletes); > > + } > > + > > + @Override > > + public boolean isRollbackOnError() { > > + return false; > > + } > > + > > + /** > > + * Recording an audit is simply persisting an {@link > AuditedEntry} > > with > > + * the available {@link Broker persistence context}. > > + * @param broker > > + * @param audits > > + */ > > + private void recordAudits(Broker broker, Collection<Audited> > > audits) { > > + for (Audited a : audits) { > > + broker.persist(new AuditedEntry(a), null); > > + } > > + } > > + > > + // ------------------------------------------------------------- > > + // Configurable implementation that does nothing. > > + // ------------------------------------------------------------- > > + @Override > > + public void setConfiguration(Configuration conf) { > > + } > > + > > + @Override > > + public void startConfiguration() { > > + } > > + > > + @Override > > + public void endConfiguration() { > > + } > > + > > + @Override > > + public void close() throws Exception { > > + } > > + > > +} > > > > Propchange: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/InplaceAuditor.java > > > > > ------------------------------------------------------------------------------ > > svn:eol-style = native > > > > Added: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/TestAudit.java > > URL: > > > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/TestAudit.java?rev=1354266&view=auto > > > > > ============================================================================== > > --- > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/TestAudit.java > > (added) > > +++ > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/TestAudit.java > > Tue Jun 26 22:16:03 2012 > > @@ -0,0 +1,150 @@ > > +/* > > + * 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.audit; > > + > > + > > +import java.util.List; > > + > > +import javax.persistence.EntityManager; > > +import javax.persistence.Persistence; > > + > > +import junit.framework.TestCase; > > + > > +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory; > > +import org.apache.openjpa.persistence.OpenJPAPersistence; > > + > > +/** > > + * A test for audit facility. > > + * > > + * @author Pinaki Poddar > > + * > > + */ > > +public class TestAudit extends TestCase { > > + private static OpenJPAEntityManagerFactory emf; > > + private static Auditor auditor; > > + private static Object oid; > > + > > + EntityManager em; > > + > > + public void setUp() { > > + if (emf == null) { > > + emf = > > OpenJPAPersistence.cast(Persistence.createEntityManagerFactory("audit")); > > + assertNotNull(emf); > > + auditor = emf.getConfiguration().getAuditorInstance(); > > + em = emf.createEntityManager(); > > + clearAuditedEntries(); > > + oid = createManagedObject(); > > + } else { > > + em = emf.createEntityManager(); > > + } > > + } > > + > > + private Object createManagedObject() { > > + em.getTransaction().begin(); > > + X x = new X(); > > + x.setName("New Object"); > > + x.setPrice(100); > > + em.persist(x); > > + em.getTransaction().commit(); > > + > > + return emf.getPersistenceUnitUtil().getIdentifier(x); > > + } > > + > > + private void clearAuditedEntries() { > > + em.getTransaction().begin(); > > + em.createQuery("delete from AuditedEntry a").executeUpdate(); > > + em.getTransaction().commit(); > > + } > > + > > + public void testAuditorIsConfigured() { > > + assertNotNull(auditor); > > + } > > + > > + public void testIsEntityAuditable() { > > + assertNotNull(X.class.getAnnotation(Auditable.class)); > > + } > > + > > + public void testNewInstancesAreAudited() { > > + X x = em.find(X.class, oid); > > + assertNotNull(x); > > + > > + AuditedEntry entry = > > findLastAuditedEntry(AuditableOperation.CREATE); > > + > > + assertNotNull(entry); > > + assertEquals(x, entry.getAudited()); > > + assertEquals(AuditableOperation.CREATE, entry.getOperation()); > > + assertEquals(X.class, entry.getAudited().getClass()); > > + assertTrue(entry.getUpdatedFields().isEmpty()); > > + } > > + > > + public void testUpdateOutsideTransactionAreAudited() { > > + X x = em.find(X.class, oid); > > + assertNotNull(x); > > + > > + x.setName("Updated Object outside transaction"); > > + > > + em.getTransaction().begin(); > > + x = em.merge(x); > > + em.getTransaction().commit(); > > + > > + AuditedEntry entry = > > findLastAuditedEntry(AuditableOperation.UPDATE); > > + > > + assertNotNull(entry); > > + assertEquals(x, entry.getAudited()); > > + assertEquals(AuditableOperation.UPDATE, entry.getOperation()); > > + assertTrue(entry.getUpdatedFields().contains("name")); > > + assertFalse(entry.getUpdatedFields().contains("price")); > > + } > > + > > + public void testUpdateInsideTransactionAreAudited() { > > + X x = em.find(X.class, oid); > > + assertNotNull(x); > > + > > + > > + em.getTransaction().begin(); > > + x.setPrice(x.getPrice()+100); > > + x = em.merge(x); > > + em.getTransaction().commit(); > > + > > + AuditedEntry entry = > > findLastAuditedEntry(AuditableOperation.UPDATE); > > + > > + > > + assertNotNull(entry); > > + assertEquals(x, entry.getAudited()); > > + assertEquals(AuditableOperation.UPDATE, entry.getOperation()); > > + assertFalse(entry.getUpdatedFields().contains("name")); > > + assertTrue(entry.getUpdatedFields().contains("price")); > > + } > > + > > + /** > > + * Finds the latest audit entry of the given operation type. > > + * The <em>latest</em> is determined by a sort on identifier which > is > > assumed to be monotonically ascending. > > + * > > + */ > > + AuditedEntry findLastAuditedEntry(AuditableOperation op) { > > + List<AuditedEntry> entry = > > + em.createQuery("select a from AuditedEntry a where > > a.operation=:op order by a.id desc", AuditedEntry.class) > > + .setMaxResults(1) > > + .setParameter("op", op) > > + .getResultList(); > > + return entry.get(0); > > + } > > + > > + > > +} > > > > Propchange: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/TestAudit.java > > > > > ------------------------------------------------------------------------------ > > svn:eol-style = native > > > > Added: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/X.java > > URL: > > > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/X.java?rev=1354266&view=auto > > > > > ============================================================================== > > --- > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/X.java > > (added) > > +++ > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/X.java > > Tue Jun 26 22:16:03 2012 > > @@ -0,0 +1,64 @@ > > +package org.apache.openjpa.audit; > > + > > +import javax.persistence.Entity; > > +import javax.persistence.GeneratedValue; > > +import javax.persistence.Id; > > + > > + > > +/** > > + * A simple persistent entity used to test audit facility. > > + * An entity is annotated with {@link Auditable} annotation to qualify > > for audit. > > + * > > + * @author Pinaki Poddar > > + * > > + */ > > +@Entity > > +@Auditable > > +public class X { > > + @Id > > + @GeneratedValue > > + private long id; > > + > > + private String name; > > + private int price; > > + > > + public String getName() { > > + return name; > > + } > > + public void setName(String name) { > > + this.name = name; > > + } > > + public int getPrice() { > > + return price; > > + } > > + public void setPrice(int price) { > > + this.price = price; > > + } > > + public long getId() { > > + return id; > > + } > > + @Override > > + public int hashCode() { > > + final int prime = 31; > > + int result = 1; > > + result = prime * result + (int) (id ^ (id >>> 32)); > > + return result; > > + } > > + @Override > > + public boolean equals(Object obj) { > > + if (this == obj) > > + return true; > > + if (obj == null) > > + return false; > > + if (getClass() != obj.getClass()) > > + return false; > > + X other = (X) obj; > > + if (id != other.id) > > + return false; > > + return true; > > + } > > + > > + public String toString() { > > + return "X[" + id + "]"; > > + } > > +} > > > > Propchange: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/audit/X.java > > > > > ------------------------------------------------------------------------------ > > svn:eol-style = native > > > > Modified: > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml > > URL: > > > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml?rev=1354266&r1=1354265&r2=1354266&view=diff > > > > > ============================================================================== > > --- > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml > > (original) > > +++ > > > openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml > > Tue Jun 26 22:16:03 2012 > > @@ -432,14 +432,16 @@ > > </properties> > > </persistence-unit> > > > > - <persistence-unit name="query-result"> > > - <mapping-file>META-INF/query-result-orm.xml</mapping-file> > > - > > <class>org.apache.openjpa.persistence.results.cls.ResultClsXml</class> > > + > > + <persistence-unit name="audit"> > > + <class>org.apache.openjpa.audit.X</class> > > + <class>org.apache.openjpa.audit.AuditedEntry</class> > > + > > <properties> > > - <property name="openjpa.jdbc.SynchronizeMappings" > > - value="buildSchema(ForeignKeys=true)"/> > > + <property name="openjpa.Auditor" > > value="org.apache.openjpa.audit.InplaceAuditor"/> > > + <property name="openjpa.jdbc.SynchronizeMappings" > > value="buildSchema(ForeignKeys=true)"/> > > + <property name="openjpa.DynamicEnhancementAgent" > > value="false"/> > > </properties> > > </persistence-unit> > > - > > > > </persistence> > > > > > > > -- *Rick Curtis*
