--- /dev/null
+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
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.sonatype.oss</groupId>
+ <artifactId>oss-parent</artifactId>
+ <version>7</version>
+ </parent>
+
+ <groupId>org.bitbucket.fbascheper</groupId>
+ <artifactId>hibernate4-maven-plugin-envers-sample</artifactId>
+ <name>Hibernate 4 Maven Plugin Envers sample</name>
+ <description>Sample project to test the maven plugin</description>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <url>http://juplo.de/hibernate4-maven-plugin</url>
+
+ <properties>
+ <de.juplo-hibernate-plugin-version>@project.version@</de.juplo-hibernate-plugin-version>
+
+ <maven.deploy.skip>true</maven.deploy.skip>
+ <org.hibernate.version>4.2.5.Final</org.hibernate.version>
+ <org.hibernate.javax.persistence_hibernate-jpa-2.0-api.version>1.0.1.Final
+ </org.hibernate.javax.persistence_hibernate-jpa-2.0-api.version>
+ <org.hibernate_hibernate-validator.version>4.3.1.Final</org.hibernate_hibernate-validator.version>
+ <org.slf4j.version>1.7.5</org.slf4j.version>
+ <org.junit.version>4.11</org.junit.version>
+ <org.hsqldb.version>2.2.9</org.hsqldb.version>
+ <geronimo-spec_geronimo-spec-jta.version>1.0.1B-rc4</geronimo-spec_geronimo-spec-jta.version>
+ <global_springframework.version>3.2.1.RELEASE</global_springframework.version>
+ <javax.validation_validation-api.version>1.0.0.GA</javax.validation_validation-api.version>
+ </properties>
+
+
+ <profiles>
+ <profile>
+ <id>createHsqlDbScript</id>
+ <!-- Activate this profile to create a database script for a clean HSQLDB schema -->
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+
+ <properties>
+ <!-- These properties are filtered into the integration-test-context-properties
+ and loaded by spring to run the integration tests -->
+ <filter.execute.db.creation.script>true</filter.execute.db.creation.script>
+ <filter.db.creation.script.location>classpath:/sql/create-tables-hsqldb.sql
+ </filter.db.creation.script.location>
+
+ <filter.dataSource.driverClassName>org.hsqldb.jdbc.JDBCDriver</filter.dataSource.driverClassName>
+ <filter.dataSource.url>jdbc:hsqldb:mem:demodb</filter.dataSource.url>
+ <filter.dataSource.user>sa</filter.dataSource.user>
+ <filter.dataSource.password>sapwd</filter.dataSource.password>
+ <filter.hibernate.dialect>org.hibernate.dialect.HSQLDialect</filter.hibernate.dialect>
+
+ <!-- These properties are used by hibernate4-maven-plugin to create the script -->
+ <hibernate.connection.driver_class>org.hsqldb.jdbcDriver</hibernate.connection.driver_class>
+ <hibernate.dialect>org.hibernate.dialect.HSQLDialect</hibernate.dialect>
+ <hibernate.connection.url>
+ <![CDATA[jdbc:hsqldb:target/db/testdb;shutdown=true]]></hibernate.connection.url>
+ <hibernate.connection.username>sa</hibernate.connection.username>
+ <hibernate.connection.password></hibernate.connection.password>
+ <hibernate.export.envers>true</hibernate.export.envers>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>de.juplo</groupId>
+ <artifactId>hibernate4-maven-plugin</artifactId>
+ <version>${de.juplo-hibernate-plugin-version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>export</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <outputFile>${project.build.sourceDirectory}/../scripts/sql/create-tables-hsqldb.sql
+ </outputFile>
+ <target>SCRIPT</target>
+ <type>CREATE</type>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${org.hibernate.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.scannotation</groupId>
+ <artifactId>scannotation</artifactId>
+ <version>1.0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${org.slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>${org.hsqldb.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${org.slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${org.slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>${org.hibernate.version}</version>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.jboss.spec.javax.transaction</groupId>
+ <artifactId>jboss-transaction-api_1.1_spec</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${org.hibernate.version}</version>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.jboss.spec.javax.transaction</groupId>
+ <artifactId>jboss-transaction-api_1.1_spec</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-envers</artifactId>
+ <version>${org.hibernate.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <version>${javax.validation_validation-api.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <artifactId>hibernate-validator</artifactId>
+ <groupId>org.hibernate</groupId>
+ <version>${org.hibernate_hibernate-validator.version}</version>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${org.junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.atomikos</groupId>
+ <artifactId>transactions-hibernate3</artifactId>
+ <version>3.8.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>${org.hsqldb.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.spec.javax.transaction</groupId>
+ <artifactId>jboss-transaction-api_1.1_spec</artifactId>
+ <version>1.0.0.Final</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${global_springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>${global_springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-jdbc</artifactId>
+ <version>${global_springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ <version>${global_springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ <version>1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${global_springframework.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ <encoding>utf8</encoding>
+ <showWarnings>true</showWarnings>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+
+ <testResources>
+ <testResource>
+ <directory>src/test/java</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </testResource>
+ <testResource>
+ <directory>src/main/scripts</directory>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ </testResources>
+
+ </build>
+
+</project>
--- /dev/null
+/**
+ * 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();
+ }
+
+}
--- /dev/null
+/**
+ * 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");
+
+
+ }
+
+}
--- /dev/null
+/**
+ * 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
--- /dev/null
+<!--
+ ~ 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.
+ -->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+ version="2.0">
+
+ <persistence-unit name="examplePU" transaction-type="JTA">
+ <description>
+ Example persistence unit.
+ </description>
+
+ <class>org.bitbucket.fbascheper.tutorial.envers.Event</class>
+
+ <properties>
+ <!-- These are set using spring config -->
+ </properties>
+
+ </persistence-unit>
+
+</persistence>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:jee="http://www.springframework.org/schema/jee"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
+
+ http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">
+
+ <bean id="transactionManager" class="${spring.jta.transaction.manager}"/>
+
+ <jee:jndi-lookup id="dataSource" jndi-name="${spring.jta.dataSource.name}"/>
+
+</beans>
--- /dev/null
+#
+# Configuration of the services
+#
+hibernate.hbm2ddl.auto = validate
+hibernate.show_sql = false
+hibernate.format_sql = false
+
+jpa.persistence.context.name = examplePU
+
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
+
+
+ <context:property-placeholder order="10"
+ location="classpath:spring-persistence-context.properties"
+ ignore-resource-not-found="false"/>
+
+ <tx:annotation-driven transaction-manager="transactionManager"/>
+
+
+ <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
+
+
+ <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
+ p:persistenceUnitName="${jpa.persistence.context.name}"
+ p:persistenceXmlLocation="classpath:META-INF/persistence-jpa.xml"
+ p:dataSource-ref="dataSource"
+ >
+
+ <property name="jpaVendorAdapter">
+ <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
+ </property>
+ <property name="jpaProperties">
+ <props>
+ <prop key="hibernate.dialect">${hibernate.dialect:org.hibernate.dialect.Oracle10gDialect}</prop>
+ <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto:validate}</prop>
+ <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
+ <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop>
+ <!--<prop key="hibernate.transaction.flush_before_completion">${hibernate.transaction.flush_before_completion}</prop>-->
+ <!--<prop key="hibernate.transaction.jta.platform">${hibernate.transaction.jta.platform}</prop>-->
+ <prop key="hibernate.transaction.manager_lookup_class">${hibernate.transaction.manager_lookup_class:org.hibernate.transaction.WebSphereExtendedJTATransactionLookup}</prop>
+ <!--<prop key="hibernate.transaction.factory_class">${hibernate.transaction.factory_class}</prop>-->
+ </props>
+ </property>
+ </bean>
+
+
+</beans>
--- /dev/null
+
+ 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;
--- /dev/null
+ 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 ;
+
--- /dev/null
+/**
+ * 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;
+ }
+
+}
--- /dev/null
+/**
+ * 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<Event>() {
+ @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<Event>() {
+ @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<Event> result = getTransactionTemplate().execute(new TransactionCallback<List<Event>>() {
+ @Override
+ public List<Event> doInTransaction(TransactionStatus status) {
+ List<Event> 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<? extends Number> 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()));
+
+ }
+
+ });
+
+ }
+
+}
--- /dev/null
+/**
+ * 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;
+
+ }
+ }
+
+}
--- /dev/null
+/**
+ * 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();
+ }
+
+}
--- /dev/null
+#
+# 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
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:p="http://www.springframework.org/schema/p"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
+
+ <bean name="props" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
+ p:order="-10"
+ p:ignoreResourceNotFound="false"
+ >
+ <property name="locations">
+ <list>
+ <value>classpath:/spring-persistence-context.properties</value>
+ <value>classpath:/hhv-test-datamodel-domain-context.properties</value>
+ </list>
+ </property>
+ </bean>
+
+
+ <!--<bean id="transactionManager" class="${spring.jta.transaction.manager}"-->
+ <!--depends-on="userTransactionService"-->
+ <!--p:transactionManager-ref="atomikosTransactionManager"-->
+ <!--p:userTransaction-ref="atomikosUserTransaction"-->
+ <!-->-->
+ <!--</bean>-->
+
+ <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"
+ depends-on="userTransactionService"
+ p:transactionManager-ref="atomikosTransactionManager"
+ p:userTransaction-ref="atomikosUserTransaction"
+ >
+ </bean>
+
+
+ <tx:annotation-driven transaction-manager="transactionManager"/>
+
+ <!--<bean id="localLogAdministrator" class="com.atomikos.icatch.admin.imp.LocalLogAdministrator"/>-->
+
+ <bean id="userTransactionService"
+ class="com.atomikos.icatch.config.UserTransactionServiceImp"
+ depends-on="props"
+ init-method="init" destroy-method="shutdownForce">
+ <constructor-arg>
+ <!-- IMPORTANT: specify all Atomikos properties here -->
+ <props>
+ <prop key="com.atomikos.icatch.service">
+ com.atomikos.icatch.standalone.UserTransactionServiceFactory
+ </prop>
+ </props>
+ </constructor-arg>
+ <!-- property name="initialLogAdministrators">
+ <list>
+ <ref bean="localLogAdministrator"/>
+ </list>
+ </property -->
+ </bean>
+
+ <!--
+ Construct Atomikos UserTransactionManager, needed to configure Spring
+ -->
+ <bean id="atomikosTransactionManager"
+ class="com.atomikos.icatch.jta.UserTransactionManager"
+ init-method="init" destroy-method="close"
+ depends-on="userTransactionService"
+ p:startupTransactionService="false"
+ p:forceShutdown="false"
+ >
+ </bean>
+
+ <!--
+ Also use Atomikos UserTransactionImp, needed to configure Spring
+ -->
+ <bean id="atomikosUserTransaction"
+ class="com.atomikos.icatch.jta.UserTransactionImp"
+ depends-on="userTransactionService"
+ p:transactionTimeout="300"
+ >
+ </bean>
+
+ <bean id="rawDataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean"
+ depends-on="props"
+ init-method="init" destroy-method="close"
+ p:uniqueResourceName="${atomikos.dataSource.uniqueResourceName}"
+ p:url="${dataSource.url}"
+ p:driverClassName="${dataSource.driverClassName}"
+ p:user="${dataSource.user}"
+ p:password="${dataSource.password}"
+ p:minPoolSize="0"
+ p:maxPoolSize="2"
+ >
+ </bean>
+
+ <bean id="initScriptRunner" class="org.bitbucket.fbascheper.tutorial.envers.util.InitScriptRunner$InitScriptRunnerImpl"
+ depends-on="rawDataSource">
+ <constructor-arg index="0" ref="rawDataSource" />
+ <constructor-arg index="1" value="classpath:sql/drop-tables-hsqldb.sql" />
+ <constructor-arg index="2" value="classpath:sql/create-tables-hsqldb.sql" />
+ </bean>
+
+ <bean id="dataSource" class="org.bitbucket.fbascheper.tutorial.envers.util.InitScriptRunningDataSourceFactoryBean"
+ factory-method="dataSourceFactory">
+ <constructor-arg index="0" ref="initScriptRunner" />
+ </bean>
+
+</beans>
--- /dev/null
+#*
+#*
+#* 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/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+
+<!-- Authors: Chris Taylor, Ceki Gulcu. -->
+
+<!-- Version: 1.2 -->
+
+<!-- A configuration element consists of optional renderer
+elements,appender elements, categories and an optional root
+element. -->
+
+<!ELEMENT log4j:configuration (renderer*, appender*,plugin*, (category|logger)*,root?,
+ (categoryFactory|loggerFactory)?)>
+
+<!-- The "threshold" attribute takes a level value below which -->
+<!-- all logging statements are disabled. -->
+
+<!-- Setting the "debug" enable the printing of internal log4j logging -->
+<!-- statements. -->
+
+<!-- By default, debug attribute is "null", meaning that we not do touch -->
+<!-- internal log4j logging settings. The "null" value for the threshold -->
+<!-- attribute can be misleading. The threshold field of a repository -->
+<!-- cannot be set to null. The "null" value for the threshold attribute -->
+<!-- simply means don't touch the threshold field, the threshold field -->
+<!-- keeps its old value. -->
+
+<!ATTLIST log4j:configuration
+ xmlns:log4j CDATA #FIXED "http://jakarta.apache.org/log4j/"
+ threshold (all|trace|debug|info|warn|error|fatal|off|null) "null"
+ debug (true|false|null) "null"
+ reset (true|false) "false"
+>
+
+<!-- renderer elements allow the user to customize the conversion of -->
+<!-- message objects to String. -->
+
+<!ELEMENT renderer EMPTY>
+<!ATTLIST renderer
+ renderedClass CDATA #REQUIRED
+ renderingClass CDATA #REQUIRED
+>
+
+<!-- Appenders must have a name and a class. -->
+<!-- Appenders may contain an error handler, a layout, optional parameters -->
+<!-- and filters. They may also reference (or include) other appenders. -->
+<!ELEMENT appender (errorHandler?, param*,
+ rollingPolicy?, triggeringPolicy?, connectionSource?,
+ layout?, filter*, appender-ref*)>
+<!ATTLIST appender
+ name CDATA #REQUIRED
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT layout (param*)>
+<!ATTLIST layout
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT filter (param*)>
+<!ATTLIST filter
+ class CDATA #REQUIRED
+>
+
+<!-- ErrorHandlers can be of any class. They can admit any number of -->
+<!-- parameters. -->
+
+<!ELEMENT errorHandler (param*, root-ref?, logger-ref*, appender-ref?)>
+<!ATTLIST errorHandler
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT root-ref EMPTY>
+
+<!ELEMENT logger-ref EMPTY>
+<!ATTLIST logger-ref
+ ref CDATA #REQUIRED
+>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ name CDATA #REQUIRED
+ value CDATA #REQUIRED
+>
+
+
+<!-- The priority class is org.apache.log4j.Level by default -->
+<!ELEMENT priority (param*)>
+<!ATTLIST priority
+ class CDATA #IMPLIED
+ value CDATA #REQUIRED
+>
+
+<!-- The level class is org.apache.log4j.Level by default -->
+<!ELEMENT level (param*)>
+<!ATTLIST level
+ class CDATA #IMPLIED
+ value CDATA #REQUIRED
+>
+
+
+<!-- If no level element is specified, then the configurator MUST not -->
+<!-- touch the level of the named category. -->
+<!ELEMENT category (param*,(priority|level)?,appender-ref*)>
+<!ATTLIST category
+ class CDATA #IMPLIED
+ name CDATA #REQUIRED
+ additivity (true|false) "true"
+>
+
+<!-- If no level element is specified, then the configurator MUST not -->
+<!-- touch the level of the named logger. -->
+<!ELEMENT logger (level?,appender-ref*)>
+<!ATTLIST logger
+ name CDATA #REQUIRED
+ additivity (true|false) "true"
+>
+
+
+<!ELEMENT categoryFactory (param*)>
+<!ATTLIST categoryFactory
+ class CDATA #REQUIRED>
+
+<!ELEMENT loggerFactory (param*)>
+<!ATTLIST loggerFactory
+ class CDATA #REQUIRED>
+
+<!ELEMENT appender-ref EMPTY>
+<!ATTLIST appender-ref
+ ref CDATA #REQUIRED
+>
+
+<!-- plugins must have a name and class and can have optional parameters -->
+<!ELEMENT plugin (param*, connectionSource?)>
+<!ATTLIST plugin
+ name CDATA #REQUIRED
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT connectionSource (dataSource?, param*)>
+<!ATTLIST connectionSource
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT dataSource (param*)>
+<!ATTLIST dataSource
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT triggeringPolicy ((param|filter)*)>
+<!ATTLIST triggeringPolicy
+ name CDATA #IMPLIED
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT rollingPolicy (param*)>
+<!ATTLIST rollingPolicy
+ name CDATA #IMPLIED
+ class CDATA #REQUIRED
+>
+
+
+<!-- If no priority element is specified, then the configurator MUST not -->
+<!-- touch the priority of root. -->
+<!-- The root category always exists and cannot be subclassed. -->
+<!ELEMENT root (param*, (priority|level)?, appender-ref*)>
+
+
+<!-- ==================================================================== -->
+<!-- A logging event -->
+<!-- ==================================================================== -->
+<!ELEMENT log4j:eventSet (log4j:event*)>
+<!ATTLIST log4j:eventSet
+ xmlns:log4j CDATA #FIXED "http://jakarta.apache.org/log4j/"
+ version (1.1|1.2) "1.2"
+ includesLocationInfo (true|false) "true"
+>
+
+
+
+<!ELEMENT log4j:event (log4j:message, log4j:NDC?, log4j:throwable?,
+ log4j:locationInfo?, log4j:properties?) >
+
+<!-- The timestamp initiationServiceType is application dependent. -->
+<!ATTLIST log4j:event
+ logger CDATA #REQUIRED
+ level CDATA #REQUIRED
+ thread CDATA #REQUIRED
+ timestamp CDATA #REQUIRED
+ time CDATA #IMPLIED
+>
+
+<!ELEMENT log4j:message (#PCDATA)>
+<!ELEMENT log4j:NDC (#PCDATA)>
+
+<!ELEMENT log4j:throwable (#PCDATA)>
+
+<!ELEMENT log4j:locationInfo EMPTY>
+<!ATTLIST log4j:locationInfo
+ class CDATA #REQUIRED
+ method CDATA #REQUIRED
+ file CDATA #REQUIRED
+ line CDATA #REQUIRED
+>
+
+<!ELEMENT log4j:properties (log4j:data*)>
+
+<!ELEMENT log4j:data EMPTY>
+<!ATTLIST log4j:data
+ name CDATA #REQUIRED
+ value CDATA #REQUIRED
+>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- Print the date in ISO 8601 initiationServiceType -->
+ <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
+ </layout>
+ </appender>
+
+ <logger name="org.hibernate" additivity="false">
+ <!-- Print only messages of level warn or above in the package com.foo -->
+ <level value="info"/>
+ <appender-ref ref="stdout" />
+ </logger>
+ <logger name="org.hibernate.tool.hbm2ddl" additivity="false">
+ <!-- Print only messages of level warn or above in the package com.foo -->
+ <level value="warn"/>
+ <appender-ref ref="stdout" />
+ </logger>
+ <logger name="org.hibernate.SQL" additivity="false">
+ <!-- Print only messages of level warn or above in the package com.foo -->
+ <level value="debug"/>
+ <appender-ref ref="stdout" />
+ </logger>
+ <logger name="org.hibernate.type.descriptor.sql.BasicBinder" additivity="false">
+ <!-- Print only messages of level warn or above in the package com.foo -->
+ <level value="trace"/>
+ <appender-ref ref="stdout" />
+ </logger>
+ <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" additivity="false">
+ <!-- Print only messages of level warn or above in the package com.foo -->
+ <level value="info"/>
+ <appender-ref ref="stdout" />
+ </logger>
+
+ <root>
+ <priority value ="warn" />
+ <appender-ref ref="stdout" />
+ </root>
+</log4j:configuration>
\ No newline at end of file