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 2012/06/27 00:16:04 UTC
svn commit: r1354266 - in /openjpa/trunk/openjpa-persistence-jdbc/src/test:
java/org/apache/openjpa/audit/ resources/META-INF/
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>
Re: svn commit: r1354266 - in
/openjpa/trunk/openjpa-persistence-jdbc/src/test:
java/org/apache/openjpa/audit/ resources/META-INF/
Posted by Pinaki Poddar <pp...@apache.org>.
Sorry, Guys. It was my bad. I had manually merged the persistence.xml and
made the mistake.
-----
Pinaki Poddar
Chair, Apache OpenJPA Project
--
View this message in context: http://openjpa.208410.n2.nabble.com/Re-svn-commit-r1354266-in-openjpa-trunk-openjpa-persistence-jdbc-src-test-java-org-apache-openjpa-au-tp7580431p7580441.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.
Re: svn commit: r1354266 - in /openjpa/trunk/openjpa-persistence-jdbc/src/test:
java/org/apache/openjpa/audit/ resources/META-INF/
Posted by Rick Curtis <cu...@gmail.com>.
Travis -
Good catch. The test should work as of revision 1356259.
Thanks,
Rick
On Thu, Jun 28, 2012 at 10:07 AM, Travis Bischel <bi...@gmail.com> 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, <pp...@apache.org> 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*
Re: svn commit: r1354266 - in /openjpa/trunk/openjpa-persistence-jdbc/src/test:
java/org/apache/openjpa/audit/ resources/META-INF/
Posted by Travis Bischel <bi...@gmail.com>.
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, <pp...@apache.org> 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>
>
>
>