You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by th...@apache.org on 2013/06/27 10:39:10 UTC

[10/11] git commit: DELTASPIKE-60 Data module initial import

DELTASPIKE-60 Data module initial import

This is a port of the CDI-Query CDI extension. See the README for more
details about it.


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/ae1a7147
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/ae1a7147
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/ae1a7147

Branch: refs/heads/master
Commit: ae1a71478d54fdd34e67770760f4645b5f57d2a3
Parents: 4f2d9a5
Author: Thomas Hug <Th...@ctp-consulting.com>
Authored: Tue Jun 25 15:06:34 2013 +0200
Committer: Thomas Hug <Th...@ctp-consulting.com>
Committed: Thu Jun 27 10:25:34 2013 +0200

----------------------------------------------------------------------
 deltaspike/modules/data/README.adoc             | 1007 ++++++++++++++++++
 deltaspike/modules/data/api/pom.xml             |   95 ++
 .../data/api/AbstractEntityRepository.java      |   61 ++
 .../data/api/EntityManagerConfig.java           |   51 +
 .../data/api/EntityManagerResolver.java         |   34 +
 .../deltaspike/data/api/EntityRepository.java   |  167 +++
 .../apache/deltaspike/data/api/FirstResult.java |   35 +
 .../apache/deltaspike/data/api/MaxResults.java  |   34 +
 .../apache/deltaspike/data/api/Modifying.java   |   37 +
 .../org/apache/deltaspike/data/api/Query.java   |   76 ++
 .../apache/deltaspike/data/api/QueryParam.java  |   37 +
 .../apache/deltaspike/data/api/QueryResult.java |  207 ++++
 .../apache/deltaspike/data/api/Repository.java  |   54 +
 .../deltaspike/data/api/audit/CreatedOn.java    |   33 +
 .../deltaspike/data/api/audit/CurrentUser.java  |   42 +
 .../deltaspike/data/api/audit/ModifiedBy.java   |   33 +
 .../deltaspike/data/api/audit/ModifiedOn.java   |   36 +
 .../deltaspike/data/api/criteria/Criteria.java  |  302 ++++++
 .../data/api/criteria/CriteriaSupport.java      |  196 ++++
 .../data/api/criteria/QuerySelection.java       |   46 +
 .../data/spi/DelegateQueryHandler.java          |   48 +
 .../data/spi/QueryInvocationContext.java        |   47 +
 deltaspike/modules/data/impl/pom.xml            |  259 +++++
 .../impl/RepositoryDefinitionException.java     |   56 +
 .../data/impl/RepositoryExtension.java          |  105 ++
 .../data/impl/audit/AuditEntityListener.java    |   59 +
 .../data/impl/audit/AuditPropertyException.java |   31 +
 .../data/impl/audit/AuditProvider.java          |   35 +
 .../impl/audit/PrePersistAuditListener.java     |   26 +
 .../data/impl/audit/PreUpdateAuditListener.java |   26 +
 .../data/impl/audit/PrincipalProvider.java      |   94 ++
 .../data/impl/audit/TimestampsProvider.java     |  128 +++
 .../impl/builder/AnnotatedQueryBuilder.java     |   87 ++
 .../data/impl/builder/DelegateQueryBuilder.java |  113 ++
 .../impl/builder/MethodExpressionException.java |   51 +
 .../data/impl/builder/MethodQueryBuilder.java   |   53 +
 .../data/impl/builder/OrderDirection.java       |   42 +
 .../data/impl/builder/QueryBuilder.java         |  121 +++
 .../data/impl/builder/QueryBuilderContext.java  |   56 +
 .../data/impl/builder/QueryBuilderFactory.java  |   50 +
 .../data/impl/builder/QueryOperator.java        |   71 ++
 .../data/impl/builder/WrappedQueryBuilder.java  |   41 +
 .../data/impl/builder/part/AndQueryPart.java    |   54 +
 .../builder/part/BasePropertyQueryPart.java     |   62 ++
 .../impl/builder/part/ConnectingQueryPart.java  |   40 +
 .../data/impl/builder/part/OrQueryPart.java     |   62 ++
 .../impl/builder/part/OrderByQueryPart.java     |  154 +++
 .../impl/builder/part/PropertyQueryPart.java    |   72 ++
 .../data/impl/builder/part/QueryPart.java       |   64 ++
 .../data/impl/builder/part/QueryRoot.java       |  138 +++
 .../postprocessor/CountQueryPostProcessor.java  |  124 +++
 .../postprocessor/FirstResultPostProcessor.java |   43 +
 .../postprocessor/FlushModePostProcessor.java   |   44 +
 .../postprocessor/HintPostProcessor.java        |   45 +
 .../postprocessor/LockModePostProcessor.java    |   44 +
 .../postprocessor/MaxResultPostProcessor.java   |   43 +
 .../OrderByQueryStringPostProcessor.java        |   80 ++
 .../impl/builder/result/DefaultQueryResult.java |  284 +++++
 .../impl/builder/result/QueryProcessor.java     |   28 +
 .../builder/result/QueryProcessorFactory.java   |  122 +++
 .../data/impl/criteria/QueryCriteria.java       |  428 ++++++++
 .../data/impl/criteria/predicate/Between.java   |   46 +
 .../data/impl/criteria/predicate/Eq.java        |   43 +
 .../impl/criteria/predicate/FetchBuilder.java   |  118 ++
 .../impl/criteria/predicate/GreaterThan.java    |   43 +
 .../criteria/predicate/GreaterThanOrEqual.java  |   43 +
 .../data/impl/criteria/predicate/In.java        |   66 ++
 .../data/impl/criteria/predicate/IsEmpty.java   |   44 +
 .../impl/criteria/predicate/IsNotEmpty.java     |   44 +
 .../data/impl/criteria/predicate/IsNotNull.java |   43 +
 .../data/impl/criteria/predicate/IsNull.java    |   43 +
 .../impl/criteria/predicate/JoinBuilder.java    |  158 +++
 .../data/impl/criteria/predicate/LessThan.java  |   43 +
 .../criteria/predicate/LessThanOrEqual.java     |   43 +
 .../data/impl/criteria/predicate/Like.java      |   43 +
 .../impl/criteria/predicate/NoValueBuilder.java |   38 +
 .../data/impl/criteria/predicate/NotEq.java     |   43 +
 .../data/impl/criteria/predicate/NotLike.java   |   43 +
 .../data/impl/criteria/predicate/OrBuilder.java |   53 +
 .../criteria/predicate/PredicateBuilder.java    |   32 +
 .../criteria/predicate/SingleValueBuilder.java  |   39 +
 .../data/impl/criteria/processor/OrderBy.java   |   53 +
 .../impl/criteria/processor/QueryProcessor.java |   30 +
 .../selection/AttributeQuerySelection.java      |   41 +
 .../selection/SingularAttributeSelection.java   |   40 +
 .../impl/criteria/selection/numeric/Abs.java    |   43 +
 .../impl/criteria/selection/numeric/Avg.java    |   43 +
 .../impl/criteria/selection/numeric/Count.java  |   43 +
 .../impl/criteria/selection/numeric/Max.java    |   43 +
 .../impl/criteria/selection/numeric/Min.java    |   43 +
 .../impl/criteria/selection/numeric/Modulo.java |   46 +
 .../impl/criteria/selection/numeric/Neg.java    |   43 +
 .../impl/criteria/selection/numeric/Sum.java    |   43 +
 .../impl/criteria/selection/strings/Lower.java  |   43 +
 .../selection/strings/SubstringFrom.java        |   51 +
 .../selection/strings/SubstringFromTo.java      |   44 +
 .../impl/criteria/selection/strings/Upper.java  |   43 +
 .../selection/temporal/CurrentDate.java         |   39 +
 .../selection/temporal/CurrentTime.java         |   39 +
 .../selection/temporal/CurrentTimestamp.java    |   39 +
 .../handler/AbstractDelegateQueryHandler.java   |   43 +
 .../impl/handler/CdiQueryContextHolder.java     |   46 +
 .../impl/handler/CdiQueryInvocationContext.java |  172 +++
 .../impl/handler/CriteriaSupportHandler.java    |  179 ++++
 .../data/impl/handler/EntityManagerLookup.java  |   59 +
 .../impl/handler/EntityRepositoryHandler.java   |  328 ++++++
 .../impl/handler/JpaQueryPostProcessor.java     |   28 +
 .../data/impl/handler/QueryHandler.java         |  129 +++
 .../impl/handler/QueryInvocationException.java  |   72 ++
 .../impl/handler/QueryStringPostProcessor.java  |   26 +
 .../deltaspike/data/impl/meta/Initialized.java  |   44 +
 .../deltaspike/data/impl/meta/MethodType.java   |   38 +
 .../data/impl/meta/NonEntityException.java      |   46 +
 .../data/impl/meta/QueryInvocation.java         |   48 +
 .../data/impl/meta/QueryInvocationLiteral.java  |   48 +
 .../data/impl/meta/RepositoryComponent.java     |  213 ++++
 .../data/impl/meta/RepositoryComponents.java    |  122 +++
 .../impl/meta/RepositoryComponentsFactory.java  |   46 +
 .../data/impl/meta/RepositoryEntity.java        |   69 ++
 .../data/impl/meta/RepositoryMethod.java        |  140 +++
 .../extractor/AnnotationMetadataExtractor.java  |   50 +
 .../impl/meta/extractor/MetadataExtractor.java  |   34 +
 .../meta/extractor/TypeMetadataExtractor.java   |   93 ++
 .../data/impl/meta/unit/Descriptor.java         |   47 +
 .../meta/unit/DescriptorHierarchyBuilder.java   |   88 ++
 .../data/impl/meta/unit/DescriptorReader.java   |  122 +++
 .../data/impl/meta/unit/EntityDescriptor.java   |   72 ++
 .../impl/meta/unit/EntityDescriptorReader.java  |  167 +++
 .../meta/unit/MappedSuperclassDescriptor.java   |   67 ++
 .../data/impl/meta/unit/PersistenceUnit.java    |   64 ++
 .../impl/meta/unit/PersistenceUnitReader.java   |   91 ++
 .../data/impl/meta/unit/PersistenceUnits.java   |  119 +++
 .../meta/unit/PersistentClassDescriptor.java    |  132 +++
 .../data/impl/meta/verifier/EntityVerifier.java |   34 +
 .../data/impl/meta/verifier/Verifier.java       |   26 +
 .../data/impl/param/IndexedParameter.java       |   45 +
 .../data/impl/param/NamedParameter.java         |   45 +
 .../deltaspike/data/impl/param/Parameter.java   |   42 +
 .../deltaspike/data/impl/param/Parameters.java  |  175 +++
 .../data/impl/property/FieldProperty.java       |   29 +
 .../data/impl/property/FieldPropertyImpl.java   |  121 +++
 .../data/impl/property/MethodProperty.java      |   29 +
 .../data/impl/property/MethodPropertyImpl.java  |  272 +++++
 .../data/impl/property/Properties.java          |  108 ++
 .../deltaspike/data/impl/property/Property.java |  116 ++
 .../data/impl/property/Reflections.java         |  514 +++++++++
 .../query/AnnotatedPropertyCriteria.java        |   52 +
 .../property/query/NamedPropertyCriteria.java   |   67 ++
 .../impl/property/query/PropertyCriteria.java   |   58 +
 .../impl/property/query/PropertyQueries.java    |   47 +
 .../data/impl/property/query/PropertyQuery.java |  252 +++++
 .../property/query/TypedPropertyCriteria.java   |   50 +
 .../deltaspike/data/impl/util/EntityUtils.java  |  114 ++
 .../deltaspike/data/impl/util/QueryUtils.java   |   97 ++
 .../impl/util/jpa/BaseQueryStringExtractor.java |   38 +
 .../jpa/EclipseLinkEjbQueryStringExtractor.java |   34 +
 .../util/jpa/HibernateQueryStringExtractor.java |   34 +
 .../util/jpa/OpenJpaQueryStringExtractor.java   |   33 +
 .../data/impl/util/jpa/ProviderSpecific.java    |   34 +
 .../impl/util/jpa/QueryStringExtractor.java     |   28 +
 .../util/jpa/QueryStringExtractorFactory.java   |   61 ++
 .../impl/src/main/resources/META-INF/beans.xml  |   26 +
 .../javax.enterprise.inject.spi.Extension       |   20 +
 .../deltaspike/data/impl/QueryResultTest.java   |  292 +++++
 .../data/impl/RepositoryExtensionTest.java      |   68 ++
 .../impl/audit/AuditEntityListenerTest.java     |  135 +++
 .../data/impl/audit/TimestampsProviderTest.java |  102 ++
 .../data/impl/builder/part/QueryRootTest.java   |  141 +++
 .../data/impl/criteria/CriteriaTest.java        |  308 ++++++
 .../data/impl/handler/EntityManagerTest.java    |   93 ++
 .../impl/handler/EntityManagerTestProducer.java |   35 +
 .../handler/EntityRepositoryHandlerTest.java    |  359 +++++++
 .../data/impl/handler/QueryHandlerTest.java     |  294 +++++
 .../AnnotationMetadataExtractorTest.java        |   84 ++
 .../extractor/TypeMetadataExtractorTest.java    |   64 ++
 .../unit/DescriptorHierarchyBuilderTest.java    |   99 ++
 .../meta/unit/OrmXmlBasedRepositoryTest.java    |   94 ++
 .../impl/meta/unit/PersistenceUnitsTest.java    |  149 +++
 .../impl/meta/verifier/EntityVerifierTest.java  |   62 ++
 .../data/impl/property/ClassToIntrospect.java   |  100 ++
 .../impl/property/PropertyFromFieldTest.java    |   44 +
 .../impl/property/PropertyFromMethodTest.java   |  144 +++
 .../impl/property/query/PropertyQueryTest.java  |  108 ++
 .../data/impl/spi/CdiQuerySpiTest.java          |   76 ++
 .../data/impl/util/EntityUtilsTest.java         |   56 +
 .../data/test/TransactionalTestCase.java        |   53 +
 .../data/test/domain/AuditedEntity.java         |  129 +++
 .../data/test/domain/EmbeddedSimple.java        |   39 +
 .../deltaspike/data/test/domain/Home.java       |   50 +
 .../data/test/domain/NamedEntity.java           |   59 +
 .../deltaspike/data/test/domain/OneToMany.java  |   37 +
 .../deltaspike/data/test/domain/OneToOne.java   |   36 +
 .../deltaspike/data/test/domain/Parent.java     |   90 ++
 .../deltaspike/data/test/domain/Principal.java  |   73 ++
 .../deltaspike/data/test/domain/Simple.java     |  140 +++
 .../deltaspike/data/test/domain/Simple2.java    |   59 +
 .../deltaspike/data/test/domain/Simple3.java    |   50 +
 .../data/test/domain/SimpleBuilder.java         |   53 +
 .../apache/deltaspike/data/test/domain/Tee.java |   54 +
 .../deltaspike/data/test/domain/Tee2.java       |   57 +
 .../deltaspike/data/test/domain/TeeId.java      |  103 ++
 .../data/test/domain/mapped/MappedId.java       |   36 +
 .../data/test/domain/mapped/MappedOne.java      |   56 +
 .../test/domain/mapped/MappedSuperclass.java    |   36 +
 .../data/test/domain/mapped/MappedThree.java    |   36 +
 .../data/test/domain/mapped/MappedTwo.java      |   59 +
 .../service/ExtendedRepositoryInterface.java    |   28 +
 .../data/test/service/HomeRepository.java       |   30 +
 .../data/test/service/MappedOneRepository.java  |   31 +
 .../data/test/service/MyEntityRepository.java   |   26 +
 .../service/MyEntityRepositoryDelegate.java     |   47 +
 .../data/test/service/MySimpleRepository.java   |   28 +
 .../data/test/service/ParentRepository.java     |  110 ++
 .../data/test/service/RepositoryInterface.java  |   28 +
 .../data/test/service/Simple2Repository.java    |   31 +
 .../test/service/SimpleCriteriaRepository.java  |   75 ++
 .../test/service/SimpleFetchRepository.java     |   28 +
 .../data/test/service/SimpleRepository.java     |   84 ++
 .../SimpleRepositoryWithEntityManager.java      |   35 +
 ...leRepositoryWithOverriddenEntityManager.java |   42 +
 .../data/test/service/Simplistic.java           |   39 +
 .../SimplisticEntityManagerResolver.java        |   37 +
 .../data/test/service/Statistics.java           |   53 +
 .../deltaspike/data/test/util/Logging.java      |   43 +
 .../data/test/util/TestDeployments.java         |  137 +++
 .../test-mapped-persistence.xml                 |   32 +
 .../resources-glassfish/test-persistence.xml    |   30 +
 .../test-mapped-persistence.xml                 |   29 +
 .../resources-jbossas7/test-persistence.xml     |   27 +
 .../test-mapped-persistence.xml                 |   32 +
 .../test/resources-openejb/test-persistence.xml |   31 +
 .../data/impl/src/test/resources/arquillian.xml |   96 ++
 .../data/impl/src/test/resources/log4j.xml      |   59 +
 .../impl/src/test/resources/logging.properties  |   32 +
 .../impl/src/test/resources/test-custom-orm.xml |   43 +
 .../src/test/resources/test-default-orm.xml     |   33 +
 .../data/impl/src/test/resources/test-orm.xml   |   32 +
 deltaspike/modules/data/pom.xml                 |  170 +++
 deltaspike/modules/pom.xml                      |    1 +
 deltaspike/parent/pom.xml                       |   23 +
 240 files changed, 19447 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/README.adoc
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/README.adoc b/deltaspike/modules/data/README.adoc
new file mode 100644
index 0000000..5252196
--- /dev/null
+++ b/deltaspike/modules/data/README.adoc
@@ -0,0 +1,1007 @@
+= DeltaSpike Data
+Thomas Hug <th...@apache.org>
+
+///////////
+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.
+///////////
+
+== DeltaSpike Data
+
+=== Introduction
+
+The repository pattern used to be one of the core J2EE patterns and could be found in 
+most enterprise applications reading and writing data to persistent stores. 
+While the Java Persistence API (JPA) as part of Java EE 5+ has replaced many aspects of the
+repository pattern, it is still a good approach to centralize complex query logic related to 
+specific entities.
+
+The DeltaSpike Data module is intended to help you simplifying your repository layer.
+While you will have complex queries in a repository requiring your full attention,
+there will also be many simple ones often requiring boilerplate code and clutter.
+This is where the DeltaSpike data module will help you keeping your repository lean so you 
+can focus on the though things.
+
+The code sample below will give you a quick overview on the common usage scenarios of the data module:
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    List<Person> findByAgeBetweenAndGender(int minAge, int maxAge, Gender gender);
+
+    @Query("select p from Person p where p.ssn = ?1")
+    Person findBySSN(String ssn);
+
+    @Query(named=Person.BY_FULL_NAME)
+    Person findByFullName(String firstName, String lastName);
+
+}
+----
+
+As you see in the sample, there are several usage scenarios outlined here:
+
+* Declare a method which executes a query by simply translating its name and parameters into a query.
+* Declare a method which automatically executes a given JPQL query string with parameters.
+* Declare a method which automatically executes a named query with parameters. 
+
+The implementation of the method is done automatically by the CDI extension. 
+A client can declare a dependency to the interface only. The details on how to use those 
+features are outlines in the following chapters.
+
+=== Installation
+
+==== Prerequisites
+
+The simplest way using the DeltaSpike data module is to run your application in a Java EE container
+supporting at least the Java EE 6 Web Profile. Other configurations like running it inside Tomcat or 
+even a Java SE application should be possible - you need to include a JPA provider as well as a CDI container
+to your application manually.
+
+Also note that in order to use abstract classes as repositories, this currently requires the presence
+of the http://www.javassist.org[javassist] library in your classpath.
+
+==== Maven Dependency Configuration
+
+If you are using Maven as your build tool, you can add the following dependencies to your +pom.xml+
+file to include the DeltaSpike data module:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.deltaspike.modules</groupId>
+    <artifactId>deltaspike-data-module-api</artifactId>
+    <version>${deltaspike.version}</version>
+    <scope>compile</scope>
+</dependency>
+<dependency>
+    <groupId>org.apache.deltaspike.modules</groupId>
+    <artifactId>deltaspike-data-module-impl</artifactId>
+    <version>${deltaspike.version}</version>
+    <scope>runtime</scope>
+</dependency>
+----
+
+[TIP]
+===============================
+Substitute the expression +${deltaspike.version}+ with the most recent or appropriate version
+of DeltaSpike. Alternatively, you can create a Maven user-defined property to satisfy this 
+substitution so you can centrally manage the version. 
+===============================
+
+Including the API at compile time and only include the implementation at runtime protects you from
+inadvertantly depending on an implementation class.
+
+==== Setup your application
+
+DeltaSpike data requires an +EntityManager+ exposed via a CDI producer - which is common practice
+in Java EE 6 applications.
+
+[source,java]
+----
+public class DataSourceProducer
+{
+
+    @PersistenceUnit
+    private EntityManagerFactory emf;
+
+    @Produces
+    public EntityManager create()
+    {
+        return emf.createEntityManager();
+    }
+
+    public void close(@Disposes EntityManager em)
+    {
+        em.close();
+    }
+
+}
+----
+
+This allows the +EntityManager+ to be injected over CDI instead of only being used with a
++@PersistenceContext+ annotation. Using multiple +EntityManager+ is explored in more detail
+in a following section.
+
+You're now ready to use repositories in your application!
+
+=== Core Concepts
+
+==== Repositories
+
+With the DeltaSpike data module, it is possible to make a repository out of basically any
+abstract class or interface (using a concrete class will work too, but you won't be able to use
+most of the CDI extension features). All that is required is to mark the type as such with a
+simple annotation:
+
+[source,java]
+----
+@Repository(forEntity = Person.class)
+public abstract class PersonRepository {
+    ...
+}
+
+@Repository(forEntity = Person.class)
+public interface PersonRepository {
+    ...
+}    
+----
+
+The +@Repository+ annotation tells the extension that this is a repository for the +Person+ entity.
+Any method defined on the repository will be processed by the framework. The annotation does not
+require to set the entity class (we'll see later why) but if there are just plain classes or
+interfaces this is the only way to tell the framework what entity the repository relates to. 
+In order to simplify this, DeltaSpike data provides several base types.
+
+===== The +EntityRepository+ interface
+
+Although mainly intended to hold complex query logic, working with both a repository and an +EntityManager+
+in the service layer might unnecessarily clutter code. In order to avoid this for the most common cases,
+DeltaSpike data provides base types which can be used to replace the entity manager.
+
+The top base type is the +EntityRepository+ interface, providing common methods used with an +EntityManager+.
+The following code shows the most important methods of the interface:
+
+[source,java]
+----
+public interface EntityRepository<E, PK extends Serializable>
+{
+
+    E save(E entity);
+
+    void remove(E entity);
+
+    void refresh(E entity);
+
+    void flush();
+
+    E findBy(PK primaryKey);
+
+    List<E> findAll();
+
+    List<E> findBy(E example, SingularAttribute<E, ?>... attributes);
+
+    List<E> findByLike(E example, SingularAttribute<E, ?>... attributes);
+
+    Long count();
+
+    Long count(E example, SingularAttribute<E, ?>... attributes);
+
+    Long countLike(E example, SingularAttribute<E, ?>... attributes);
+
+} 
+----
+
+The concrete repository can then extend this basic interface. For our Person repository,
+this might look like the following:
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    Person findBySsn(String ssn);
+
+} 
+----
+
+[TIP]
+===============================
+Annotations on interfaces do not inherit. If the +EntityRepository+ interface is extended by another
+interface adding some more common methods, it is not possible to simply add the annotation there.
+It needs to go on each concrete repository. The same is not true if a base class is introduced,
+as we see in the next chapter. 
+===============================
+
+===== The +AbstractEntityRepository+ class
+
+This class is an implementation of the +EntityRepository+ interface and provides additional functionality
+when custom query logic needs also to be implemented in the repository.
+
+[source,java]
+----
+public abstract class PersonRepository extends AbstractEntityRepository<Person, Long>
+{
+
+    public Person findBySSN(String ssn)
+    {
+        return getEntityManager()
+                .createQuery("select p from Person p where p.ssn = ?1", Person.class)
+                .setParameter(1, ssn)
+                .getResultList();
+    }
+
+}
+----
+
+==== Using Multiple +EntityManager+
+
+While most applications will run just fine with a single +EntityManager+, there might be setups
+where multiple data sources are used. This can be configured with the +EntityManagerConfig+ annotation:
+
+[source,java]
+----
+@Repository
+@EntityManagerConfig(entityManagerResolver = CrmEntityManagerResolver.class, flushMode = FlushModeType.COMMIT)
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+    ...
+}
+
+public class CrmEntityManagerResolver implements EntityManagerResolver
+{
+    @Inject @CustomerData // Qualifier - assumes a producer is around...
+    private EntityManager em;
+
+    @Override
+    public EntityManager resolveEntityManager()
+    {
+        return em;
+    }
+}
+----
+
+Again, note that annotations on interfaces do not inherit, so it's not possible to create something like a base
++CrmRepository+ interface with the +@EntityManagerConfig+ and then extending / implementing this interface.
+
+=== Query Method Expressions
+
+Good naming is a difficult aspects in software engineering. A good method name usually makes 
+comments unnecessary and states exactly what the method does. And with method expressions, the 
+method name is actually the implementation!
+
+==== Using method expressions
+
+Let's start by looking at a (simplified for readability) example:
+
+[source,java]
+----
+@Entity
+public class Person
+{
+
+    @Id @GeneratedValue
+    private Long id;
+    private String name;
+    private Integer age;
+    private Gender gender;
+
+}
+
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    List<Person> findByNameLikeAndAgeBetweenAndGender(String name, 
+                                  int minAge, int maxAge, Gender gender);
+
+}
+----
+
+Looking at the method name, this can easily be read as query all Persons which have a name like
+the given name parameter, their age is between a min and a max age and having a specific gender.
+The DeltaSpike module can translate method names following a given format and directly generate
+the query implementation out of it (in EBNF-like form):
+
+[source]
+----
+(Entity|List<Entity>) findBy(Property[Comparator]){Operator Property [Comparator]}
+----
+
+Or in more concrete words:
+
+* The query method must either return an entity or a list of entities
+* It must start with the +findBy+ keyword
+* Followed by a property of the Repository entity and an optional comparator (we'll define this later). The property will be used in the query together with the comparator. Note that the number of arguments passed to the method depend on the comparator.
+* You can add more blocks of property-comparator which have to be concatenated by a boolean operator. This is either an +And+ or +Or+
+
+Other assumptions taken by the expression evaluator:
+
+* The property name starts lower cased while the property in the expression has an upper cases first character. 
+
+Following comparators are currently supported to be used in method expressions:
+
+[options="header"]
+|=======
+|Name                |# of Arguments |Description
+|Equal               |1              |Property must be equal to argument value. If the operator is omitted in the expression, this is assumed as default.
+|NotEqual            |1              |Property must be not equal to argument value.
+|Like                |1              |Property must be like the argument value. Use the %-wildcard in the argument.
+|GreaterThan         |1              |Property must be greater than argument value.
+|GreaterThanEquals   |1              |Property must be greater than or equal to argument value.
+|LessThan            |1              |Property must be less than argument value.
+|LessThanEquals      |1              |Property must be less than or equal to argument value.
+|Between             |2              |Property must be between the two argument values.
+|IsNull              |0              |Property must be null.
+|IsNotNull           |0              |Property must be non-null.
+|=======
+
+Note that DeltaSpike will validate those expressions during startup, so you will notice early in case you have a typo
+in those expressions.
+
+==== Query Ordering
+
+Beside comparators it's also possible to sort queries by using the +OrderBy+ keyword, followed
+by the attribute name and the direction (+Asc+ or +Desc+).
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    List<Person> findByLastNameLikeOrderByAgeAscLastNameDesc(String lastName);
+
+} 
+----
+
+==== Nested Properties
+
+To create a comparison on a nested property, the traversal parts can be separated by a +_+:
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    List<Person> findByCompany_companyName(String companyName);
+
+}
+----
+
+==== Query Options
+
+DeltaSpike supports query options on method expressions. If you want to page a query,
+you can change the first result as well as the maximum number of results returned:
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    List<Person> findByNameLike(String name, @FirstResult int start, @MaxResults int pageSize);
+
+}
+----
+
+==== Method Prefix
+
+In case the +findBy+ prefix does not comply with your team conventions, this can be adapted:
+
+[source,java]
+----
+@Repository(methodPrefix = "fetchWith")
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    List<Person> fetchWithNameLike(String name, @FirstResult int start, @MaxResults int pageSize);
+
+}
+----
+
+=== Query Annotations
+
+While method expressions are fine for simple queries, they will often reach their limit once things
+get slightly more complex. Another aspect is the way you want to use JPA: The recommended approach 
+using JPA for best performance is over named queries. To help incorporate those use cases, the 
+DeltaSpike data module supports also annotating methods for more control on the generated query.
+
+==== Using Query Annotations
+
+The simples way to define a specific query is by annotating a method and providing the JPQL query
+string which has to be executed. In code, this looks like the following sample:
+
+[source,java]
+----
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    @Query("select count(p) from Person p where p.age > ?1")
+    Long countAllOlderThan(int minAge);
+
+}
+---- 
+
+The parameter binding in the query corresponds to the argument index in the method.
+
+You can also refer to a named query which is constructed and executed automatically. The +@Query+
+annotation has a named attribute which corresponds to the query name:
+
+[source,java]
+----
+@Entity
+@NamedQueries({
+    @NamedQuery(name = Person.BY_MIN_AGE,
+                query = "select count(p) from Person p where p.age > ?1 order by p.age asc")
+})
+public class Person
+{
+
+    public static final String BY_MIN_AGE = "person.byMinAge";
+    ...
+
+}
+
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    @Query(named = Person.BY_MIN_AGE)
+    Long countAllOlderThan(int minAge);
+
+}
+----
+
+Same as before, the parameter binding corresponds to the argument index in the method. If the named
+query requires named parameters to be used, this can be done by annotating the arguments with the 
++@QueryParam+ annotation.
+
+[TIP]
+===============================
+Java does not preserve method parameter names (yet), that's why the annotation is needed.
+===============================
+
+[source,java]
+----
+@NamedQuery(name = Person.BY_MIN_AGE,
+            query = "select count(p) from Person p where p.age > :minAge order by p.age asc")
+            
+...
+
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    @Query(named = Person.BY_MIN_AGE)
+    Long countAllOlderThan(@QueryParam("minAge") int minAge);
+
+}
+----
+
+It is also possible to set a native SQL query in the annotation. The +@Query+ annotation has a native attribute
+which flags that the query is not JPQL but plain SQL:
+
+[source,java]
+----
+@Entity
+@Table(name = "PERSON_TABLE")
+public class Person
+{
+    ...
+}
+
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    @Query(value = "SELECT * FROM PERSON_TABLE p WHERE p.AGE > ?1", isNative = true)
+    List<Person> findAllOlderThan(int minAge);
+
+}
+----
+
+==== Annotation Options
+
+Beside providing a query string or reference, the +@Query+ annotation provides also two more attributes:
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    @Query(named = Person.BY_MIN_AGE, max = 10, lock = LockModeType.PESSIMISTIC_WRITE)
+    List<Person> findAllForUpdate(int minAge);
+
+}
+----
+
+[options="header"]
+|=======
+|Name  |Description
+|max   |Limits the number of results.
+|lock  |Use a specific LockModeType to execute the query.
+|=======
+
+Note that these options can also be applied to method expressions.
+
+==== Query Options
+
+All the query options you have seen so far are more or less static. But sometimes you might want
+to apply certain query options dynamically. For example, sorting criteria could come from a user
+selection so they cannot be known beforehand. DeltaSpike allows you to apply query options at runtime by
+using the +QueryResult+ result type:
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    @Query("select p from Person p where p.age between ?1 and ?2")
+    QueryResult<Person> findAllByAge(int minAge, int maxAge);
+
+}
+----
+
+Once you have obtained a +QueryResult+, you can apply further options to the query:
+
+[source,java]
+----
+List<Person> result = personRepository.findAllByAge(18, 65)
+    .sortAsc(Person_.lastName)
+    .sortDesc(Person_.age)
+    .lockMode(LockModeType.WRITE)
+    .hint("org.hibernate.timeout", Integer.valueOf(10))
+    .getResultList(); 
+----
+
+CAUTION: Note that sorting is only applicable to method expressions or non-named queries. For named queries it might be possible, but is currently only supported for Hibernate, EclipseLink and OpenJPA.
+
+Note that the +QueryResult+ return type can also be used with method expressions.
+
+==== Pagination
+
+We introduced the +QueryResult+ type in the last chapter, which can also be used for pagination:
+
+[source,java]
+----
+// Query API style
+QueryResult<Person> paged = personRepository.findByAge(age)
+    .maxResults(10)
+    .firstResult(50);
+
+// or paging style
+QueryResult<Person> paged = personRepository.findByAge(age)
+    .withPageSize(10) // equivalent to maxResults
+    .toPage(5);
+
+int totalPages = paged.countPages();
+----
+
+==== Bulk Operations
+
+While reading entities and updating them one by one might be fine for many use cases, applying bulk
+updates or deletes is also a common usage scenario for repositories. DeltaSpike supports this with a special
+marking annotation +@Modifying+:
+
+[source,java]
+----
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+    @Modifying
+    @Query("update Person as p set p.classifier = ?1 where p.classifier = ?2")
+    int updateClassifier(Classifier current, Classifier next);
+
+}
+----
+
+Bulk operation query methods can either return void or int, which counts the number of entities affected
+by the bulk operation. 
+
+=== Extensions
+
+==== Query Delegates
+
+While repositories defines several base interfaces, there might still be the odd convenience
+method that is missing. This is actually intentional - things should not get overloaded for each and
+every use case. That's why in DeltaSpike you can define your own reusable methods.
+
+For example, you might want to use the QueryDsl library in your repositories:
+
+[source,java]
+----
+import com.mysema.query.jpa.impl.JPAQuery;
+
+public interface QueryDslSupport
+{
+    JPAQuery jpaQuery();
+}
+
+@Repository(forEntity = Person.class)
+public interface PersonRepository extends QueryDslSupport
+{
+   ...
+}
+----   
+
+==== Implementing the Query Delegate
+
+The first step is to define an interface which contains the extra methods for your repositories
+(as shown above):
+
+[source,java]
+----
+public interface QueryDslSupport
+{
+    JPAQuery jpaQuery();
+}
+----
+
+As a next step, you need to provide an implementation for this interface once. It's also important
+that this implementation implements the +DelegateQueryHandler+ interface (don't worry, this is just
+an empty marker interface):
+
+[source,java]
+----
+public class QueryDslRepositoryExtension<E> implements QueryDslSupport, DelegateQueryHandler
+{
+
+    @Inject
+    private QueryInvocationContext context;
+
+
+    @Override
+    public JPAQuery jpaQuery()
+    {
+        return new JPAQuery(context.getEntityManager());
+    }
+
+}
+----        
+
+As you see in the sample, you can inject a +QueryInvocationContext+ which contains utility methods
+like accessing the current +EntityManager+ and entity class.       
+
+Note that, if you define multiple extensions with equivalent method signatures, there is no specific
+order in which the implementation is selected.
+
+=== JPA Criteria API Support
+
+Beside automatic query generation, the DeltaSpike data module also provides a DSL-like API to create JPA 2 Criteria queries.
+It takes advantage of the JPA 2 meta model, which helps creating type safe queries.
+
+TIP: The JPA meta model can easily be generated with an annotation processor. Hibernate or EclipseLink provide such a processor, which can be integrated into your compile and build cycle.
+
+Note that this criteria API is not intended to replace the standard criteria API - it's rather a utility
+API that should make life easier on the most common cases for a custom query. The JPA criteria API's 
+strongest point is certainly its type safety - which comes at the cost of readability. We're trying to 
+provide a middle way here. A less powerful API, but still type safe and readable.
+
+==== API Usage
+
+The API is centered around the Criteria class and is targeted to provide a fluent interface
+to write criteria queries:
+
+[source,java]
+----
+@Repository(forEntity = Person.class)
+public abstract class PersonRepository implements CriteriaSupport<Person>
+{
+
+    public List<Person> findAdultFamilyMembers(String name, Integer minAge)
+    {
+        return criteria()
+                .like(Person_.name, "%" + name + "%")
+                .gtOrEq(Person_.age, minAge)
+                .eq(Person_.validated, Boolean.TRUE)
+                .orderDesc(Person_.age)
+                .getResultList();
+    }
+
+}
+----
+
+Following comparators are supported by the API:
+
+[options="header"]
+|=======================
+|Name                    |Description
+|.eq(..., ...)           |Property value must be equal to the given value   
+|.in(..., ..., ..., ...) |Property value must be in one of the given values.
+|.notEq(..., ...)        |Negates equality
+|.like(..., ...)         |A SQL +like+ equivalent comparator. Use % on the value.
+|.notLike(..., ...)      |Negates the like value
+|.lt(..., ...)           |Property value must be less than the given value.
+|.ltOrEq(..., ...)       |Property value must be less than or equal to the given value.
+|.gt(..., ...)           |Property value must be greater than the given value.
+|.gtOrEq(..., ...)       |Property value must be greater than or equal to the given value.
+|.between(..., ..., ...) |Property value must be between the two given values.
+|.isNull(...)            |Property must be +null+
+|.isNotNull(...)         |Property must be non-null
+|.isEmpty(...)           |Collection property must be empty
+|.isNotEmpty(...)        |Collection property must be non-empty
+|=======================
+
+The query result can be modified with the following settings:
+
+[options="header"]
+|=======================
+|Name            |Description
+|.orderAsc(...)  |Sorts the result ascending by the given property. Note that this can be applied to several properties
+|.orderDesc(...) |Sorts the result descending by the given property. Note that this can be applied to several properties
+|.distinct()     |Sets distinct to true on the query.
+|=======================
+
+Once all comparators and query options are applied, the +createQuery()+ method is called. 
+This creates a JPA TypedQuery object for the repository entity. If required, further processing can be applied here.
+
+==== Joins
+
+For simple cases, restricting on the repository entity only works out fine, but once the data model
+gets more complicated, the query will have to consider relations to other entities. The module's criteria
+API therefore supports joins as shown in the sample below:
+
+[source,java]
+----
+@Repository
+public abstract class PersonRepository extends AbstractEntityRepository<Person, Long>
+{
+
+    public List<Person> findByCompanyName(String companyName)
+    {
+        return criteria()
+                .join(Person_.company,
+                    where(Company.class)
+                        .eq(Company_.name, companyName)
+                )
+                .eq(Person_.validated, Boolean.TRUE)
+                .getResultList();
+    }
+
+}
+----
+
+Beside the inner and outer joins, also fetch joins are supported. Those are slighly simpler as seen in the next sample:
+
+[source,java]
+----
+public abstract class PersonRepository extends AbstractEntityRepository<Person, Long>
+{
+
+    public Person findBySSN(String ssn)
+    {
+        return criteria()
+                .fetch(Person_.familyMembers)
+                .eq(Person_.ssn, ssn)
+                .distinct()
+                .getSingleResult();
+    }
+
+}
+----
+
+==== Boolean Operators
+
+By default, all query operators are concatenated as an and conjunction to the query. The DeltaSpike
+criteria API also allows to add groups of disjunctions.
+
+[source,java]
+----
+public abstract class PersonRepository extends AbstractEntityRepository<Person, Long>
+{
+
+    public List<Person> findAdults()
+    {
+        return criteria()
+                .or(
+                    criteria().
+                        .gtOrEq(Person_.age, 18)
+                        .eq(Person_.origin, Country.SWITZERLAND),
+                    criteria().
+                        .gtOrEq(Person_.age, 21)
+                        .eq(Person_.origin, Country.USA)
+                )
+                .getResultList();
+    }
+
+}
+----
+
+==== Selections
+
+It might not always be appropriate to retrieve full entities - you might also be interested
+in scalar values or by modified entity attributes. The Criteria interface allows this with the
+selection method:
+
+[source,java]
+----
+public abstract class PersonRepository extends AbstractEntityRepository<Person, Long>
+{
+
+    public Statistics ageStatsFor(Segment segment)
+    {
+        return criteria()
+                 .select(Statistics.class, avg(Person_.age), min(Person_.age), max(Person_.age))
+                 .eq(Person_.segment, segment)
+                 .getSingleResult();
+    }
+
+    public List<Object[]> personViewForFamily(String name)
+    {
+        return criteria()
+                 .select(upper(Person_.name), attribute(Person_.age), substring(Person_.firstname, 1))
+                 .like(Person_.name, name)
+                 .getResultList();
+    }
+
+}
+----
+
+There are also several functions supported which can be used in the selection clause:
+
+[options="header"]
+|=======================
+|Name                             |Description
+|abs(...)                         |Absolute value. Applicable to Number attributes.
+|avg(...)                         |Average value. Applicable to Number attributes.
+|count(...)                       |Count function. Applicable to Number attributes.
+|max(...)                         |Max value. Applicable to Number attributes.
+|min(...)                         |Min value. Applicable to Number attributes.
+|modulo(...)                      |Modulo function. Applicable to Integer attributes.
+|neg(...)                         |Negative value. Applicable to Number attributes.
+|sum(...)                         |Sum function. Applicable to Number attributes.
+|lower(...)                       |String to lowercase. Applicable to String attributes.
+|substring(int from, ...)         |Substring starting from. Applicable to String attributes.
+|substring(int from, int to, ...) |Substring starting from ending to. Applicable to String attributes.
+|upper(...)                       |String to uppercase. Applicable to String attributes.
+|currDate()                       |The DB sysdate. Returns a Date object.
+|currTime()                       |The DB sysdate. Returns a Time object.
+|currTStamp()                     |The DB sysdate. Returns a Timestamp object. 
+|=======================
+
+=== Auditing
+
+A common requirement for entities is tracking what is being done with them. DeltaSpike provides
+a convenient way to support this requirement.
+
+TIP: DeltaSpike does not support creating revisions of entities. If this is a requirement for your audits, have a look at Hibernate Envers.
+
+==== Activating Auditing
+
+DeltaSpike uses an entity listener to update auditing data before entities get created or update.
+The entity listener must be activated before it can be used. This can either be done globally for
+all entities of a persistent unit or per entity.
+
+Activation per persistence unit in +orm.xml+:
+
+[source,xml]
+----
+<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd" version="2.0">
+    <persistence-unit-metadata>
+        <persistence-unit-defaults>
+            <entity-listeners>
+                <entity-listener class="org.apache.deltaspike.data.impl.audit.AuditEntityListener" />
+            </entity-listeners>
+        </persistence-unit-defaults>
+    </persistence-unit-metadata>
+</entity-mappings>
+----
+
+Activation per entity:
+
+[source,java]
+----
+@Entity
+@EntityListeners(AuditEntityListener.class)
+public class AuditedEntity
+{
+
+    ...
+
+}
+---- 
+
+==== Using Auditing Annotations
+
+All that has to be done now is annotating the entity properties which are used to audit the entity.
+
+===== Updating Timestamps
+
+To keep track on creation and modification times, following annotations can be used:
+
+[source,java]
+----
+@Entity
+public class AuditedEntity
+{
+
+    ...
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @CreatedOn
+    private Date created;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @ModifiedOn
+    private Date updated;
+
+    ...
+
+}
+----
+
+In case the modification date should also be set during entity creation, the annotation can be customized:
+
+[source,java]
+----
+@ModifiedOn(setOnCreate=true)
+----
+
+===== Who's Changing My Entities?
+
+Beside keeping track of when a change has happened, it's also often critical to track who's responsible
+for the change. Annotate a user tracking field with the following annotation:
+
+[source,java]
+----
+@Entity
+public class AuditedEntity
+{
+
+    ...
+
+    @ModifiedBy
+    private String auditUser;
+
+    ... 
+
+}
+----
+
+Now a little help is needed. The entity listener needs to be able to resolve the current user -
+there must be a bean available of the matching type for the annotation property, exposed over a special CDI qualifier:
+
+[source,java]
+----
+public class UserProvider
+{
+
+    @Inject
+    private User user;
+
+    @Produces @CurrentUser
+    public String currentUser() {
+        return user.getUsername();
+    }
+
+    ... 
+
+}
+----        
+
+TIP: The JPA Spec does not recommend to modify entity relations from within a lifecycle callback. If you expose another entity here, make sure that your persistence provider supports this. Also you should ensure that the entity is attached to a persistent context. Also, be aware that the CDI container will proxy a scoped bean, which might confuse the persistence provider when persisting / updating the target entity.
+

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/pom.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/pom.xml b/deltaspike/modules/data/api/pom.xml
new file mode 100755
index 0000000..9e20112
--- /dev/null
+++ b/deltaspike/modules/data/api/pom.xml
@@ -0,0 +1,95 @@
+<?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.
+-->
+<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/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    
+    <parent>
+        <groupId>org.apache.deltaspike.modules</groupId>
+        <artifactId>data-module-project</artifactId>
+        <version>0.5-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>deltaspike-data-module-api</artifactId>
+    <packaging>bundle</packaging>
+
+    <name>Apache DeltaSpike Data-Module API</name>
+
+    <prerequisites>
+        <maven>3.0</maven>
+    </prerequisites>
+    
+    <properties>
+        <deltaspike.osgi.export.pkg>
+            org.apache.deltaspike.data.*
+        </deltaspike.osgi.export.pkg>
+        <deltaspike.osgi.import>
+            !org.apache.deltaspike.data.*,
+            *
+        </deltaspike.osgi.import>
+        <cdi.osgi.beans-managed>META-INF/beans.xml</cdi.osgi.beans-managed>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.spec.javax.ejb</groupId>
+            <artifactId>jboss-ejb-api_3.1_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.apache.deltaspike.core</groupId>
+            <artifactId>deltaspike-core-api</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.apache.deltaspike.modules</groupId>
+            <artifactId>deltaspike-partial-bean-module-api</artifactId>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!-- no test phase for API module -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/AbstractEntityRepository.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/AbstractEntityRepository.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/AbstractEntityRepository.java
new file mode 100755
index 0000000..94e99f9
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/AbstractEntityRepository.java
@@ -0,0 +1,61 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.io.Serializable;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaQuery;
+
+
+/**
+ * Base Repository class to be extended by concrete implementations
+ * (abstract classes with implementation methods).
+ * @author thomashug
+ *
+ * @param <E>   Entity type.
+ * @param <PK>  Primary key type.
+ */
+@Repository
+public abstract class AbstractEntityRepository<E, PK extends Serializable>
+        implements EntityRepository<E, PK>
+{
+
+    /**
+     * Utility method to get hold of the entity manager for this Repository.
+     * This method can be overridden and decorated with qualifiers. If done, the qualifiers
+     * will be used to resolve a specific entity manager other than the default one.
+     *
+     * @return          Entity manager instance.
+     */
+    protected abstract EntityManager entityManager();
+
+    /**
+     * Utility method to create a criteria query.
+     * @return          Criteria query
+     */
+    protected abstract CriteriaQuery<E> criteriaQuery();
+
+    /**
+     * Get the entity class this Repository is related to.
+     * @return          Repository entity class.
+     */
+    protected abstract Class<E> entityClass();
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerConfig.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerConfig.java
new file mode 100644
index 0000000..74570dc
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerConfig.java
@@ -0,0 +1,51 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.persistence.FlushModeType;
+
+/**
+ * Configure the EntityManager for a specific repository.
+ * @author thomashug
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EntityManagerConfig
+{
+    /**
+     * References the type which provides the EntityManager for a specific repository.
+     * Must be resolvable over the BeanManager.
+     */
+    Class<? extends EntityManagerResolver> entityManagerResolver() default EntityManagerResolver.class;
+
+    /**
+     * Set the flush mode for the repository EntityManager.
+     */
+    FlushModeType flushMode() default FlushModeType.AUTO;
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerResolver.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerResolver.java
new file mode 100644
index 0000000..bc99e02
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityManagerResolver.java
@@ -0,0 +1,34 @@
+/*
+ * 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.deltaspike.data.api;
+
+import javax.persistence.EntityManager;
+
+/**
+ * Resolve the EntityManager used for a specific repository.
+ * Only necessary if there are more than one persistence unit.
+ *
+ * @author thomashug
+ */
+public interface EntityManagerResolver
+{
+
+    EntityManager resolveEntityManager();
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityRepository.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityRepository.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityRepository.java
new file mode 100755
index 0000000..b7f56f5
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/EntityRepository.java
@@ -0,0 +1,167 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.metamodel.SingularAttribute;
+
+/**
+ * Base Repository interface. All methods are implemented by the query extension.
+ * @author thomashug
+ *
+ * @param <E>   Entity type.
+ * @param <PK>  Primary key type.
+ */
+public interface EntityRepository<E, PK extends Serializable>
+{
+
+    /**
+     * Persist (new entity) or merge the given entity.
+     * @param entity            Entity to save.
+     * @return                  Returns the modified entity.
+     */
+    E save(E entity);
+
+    /**
+     * {@link #save(Object)}s the given entity and flushes the persistence context afterwards.
+     * @param entity            Entity to save.
+     * @return                  Returns the modified entity.
+     */
+    E saveAndFlush(E entity);
+
+    /**
+     * {@link #save(Object)}s the given entity and flushes the persistence context afterwards,
+     * followed by a refresh (e.g. to load DB trigger modifications).
+     * @param entity            Entity to save.
+     * @return                  Returns the modified entity.
+     */
+    E saveAndFlushAndRefresh(E entity);
+
+    /**
+     * Convenience access to {@link javax.persistence.EntityManager#remove(Object)}.
+     * @param entity            Entity to remove.
+     */
+    void remove(E entity);
+
+    /**
+     * Convenience access to {@link javax.persistence.EntityManager#remove(Object)}
+     * with a following flush.
+     * @param entity            Entity to remove.
+     */
+    void removeAndFlush(E entity);
+
+    /**
+     * Convenience access to {@link javax.persistence.EntityManager#refresh(Object)}.
+     * @param entity            Entity to refresh.
+     */
+    void refresh(E entity);
+
+    /**
+     * Convenience access to {@link javax.persistence.EntityManager#flush()}.
+     */
+    void flush();
+
+    /**
+     * Entity lookup by primary key. Convenicence method around
+     * {@link javax.persistence.EntityManager#find(Class, Object)}.
+     * @param primaryKey        DB primary key.
+     * @return                  Entity identified by primary or null if it does not exist.
+     */
+    E findBy(PK primaryKey);
+
+    /**
+     * Lookup all existing entities of entity class {@code <E>}.
+     * @return                  List of entities, empty if none found.
+     */
+    List<E> findAll();
+
+    /**
+     * Lookup a range of existing entities of entity class {@code <E>} with support for pagination.
+     * @param start             The starting position.
+     * @param max               The maximum number of results to return
+     * @return                  List of entities, empty if none found.
+     */
+    List<E> findAll(int start, int max);
+
+    /**
+     * Query by example - for a given object and a specific set of properties.
+     * @param example           Sample entity. Query all like.
+     * @param attributes        Which attributes to consider for the query.
+     * @return                  List of entities matching the example, or empty if none found.
+     */
+    List<E> findBy(E example, SingularAttribute<E, ?>... attributes);
+
+    /**
+     * Query by example - for a given object and a specific set of properties with support for pagination.
+     * @param example           Sample entity. Query all like.
+     * @param start             The starting position.
+     * @param max               The maximum number of results to return
+     * @param attributes        Which attributes to consider for the query.
+     * @return                  List of entities matching the example, or empty if none found.
+     */
+    List<E> findBy(E example, int start, int max, SingularAttribute<E, ?>... attributes);
+
+    /**
+     * Query by example - for a given object and a specific set of properties using a like operator for Strings.
+     * @param example           Sample entity. Query all like.
+     * @param attributes        Which attributes to consider for the query.
+     * @return                  List of entities matching the example, or empty if none found.
+     */
+    List<E> findByLike(E example, SingularAttribute<E, ?>... attributes);
+
+    /**
+     * Query by example - for a given object and a specific set of properties
+     * using a like operator for Strings with support for pagination.
+     * @param example           Sample entity. Query all like.
+     * @param start             The starting position.
+     * @param max               The maximum number of results to return
+     * @param attributes        Which attributes to consider for the query.
+     * @return                  List of entities matching the example, or empty if none found.
+     */
+    List<E> findByLike(E example, int start, int max, SingularAttribute<E, ?>... attributes);
+
+    /**
+     * Count all existing entities of entity class {@code <E>}.
+     * @return                  Counter.
+     */
+    Long count();
+
+    /**
+     * Count existing entities of entity class {@code <E>}
+     * with for a given object and a specific set of properties..
+     * @param example           Sample entity. Query all like.
+     * @param attributes        Which attributes to consider for the query.
+     *
+     * @return                  Counter.
+     */
+    Long count(E example, SingularAttribute<E, ?>... attributes);
+
+    /**
+     * Count existing entities of entity class using the like operator for String attributes {@code <E>}
+     * with for a given object and a specific set of properties..
+     * @param example           Sample entity. Query all like.
+     * @param attributes        Which attributes to consider for the query.
+     *
+     * @return                  Counter.
+     */
+    Long countLike(E example, SingularAttribute<E, ?>... attributes);
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/FirstResult.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/FirstResult.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/FirstResult.java
new file mode 100644
index 0000000..5c88e2e
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/FirstResult.java
@@ -0,0 +1,35 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use paging for the query. Must be applied to an Integer parameter.
+ * @author thomashug
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface FirstResult
+{
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/MaxResults.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/MaxResults.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/MaxResults.java
new file mode 100644
index 0000000..40f563a
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/MaxResults.java
@@ -0,0 +1,34 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Limit the size of the result set. Must be applied to an Integer parameter.
+ * @author thomashug
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface MaxResults
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Modifying.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Modifying.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Modifying.java
new file mode 100644
index 0000000..eddb137
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Modifying.java
@@ -0,0 +1,37 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a query method to be modifying. This will execute the
+ * {@link javax.persistence.Query#executeUpdate()} method instead of
+ * {@link javax.persistence.Query#getResultList()} (or the corresponding single result method).
+ *
+ * @author thomashug
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Modifying
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java
new file mode 100755
index 0000000..7098116
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java
@@ -0,0 +1,76 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.persistence.LockModeType;
+import javax.persistence.QueryHint;
+
+/**
+ * Supply query meta data to a method with this annotation.<br/>
+ * Currently supports:
+ * <ul><li>JPQL queries as part of the annotation value</li>
+ * <li>Execute named queries referenced by the named value</li>
+ * <li>Execute native SQL queries</li>
+ * <li>Restrict the result size to a static value</li>
+ * <li>Provide a lock mode</li></ul>
+ * @author thomashug
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Query
+{
+
+    /**
+     * Defines the Query to execute. Can be left empty for method expression queries
+     * or when referencing a {@link #named()} query.
+     */
+    String value() default "";
+
+    /**
+     * References a named query.
+     */
+    String named() default "";
+
+    /**
+     * Defines a native SQL query.
+     */
+    boolean isNative() default false;
+
+    /**
+     * Limits the number of results the query returns.
+     */
+    int max() default 0;
+
+    /**
+     * Defines a lock mode for the query.
+     */
+    LockModeType lock() default LockModeType.NONE;
+
+    /**
+     * (Optional) Query properties and hints.  May include vendor-specific query hints.
+     */
+    QueryHint[] hints() default {
+    };
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryParam.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryParam.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryParam.java
new file mode 100644
index 0000000..c196c0c
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryParam.java
@@ -0,0 +1,37 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a method parameter as a query parameter.
+ * Can be named by the annotation value.
+ *
+ * @author thomashug
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface QueryParam
+{
+    String value() default "";
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java
new file mode 100644
index 0000000..be6281c
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java
@@ -0,0 +1,207 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.util.List;
+
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
+import javax.persistence.metamodel.SingularAttribute;
+
+/**
+ * Can be used as query result type, which will not execute the query immediately.
+ * Allows some post processing like defining query ordering.
+ *
+ * @author thomashug
+ * @param <E> Entity type
+ */
+public interface QueryResult<E>
+{
+
+    /**
+     * Sort the query result ascending by the given entity singular attribute.
+     * This is the typesafe version, alternatively a {@link #orderAsc(String)}
+     * String can be used.
+     *
+     * @param attribute         Sort attribute.
+     * @return                  Fluent API: the result instance.
+     */
+    <X> QueryResult<E> orderAsc(SingularAttribute<E, X> attribute);
+
+    /**
+     * Sort the query result ascending by the given entity attribute.
+     *
+     * @param attribute         Sort attribute.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> orderAsc(String attribute);
+
+    /**
+     * Sort the query result descending by the given entity singular attribute.
+     * This is the typesafe version, alternatively a {@link #orderDesc(String)}
+     * String can be used.
+     *
+     * @param attribute         Sort attribute.
+     * @return                  Fluent API: the result instance.
+     */
+    <X> QueryResult<E> orderDesc(SingularAttribute<E, X> attribute);
+
+    /**
+     * Sort the query result descending by the given entity attribute.
+     *
+     * @param attribute         Sort attribute.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> orderDesc(String attribute);
+
+    /**
+     * Revert an existing order attribute sort direction. Defaults to ascending
+     * order if the sort attribute was not used before.
+     *
+     * @param attribute         Sort attribute.
+     * @return                  Fluent API: the result instance.
+     */
+    <X> QueryResult<E> changeOrder(SingularAttribute<E, X> attribute);
+
+    /**
+     * Remove any ordering from the query result object.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> clearOrder();
+
+    /**
+     * Revert an existing order attribute sort direction. Defaults to ascending
+     * order if the sort attribute was not used before.
+     *
+     * @param attribute         Sort attribute.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> changeOrder(String attribute);
+
+    /**
+     * Limit the number of results returned by the query.
+     *
+     * @param max               Max number of results.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> maxResults(int max);
+
+    /**
+     * Pagination: Set the result start position.
+     *
+     * @param first             Result start position.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> firstResult(int first);
+
+    /**
+     * Sets the query lock mode.
+     *
+     * @param lockMode          Query lock mode to use in the query.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> lockMode(LockModeType lockMode);
+
+    /**
+     * Sets the query flush mode.
+     *
+     * @param flushMode         Query flush mode to use in the query.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> flushMode(FlushModeType flushMode);
+
+    /**
+     * Apply a query hint to the query to execute.
+     *
+     * @param hint              Hint name.
+     * @param value             Hint value.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> hint(String hint, Object value);
+
+    /**
+     * Fetch the result set.
+     *
+     * @return                  List of entities retrieved by the query.
+     */
+    List<E> getResultList();
+
+    /**
+     * Fetch a single result entity.
+     *
+     * @return                  Entity retrieved by the query.
+     */
+    E getSingleResult();
+
+    /**
+     * Count the result set.
+     * @return                  Result count.
+     */
+    long count();
+
+    /**
+     * Set a page size on the query result. Defaults to 10 or takes the value of a
+     * previous {@link #maxResults(int)} call.
+     *
+     * @param pageSize          Page size for further queries.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> withPageSize(int pageSize);
+
+    /**
+     * Move the page cursor to a specific page.
+     *
+     * @param page              Page to move to for the next query.
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> toPage(int page);
+
+    /**
+     * Move to the next page.
+     *
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> nextPage();
+
+    /**
+     * Move to the previous page.
+     *
+     * @return                  Fluent API: the result instance.
+     */
+    QueryResult<E> previousPage();
+
+    /**
+     * Count the number of pages.
+     * @return                  Page count.
+     */
+    int countPages();
+
+    /**
+     * Return the actual page.
+     * @return                  Page position.
+     */
+    int currentPage();
+
+    /**
+     * Return the actual page size.
+     * @return                  Page size.
+     */
+    int pageSize();
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java
new file mode 100755
index 0000000..8cc6a06
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java
@@ -0,0 +1,54 @@
+/*
+ * 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.deltaspike.data.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.deltaspike.partialbean.api.PartialBeanBinding;
+
+/**
+ * The Repository annotation needs to be present in order to have the
+ * interface or class to be processed by the CDI extension.
+ *
+ * @author thomashug
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Inherited
+@PartialBeanBinding
+public @interface Repository
+{
+    /**
+     * Relates the repository to a specific Entity. Can be left to
+     * default when the Entity is determined by one of the base
+     * repository classes.
+     */
+    Class<?> forEntity() default Object.class;
+
+    /**
+     * The method prefix for method expressions. Can be adapted to
+     * domain specific conventions.
+     */
+    String methodPrefix() default "findBy";
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CreatedOn.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CreatedOn.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CreatedOn.java
new file mode 100644
index 0000000..9a9406d
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CreatedOn.java
@@ -0,0 +1,33 @@
+/*
+ * 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.deltaspike.data.api.audit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a property which should be updated with a timestamp when the entity gets persisted.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.METHOD })
+public @interface CreatedOn
+{
+}