From: Kai Moritz Date: Tue, 29 Apr 2014 16:01:10 +0000 (+0200) Subject: Added integration-test provided by Erik-Berndt Scheper --- diff --git a/src/it/hibernate4-maven-plugin-envers-sample/README.md b/src/it/hibernate4-maven-plugin-envers-sample/README.md new file mode 100644 index 00000000..cc048a43 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/README.md @@ -0,0 +1,38 @@ +Hibernate-4 maven plugin Envers sample project +==================== + +Introduction +--------------------- + +This is a sample project that can be used to demonstrate the [Hibernate4-maven-plugin](http://juplo.de/hibernate4-maven-plugin/) +in combination with the Hibernate Envers module. + +The Maven pom.xml file contains the definitions to run the Hibernate4-maven-plugin. + +The project code contains a JPA entity, an Envers audit revision entity and +a single integration test using an in-memory HSQLDB database. + +The integration test performs the following actions: + +* Initialize a JTA environment using [Atomikos transaction essentials](http://www.atomikos.com/Main/TransactionsEssentials/) +* Startup an XA datasource +* Run the SQL-script to drop any existing tables in the HSQLDB database (script/drop-tables-hsqldb.sql) +* Run the SQL-script to create the tables in the HSQLDB database (create-tables-hsqldb.sql) + + Note: this script is created by the Hibernate4-maven-plugin + +* Load the Hibernate (and Envers) configuration, including the validation of the database schema +* Persist and update entities that are audited by Hibernate Envers +* Verify the revisions and the audit tables + +Usage +--------------------- + +__Rebuild the SQL-script using the Hibernate4-maven-plugin to create the database__ + + mvn -PcreateHsqlDbScript clean compile hibernate4:export + +__Build and run the integration tests__ + + mvn clean package + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/pom.xml b/src/it/hibernate4-maven-plugin-envers-sample/pom.xml new file mode 100644 index 00000000..3ca641da --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/pom.xml @@ -0,0 +1,291 @@ + + + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + org.bitbucket.fbascheper + hibernate4-maven-plugin-envers-sample + Hibernate 4 Maven Plugin Envers sample + Sample project to test the maven plugin + 1.0-SNAPSHOT + jar + http://juplo.de/hibernate4-maven-plugin + + + @project.version@ + + true + 4.2.5.Final + 1.0.1.Final + + 4.3.1.Final + 1.7.5 + 4.11 + 2.2.9 + 1.0.1B-rc4 + 3.2.1.RELEASE + 1.0.0.GA + + + + + + createHsqlDbScript + + + false + + + + + true + classpath:/sql/create-tables-hsqldb.sql + + + org.hsqldb.jdbc.JDBCDriver + jdbc:hsqldb:mem:demodb + sa + sapwd + org.hibernate.dialect.HSQLDialect + + + org.hsqldb.jdbcDriver + org.hibernate.dialect.HSQLDialect + + + sa + + true + + + + + + de.juplo + hibernate4-maven-plugin + ${de.juplo-hibernate-plugin-version} + + + + export + + + + + ${project.build.sourceDirectory}/../scripts/sql/create-tables-hsqldb.sql + + SCRIPT + CREATE + + + + org.hibernate + hibernate-core + ${org.hibernate.version} + + + org.scannotation + scannotation + 1.0.3 + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + org.hsqldb + hsqldb + ${org.hsqldb.version} + + + + + + + + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + org.slf4j + slf4j-log4j12 + ${org.slf4j.version} + test + + + log4j + log4j + 1.2.17 + test + + + org.hibernate + hibernate-entitymanager + ${org.hibernate.version} + compile + + + org.jboss.spec.javax.transaction + jboss-transaction-api_1.1_spec + + + + + org.hibernate + hibernate-core + ${org.hibernate.version} + compile + + + org.jboss.spec.javax.transaction + jboss-transaction-api_1.1_spec + + + + + org.hibernate + hibernate-envers + ${org.hibernate.version} + compile + + + javax.validation + validation-api + ${javax.validation_validation-api.version} + compile + + + hibernate-validator + org.hibernate + ${org.hibernate_hibernate-validator.version} + compile + + + org.jboss.logging + jboss-logging + + + + + junit + junit + ${org.junit.version} + test + + + com.atomikos + transactions-hibernate3 + 3.8.0 + test + + + org.hsqldb + hsqldb + ${org.hsqldb.version} + test + + + org.jboss.spec.javax.transaction + jboss-transaction-api_1.1_spec + 1.0.0.Final + provided + + + org.springframework + spring-context + ${global_springframework.version} + + + org.springframework + spring-tx + ${global_springframework.version} + + + org.springframework + spring-jdbc + ${global_springframework.version} + + + org.springframework + spring-orm + ${global_springframework.version} + + + javax.inject + javax.inject + 1 + + + org.springframework + spring-test + ${global_springframework.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.6 + 1.6 + utf8 + true + + + + + + + src/main/java + + ** + + + **/*.java + + + + src/main/resources + + + + + + src/test/java + + ** + + + **/*.java + + + + src/main/scripts + + + src/test/resources + + + + + + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/AuditRevision.java b/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/AuditRevision.java new file mode 100644 index 00000000..48c9707d --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/AuditRevision.java @@ -0,0 +1,151 @@ +/** + * Copyright 2013 F.B.A. Scheper. + * + * Licensed 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.bitbucket.fbascheper.tutorial.envers; + +import org.hibernate.envers.RevisionEntity; +import org.hibernate.envers.RevisionNumber; +import org.hibernate.envers.RevisionTimestamp; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * The implementation of the {@link org.hibernate.envers.RevisionEntity}. + * + * @author Erik-Berndt Scheper + * @see org.hibernate.envers.RevisionEntity + * @since 11-09-2013 + */ +@Entity +@Table(name = "TTL_AUDIT_REVISION") +@RevisionEntity(AuditRevisionListener.class) +public class AuditRevision implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(name = "ID") + @SequenceGenerator(name = "TTL_AUDIT_REVISION_SEQ", sequenceName = "TTL_AUDIT_REVISION_SEQ", allocationSize = 10) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TTL_AUDIT_REVISION_SEQ") + @RevisionNumber + private Long id; + + @RevisionTimestamp + @Column(name = "ENVERS_TSTAMP", nullable = false) + private long timestamp; + + @NotNull + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "EVENT_DATE") + private Date revisionTimeStamp; + + @NotNull + @Column(name = "USER_NAME", length = 80, nullable = false) + private String userName; + + // ********************** Getters and setters ********************** // + + /** + * @return the id of this revision + */ + public Long getId() { + return id; + } + + /** + * @param id the id of this revision + */ + void setId(Long id) { + this.id = id; + } + + /** + * @return the timestamp of this revision + */ + long getTimestamp() { + return timestamp; + } + + void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + /** + * @return the timestamp of this revision + */ + public Date getRevisionTimeStamp() { + return revisionTimeStamp; + } + + void setRevisionTimeStamp(Date revisionTimeStamp) { + this.revisionTimeStamp = revisionTimeStamp; + } + + /** + * @return name of the user who initiated the change resulting in this revision. + */ + public String getUserName() { + return userName; + } + + /** + * @param userName name of the user who initiated the change resulting in this revision. + */ + void setUserName(String userName) { + this.userName = userName; + } + + // ********************** Common Methods ********************** // + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AuditRevision that = (AuditRevision) o; + + if (id != null ? !id.equals(that.id) : that.id != null) return false; + + return true; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + + output.append("AuditRevision {"); + output.append(" id = \"").append(getId()).append("\", "); + output.append(" revisionTimeStamp = \"").append(revisionTimeStamp).append("\", "); + output.append(" userName = \"").append(userName).append("\"}"); + + return output.toString(); + } + +} diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/AuditRevisionListener.java b/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/AuditRevisionListener.java new file mode 100644 index 00000000..936abb9f --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/AuditRevisionListener.java @@ -0,0 +1,46 @@ +/** + * Copyright 2013 F.B.A. Scheper. + * + * Licensed 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.bitbucket.fbascheper.tutorial.envers; + +import org.hibernate.envers.RevisionListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +/** + * The {@link org.hibernate.envers.RevisionListener}-implementation used to initialize an {@link AuditRevision}. + * + * @author Erik-Berndt Scheper + * @see AuditRevision + * @since 11-09-2013 + */ +public class AuditRevisionListener implements RevisionListener { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Override + public void newRevision(Object revisionEntity) { + + AuditRevision auditRevision = (AuditRevision) revisionEntity; + auditRevision.setRevisionTimeStamp(new Date()); + + auditRevision.setUserName("EXAMPLE_USER"); + + + } + +} diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/Event.java b/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/Event.java new file mode 100644 index 00000000..43a6e798 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/java/org/bitbucket/fbascheper/tutorial/envers/Event.java @@ -0,0 +1,140 @@ +/** + * Copyright 2013 F.B.A. Scheper. + * + * Licensed 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.bitbucket.fbascheper.tutorial.envers; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.RevisionNumber; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * A random event registered, based on the original hibernate tutorial by Steve Ebersole. + * + * @author Erik-Berndt Scheper + * @see AuditRevision + * @since 11-09-2013 + */ +@Entity +@Table(name = "TTL_EVENT") +@Audited +public class Event { + + @Id + @Column(name = "ID") + @SequenceGenerator(name = "TTL_EVENT_SEQ", sequenceName = "TTL_EVENT_SEQ", allocationSize = 10) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TTL_EVENT_SEQ") + @RevisionNumber + private Long id; + + @NotNull + @Column(name = "TITLE", length = 80, nullable = false) + private String title; + + @NotNull + @Column(name = "EVENT_DATE", nullable = false) + @Temporal(TemporalType.TIMESTAMP) + private Date date; + + /** + * Default constructor, mandated by JPA. + */ + Event() { + // do nothing + } + + /** + * Initializing constructor. + * + * @param title title of the event + * @param date date of the event + */ + public Event(String title, Date date) { + this.title = title; + this.date = date; + } + + // ********************** Getters and setters ********************** // + + public Long getId() { + return id; + } + + void setId(Long id) { + this.id = id; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + // ********************** Common Methods ********************** // + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Event event = (Event) o; + + if (date != null ? !date.equals(event.date) : event.date != null) return false; + if (title != null ? !title.equals(event.title) : event.title != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = title != null ? title.hashCode() : 0; + result = 31 * result + (date != null ? date.hashCode() : 0); + return result; + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + + output.append("Event {"); + output.append(" id = \"").append(getId()).append("\", "); + output.append(" title = \"").append(title).append("\", "); + output.append(" date = \"").append(date).append("\"}"); + + return output.toString(); + } + + +} \ No newline at end of file diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/META-INF/persistence-jpa.xml b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/META-INF/persistence-jpa.xml new file mode 100644 index 00000000..a668c3d9 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/META-INF/persistence-jpa.xml @@ -0,0 +1,34 @@ + + + + + + Example persistence unit. + + + org.bitbucket.fbascheper.tutorial.envers.Event + + + + + + + + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-application-context.xml b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-application-context.xml new file mode 100644 index 00000000..0af6233b --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-application-context.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.properties b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.properties new file mode 100644 index 00000000..1909a7b6 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.properties @@ -0,0 +1,10 @@ +# +# Configuration of the services +# +hibernate.hbm2ddl.auto = validate +hibernate.show_sql = false +hibernate.format_sql = false + +jpa.persistence.context.name = examplePU + + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.xml b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.xml new file mode 100644 index 00000000..78f81117 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/resources/spring-persistence-context.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + ${hibernate.dialect:org.hibernate.dialect.Oracle10gDialect} + ${hibernate.hbm2ddl.auto:validate} + ${hibernate.show_sql:false} + ${hibernate.format_sql:false} + + + ${hibernate.transaction.manager_lookup_class:org.hibernate.transaction.WebSphereExtendedJTATransactionLookup} + + + + + + + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/scripts/sql/create-tables-hsqldb.sql b/src/it/hibernate4-maven-plugin-envers-sample/src/main/scripts/sql/create-tables-hsqldb.sql new file mode 100644 index 00000000..fe6130e0 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/scripts/sql/create-tables-hsqldb.sql @@ -0,0 +1,33 @@ + + create table TTL_AUDIT_REVISION ( + ID bigint not null, + EVENT_DATE timestamp, + ENVERS_TSTAMP bigint not null, + USER_NAME varchar(80) not null, + primary key (ID) + ); + + create table TTL_EVENT ( + ID bigint not null, + EVENT_DATE timestamp not null, + TITLE varchar(80) not null, + primary key (ID) + ); + + create table TTL_EVENT_AUD ( + ID bigint not null, + REV bigint not null, + REVTYPE tinyint, + EVENT_DATE timestamp, + TITLE varchar(80), + primary key (ID, REV) + ); + + alter table TTL_EVENT_AUD + add constraint FK_cjsh8995uabmdm9b30uvmyj6p + foreign key (REV) + references TTL_AUDIT_REVISION; + + create sequence TTL_AUDIT_REVISION_SEQ; + + create sequence TTL_EVENT_SEQ; diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/main/scripts/sql/drop-tables-hsqldb.sql b/src/it/hibernate4-maven-plugin-envers-sample/src/main/scripts/sql/drop-tables-hsqldb.sql new file mode 100644 index 00000000..1578d898 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/main/scripts/sql/drop-tables-hsqldb.sql @@ -0,0 +1,10 @@ + drop table TTL_AUDIT_REVISION if exists cascade; + + drop table TTL_EVENT if exists cascade; + + drop table TTL_EVENT_AUD if exists cascade; + + drop sequence TTL_AUDIT_REVISION_SEQ if exists ; + + drop sequence TTL_EVENT_SEQ if exists ; + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/AbstractIntegrationTest.java b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/AbstractIntegrationTest.java new file mode 100644 index 00000000..420a9642 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/AbstractIntegrationTest.java @@ -0,0 +1,87 @@ +/** + * Copyright 2013 F.B.A. Scheper. + * + * Licensed 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.bitbucket.fbascheper.tutorial.envers; + +import org.bitbucket.fbascheper.tutorial.envers.util.InitScriptRunner; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DelegatingSmartContextLoader; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.sql.DataSource; +import java.io.IOException; + +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; + +/** + * Base class for the integration tests using Spring, Hibernate and JTA. + * + * @author Erik-Berndt Scheper + * @since 11-09-2013 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = DelegatingSmartContextLoader.class, + locations = {"classpath:/hhv-test-datamodel-domain-context.xml", "classpath:/spring-persistence-context.xml"}) +public abstract class AbstractIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Inject + private PlatformTransactionManager transactionManager; + + @Value(value = "${hibernate.dialect}") + private String hibernateDialect; + + @Resource(name = "dataSource") + private DataSource dataSource; + + @Inject + private InitScriptRunner initScriptRunner; + + @Before + public void initIntegrationTest() throws IOException { + assertThat(transactionManager, notNullValue()); + assertThat(entityManager, notNullValue()); + assertThat(hibernateDialect, notNullValue()); + assertThat(dataSource, notNullValue()); + + // re-run the database creation script for each test + initScriptRunner.runScript(); + + } + + protected EntityManager getEntityManager() { + return entityManager; + } + + protected TransactionTemplate getTransactionTemplate() { + + TransactionTemplate template = new TransactionTemplate(transactionManager); + return template; + } + +} diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/EnversIllustrationTest.java b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/EnversIllustrationTest.java new file mode 100644 index 00000000..91b3cf11 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/EnversIllustrationTest.java @@ -0,0 +1,138 @@ +/** + * Copyright 2013 F.B.A. Scheper. + * + * Licensed 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.bitbucket.fbascheper.tutorial.envers; + +import org.hibernate.envers.AuditReader; +import org.hibernate.envers.AuditReaderFactory; +import org.junit.Test; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; + +import java.util.Date; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; + +/** + * Illustrates the set up and use of Envers using JTA; based on the original hibernate tutorial by Steve Ebersole. + * + * @author Erik-Berndt Scheper + * @since 11-09-2013 + */ +public class EnversIllustrationTest extends AbstractIntegrationTest { + + @Test + public void testOne() { + + // create a couple of events + final Event event1 = getTransactionTemplate().execute(new TransactionCallback() { + @Override + public Event doInTransaction(TransactionStatus status) { + // revision 1 + Event event = new Event("Our very first event!", new Date()); + getEntityManager().persist(event); + return event; + + } + }); + final Event event2 = getTransactionTemplate().execute(new TransactionCallback() { + @Override + public Event doInTransaction(TransactionStatus status) { + // revision 2 + Event event = new Event("A follow up event", new Date()); + getEntityManager().persist(event); + return event; + + } + }); + + // now lets pull events from the database and list them + + List result = getTransactionTemplate().execute(new TransactionCallback>() { + @Override + public List doInTransaction(TransactionStatus status) { + List result = getEntityManager().createQuery("select evt from Event evt", Event.class).getResultList(); + for (Event event : result) { + System.out.println("Event (" + event.getDate() + ") : " + event.getTitle()); + } + + return result; + } + }); + + // verify that id's were generated + final Long event1Id = event1.getId(); + final Long event2Id = event2.getId(); + + assertThat(event1Id, notNullValue()); + assertThat(event2Id, notNullValue()); + + // so far the code is the same as we have seen in previous tutorials. Now lets leverage Envers... + // first lets create some revisions + getTransactionTemplate().execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus status) { + // revision 3 + Event myEvent = getEntityManager().find(Event.class, event2Id); + myEvent.setDate(new Date()); + myEvent.setTitle(myEvent.getTitle() + " (rescheduled)"); + + } + }); + + // and then use an AuditReader to look back through history + getTransactionTemplate().execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus status) { + + Event myEvent = getEntityManager().find(Event.class, event2Id); + assertThat("A follow up event (rescheduled)", is(myEvent.getTitle())); + + AuditReader reader = AuditReaderFactory.get(getEntityManager()); + + List event2Revisions = reader.getRevisions(Event.class, event2Id); + assertThat(event2Revisions.size(), is(2)); + + long event2Revision1 = event2Revisions.get(0).longValue(); + long event2Revision2 = event2Revisions.get(1).longValue(); + + assertThat(event2Revision1, is(2L)); + assertThat(event2Revision2, is(3L)); + + Event firstRevision = reader.find(Event.class, event2Id, event2Revision1); + + assertThat(firstRevision, notNullValue()); + assertThat(firstRevision.getTitle(), notNullValue()); + assertThat(firstRevision.getTitle(), not(is(myEvent.getTitle()))); + assertThat(firstRevision.getDate(), not(is(myEvent.getDate()))); + + Event secondRevision = reader.find(Event.class, event2Id, event2Revision2); + assertThat(secondRevision, notNullValue()); + assertThat(secondRevision.getTitle(), notNullValue()); + assertThat(secondRevision.getTitle(), is(myEvent.getTitle())); + assertThat(secondRevision.getDate(), is(myEvent.getDate())); + + } + + }); + + } + +} diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/util/InitScriptRunner.java b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/util/InitScriptRunner.java new file mode 100644 index 00000000..b7c9e041 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/util/InitScriptRunner.java @@ -0,0 +1,87 @@ +/** + * Copyright 2013 F.B.A. Scheper. + * + * Licensed 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.bitbucket.fbascheper.tutorial.envers.util; + +import org.springframework.core.io.Resource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.jdbc.JdbcTestUtils; + +import javax.sql.DataSource; + +/** + * A initialization script runner. + * + * @author Erik-Berndt Scheper + * @since 11-09-2013 + */ +public interface InitScriptRunner { + + /** + * Run the database creation script. + */ + public void runScript(); + + /** + * Return the datasource used to run the script + * + * @return the datasource + */ + public DataSource getDataSource(); + + + /** + * Default implementation for the runner of the creation script. + */ + public static class InitScriptRunnerImpl implements InitScriptRunner { + + private final DataSource dataSource; + private final Resource dbDropScriptLocation; + private final Resource dbCreateScriptLocation; + + + /** + * Initializing constructor. + * + * @param dataSource the raw {@link javax.sql.DataSource} to return + * @param dbDropScriptLocation location of the create DB drop script to run + * @param dbCreateScriptLocation location of the create DB create script to run + */ + public InitScriptRunnerImpl(DataSource dataSource, + Resource dbDropScriptLocation, + Resource dbCreateScriptLocation) { + this.dataSource = dataSource; + this.dbDropScriptLocation = dbDropScriptLocation; + this.dbCreateScriptLocation = dbCreateScriptLocation; + } + + @Override + public void runScript() { + + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + JdbcTestUtils.executeSqlScript(jdbcTemplate, dbDropScriptLocation, false); + JdbcTestUtils.executeSqlScript(jdbcTemplate, dbCreateScriptLocation, false); + + } + + @Override + public DataSource getDataSource() { + + return this.dataSource; + + } + } + +} diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/util/InitScriptRunningDataSourceFactoryBean.java b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/util/InitScriptRunningDataSourceFactoryBean.java new file mode 100644 index 00000000..3757dfa4 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/java/org/bitbucket/fbascheper/tutorial/envers/util/InitScriptRunningDataSourceFactoryBean.java @@ -0,0 +1,40 @@ +/** + * Copyright 2013 F.B.A. Scheper. + * + * Licensed 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.bitbucket.fbascheper.tutorial.envers.util; + +import javax.sql.DataSource; + +/** + * A Bean of a {@link javax.sql.DataSource} type that initially runs a database creation script. + * + * @author Erik-Berndt Scheper + * @since 11-09-2013 + */ +public class InitScriptRunningDataSourceFactoryBean { + + /** + * Factory method returning a DataSource after running the init script. + * + * @param initScriptRunner the script runner implementation + */ + public static DataSource dataSourceFactory(InitScriptRunner initScriptRunner) { + + initScriptRunner.runScript(); + + return initScriptRunner.getDataSource(); + } + +} diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/hhv-test-datamodel-domain-context.properties b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/hhv-test-datamodel-domain-context.properties new file mode 100644 index 00000000..4cd69447 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/hhv-test-datamodel-domain-context.properties @@ -0,0 +1,20 @@ +# +# Configuration of the services +# + +atomikos.dataSource.uniqueResourceName = hhv_atomikos_ds + +# These properties are set using filtering via the MAVEN POM +dataSource.driverClassName=org.hsqldb.jdbc.JDBCDriver +dataSource.url=jdbc:hsqldb:target/db/testdb;shutdown=true +dataSource.user=sa +dataSource.password +hibernate.dialect =org.hibernate.dialect.HSQLDialect + + +hibernate.hbm2ddl.auto = validate +hibernate.format_sql = true +hibernate.show_sql = false +hibernate.transaction.manager_lookup_class = com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup + +spring.jta.transaction.manager = org.springframework.transaction.jta.JtaTransactionManager diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/hhv-test-datamodel-domain-context.xml b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/hhv-test-datamodel-domain-context.xml new file mode 100644 index 00000000..97f72af1 --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/hhv-test-datamodel-domain-context.xml @@ -0,0 +1,108 @@ + + + + + + + classpath:/spring-persistence-context.properties + classpath:/hhv-test-datamodel-domain-context.properties + + + + + + + + + + --> + + + + + + + + + + + + + + + + com.atomikos.icatch.standalone.UserTransactionServiceFactory + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/jta.properties b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/jta.properties new file mode 100644 index 00000000..8727c65a --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/jta.properties @@ -0,0 +1,29 @@ +#* +#* +#* Copyright 2006-2007 the original author or authors. +#* +#* Licensed 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. +#* +#* + + +com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory +com.atomikos.icatch.console_file_name = tm-dev.out +com.atomikos.icatch.log_base_name = tmlog-dev +com.atomikos.icatch.tm_unique_name = tmdev +com.atomikos.icatch.serial_jta_transactions=false +com.atomikos.icatch.automatic_resource_registration=true +com.atomikos.icatch.max_actives=15000 +com.atomikos.icatch.max_timeout=3600000 +com.atomikos.icatch.output_dir=target/atomikosxatm/ +com.atomikos.icatch.log_base_dir=target/atomikosxatm/ diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/log4j.dtd b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/log4j.dtd new file mode 100644 index 00000000..5355525d --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/log4j.dtd @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/log4j.xml b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/log4j.xml new file mode 100644 index 00000000..7b53f87f --- /dev/null +++ b/src/it/hibernate4-maven-plugin-envers-sample/src/test/resources/log4j.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file