From f43b662e6c83a8a98b5946d22cb6e513756860ef Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 23 Aug 2023 10:35:41 +0200 Subject: [PATCH] Migrate documentation site to Antora. Closes #425 --- .gitignore | 4 + pom.xml | 45 +-- src/main/antora/antora-playbook.yml | 42 +++ src/main/antora/antora.yml | 12 + src/main/antora/modules/ROOT/nav.adoc | 22 ++ .../modules/ROOT/pages/commons/upgrade.adoc | 1 + src/main/antora/modules/ROOT/pages/index.adoc | 20 ++ src/main/antora/modules/ROOT/pages/ldap.adoc | 8 + .../ROOT/pages/ldap/cdi-integration.adoc | 38 +++ .../ROOT/pages/ldap/configuration.adoc | 119 ++++++++ .../ROOT/pages/ldap/query-methods.adoc | 78 +++++ .../modules/ROOT/pages/ldap/querydsl.adoc | 9 + .../antora/modules/ROOT/pages/ldap/usage.adoc | 78 +++++ .../pages/repositories/core-concepts.adoc | 1 + .../repositories/core-domain-events.adoc | 1 + .../pages/repositories/core-extensions.adoc | 1 + .../pages/repositories/create-instances.adoc | 1 + .../repositories/custom-implementations.adoc | 1 + .../ROOT/pages/repositories/definition.adoc | 1 + .../ROOT/pages/repositories/introduction.adoc | 8 + .../repositories/namespace-reference.adoc | 1 + .../pages/repositories/null-handling.adoc | 1 + .../ROOT/pages/repositories/projections.adoc | 4 + .../query-keywords-reference.adoc | 1 + .../repositories/query-methods-details.adoc | 1 + .../query-return-types-reference.adoc | 1 + .../resources/antora-resources/antora.yml | 21 ++ src/main/asciidoc/images/epub-cover.png | Bin 39939 -> 0 bytes src/main/asciidoc/images/epub-cover.svg | 11 - src/main/asciidoc/index.adoc | 31 -- src/main/asciidoc/preface.adoc | 69 ----- .../asciidoc/reference/ldap-repositories.adoc | 274 ------------------ 32 files changed, 500 insertions(+), 405 deletions(-) create mode 100644 src/main/antora/antora-playbook.yml create mode 100644 src/main/antora/antora.yml create mode 100644 src/main/antora/modules/ROOT/nav.adoc create mode 100644 src/main/antora/modules/ROOT/pages/commons/upgrade.adoc create mode 100644 src/main/antora/modules/ROOT/pages/index.adoc create mode 100644 src/main/antora/modules/ROOT/pages/ldap.adoc create mode 100644 src/main/antora/modules/ROOT/pages/ldap/cdi-integration.adoc create mode 100644 src/main/antora/modules/ROOT/pages/ldap/configuration.adoc create mode 100644 src/main/antora/modules/ROOT/pages/ldap/query-methods.adoc create mode 100644 src/main/antora/modules/ROOT/pages/ldap/querydsl.adoc create mode 100644 src/main/antora/modules/ROOT/pages/ldap/usage.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/definition.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/introduction.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/namespace-reference.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/projections.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc create mode 100644 src/main/antora/resources/antora-resources/antora.yml delete mode 100644 src/main/asciidoc/images/epub-cover.png delete mode 100644 src/main/asciidoc/images/epub-cover.svg delete mode 100644 src/main/asciidoc/index.adoc delete mode 100644 src/main/asciidoc/preface.adoc delete mode 100644 src/main/asciidoc/reference/ldap-repositories.adoc diff --git a/.gitignore b/.gitignore index 3b34d16..1455ce3 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,7 @@ src/ant/.ant-targets-upload-dist.xml atlassian-ide-plugin.xml /.gradle/ /.idea/ +package.json +package-lock.json +node +node_modules diff --git a/pom.xml b/pom.xml index 17b47bb..6a67fa1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 @@ -134,25 +135,6 @@ org.apache.maven.plugins maven-assembly-plugin - - org.asciidoctor - asciidoctor-maven-plugin - - - ${project.version} - ${project.name} - ${project.version} - ${aspectj} - ${querydsl} - ${spring} - ${releasetrain} - ${spring-ldap} - true - 3 - true - - - @@ -163,6 +145,29 @@ 2.3.2.BUILD-SNAPSHOT + + antora + + + + io.spring.maven.antora + antora-maven-plugin + + + + + + + antora-process-resources + + + + src/main/antora/resources/antora-resources + true + + + + diff --git a/src/main/antora/antora-playbook.yml b/src/main/antora/antora-playbook.yml new file mode 100644 index 0000000..abb3c87 --- /dev/null +++ b/src/main/antora/antora-playbook.yml @@ -0,0 +1,42 @@ +# PACKAGES antora@3.2.0-alpha.2 @antora/atlas-extension:1.0.0-alpha.1 @antora/collector-extension@1.0.0-alpha.3 @springio/antora-extensions@1.1.0-alpha.2 @asciidoctor/tabs@1.0.0-alpha.12 @opendevise/antora-release-line-extension@1.0.0-alpha.2 +# +# The purpose of this Antora playbook is to build the docs in the current branch. +antora: + extensions: + - '@antora/collector-extension' + - require: '@springio/antora-extensions/root-component-extension' + root_component_name: 'data-ldap' +site: + title: Spring Data LDAP + url: https://docs.spring.io/spring-data-ldap/reference/ +content: + sources: + - url: ./../../.. + branches: HEAD + start_path: src/main/antora + worktrees: true + - url: https://github.com/spring-projects/spring-data-commons + # Refname matching: + # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ + branches: [ main, 3.2.x ] + start_path: src/main/antora +asciidoc: + attributes: + page-pagination: '' + hide-uri-scheme: '@' + tabs-sync-option: '@' + chomp: 'all' + extensions: + - '@asciidoctor/tabs' + - '@springio/asciidoctor-extensions' + sourcemap: true +urls: + latest_version_segment: '' +runtime: + log: + failure_level: warn + format: pretty +ui: + bundle: + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.3/ui-bundle.zip + snapshot: true diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml new file mode 100644 index 0000000..5cb8796 --- /dev/null +++ b/src/main/antora/antora.yml @@ -0,0 +1,12 @@ +name: data-ldap +version: true +title: Spring Data LDAP +nav: + - modules/ROOT/nav.adoc +ext: + collector: + - run: + command: ./mvnw validate process-resources -am -Pantora-process-resources + local: true + scan: + dir: target/classes/ diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc new file mode 100644 index 0000000..5d3922f --- /dev/null +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -0,0 +1,22 @@ +* xref:index.adoc[Overview] +** xref:commons/upgrade.adoc[] +* xref:repositories/introduction.adoc[] +** xref:repositories/core-concepts.adoc[] +** xref:repositories/definition.adoc[] +** xref:repositories/create-instances.adoc[] +** xref:repositories/query-methods-details.adoc[] +** xref:repositories/projections.adoc[] +** xref:repositories/custom-implementations.adoc[] +** xref:repositories/core-domain-events.adoc[] +** xref:repositories/core-extensions.adoc[] +** xref:repositories/null-handling.adoc[] +** xref:repositories/namespace-reference.adoc[] +** xref:repositories/query-keywords-reference.adoc[] +** xref:repositories/query-return-types-reference.adoc[] +* xref:ldap.adoc[] +** xref:ldap/configuration.adoc[] +** xref:ldap/usage.adoc[] +** xref:ldap/query-methods.adoc[] +** xref:ldap/querydsl.adoc[] +** xref:ldap/cdi-integration.adoc[] +* https://github.com/spring-projects/spring-data-commons/wiki[Wiki] diff --git a/src/main/antora/modules/ROOT/pages/commons/upgrade.adoc b/src/main/antora/modules/ROOT/pages/commons/upgrade.adoc new file mode 100644 index 0000000..51a9189 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/commons/upgrade.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$upgrade.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/index.adoc b/src/main/antora/modules/ROOT/pages/index.adoc new file mode 100644 index 0000000..6761b46 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/index.adoc @@ -0,0 +1,20 @@ +[[spring-data-ldap-reference-documentation]] += Spring Data LDAP +:revnumber: {version} +:revdate: {localdate} +:feature-scroll: true + +_Spring Data LDAP provides repository support for Lightweight Directory Access Protocol (LDAP). +It eases development of applications with a consistent programming model that need to access LDAP data sources._ + +[horizontal] +xref:repositories/introduction.adoc[Introduction] :: Introduction to Spring Data Repositories +xref:ldap.adoc[LDAP] :: LDAP and LDAP Repositories +https://github.com/spring-projects/spring-data-commons/wiki[Wiki] :: What's New, Upgrade Notes, Supported Versions, additional cross-version information. + +Mattias Hellborg Arthursson, Ulrik Sandberg, Eric Dalquist, Keith Barlow, Rob Winch, Mark Paluch, Jay Bryant + +(C) 2008-2023 VMware, Inc. + +Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically. + diff --git a/src/main/antora/modules/ROOT/pages/ldap.adoc b/src/main/antora/modules/ROOT/pages/ldap.adoc new file mode 100644 index 0000000..c804f57 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/ldap.adoc @@ -0,0 +1,8 @@ +[[ldap.repositories]] += LDAP Repositories +:page-section-summary-toc: 1 + +This chapter points out the specialties for repository support for LDAP. +It builds on the core repository support explained in xref:repositories/introduction.adoc[Working with Spring Data Repositories]. +You should have a sound understanding of the basic concepts explained there. + diff --git a/src/main/antora/modules/ROOT/pages/ldap/cdi-integration.adoc b/src/main/antora/modules/ROOT/pages/ldap/cdi-integration.adoc new file mode 100644 index 0000000..c904965 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/ldap/cdi-integration.adoc @@ -0,0 +1,38 @@ +[[ldap.repositories.cdi-integration]] += CDI Integration + +Instances of the repository interfaces are usually created by a container, for which Spring is the most natural choice when working with Spring Data. +Spring Data LDAP includes a custom CDI extension that lets you use the repository abstraction in CDI environments. +The extension is part of the JAR. +To activate it, drop the Spring Data LDAP JAR into your classpath. +You can now set up the infrastructure by implementing a CDI Producer for the `LdapTemplate`, as the following example shows: + +[source,java] +---- +class LdapTemplateProducer { + + @Produces + @ApplicationScoped + public LdapOperations createLdapTemplate() { + + ContextSource contextSource = … + return new LdapTemplate(contextSource); + } +} +---- + +The Spring Data LDAP CDI extension picks up the `LdapTemplate` as a CDI bean and creates a proxy for a Spring Data repository whenever a bean of a repository type is requested by the container. +Thus, obtaining an instance of a Spring Data repository is a matter of declaring an injected property, as the following example shows: + +[source,java] +---- +class RepositoryClient { + + @Inject + PersonRepository repository; + + public void businessMethod() { + List people = repository.findAll(); + } +} +---- diff --git a/src/main/antora/modules/ROOT/pages/ldap/configuration.adoc b/src/main/antora/modules/ROOT/pages/ldap/configuration.adoc new file mode 100644 index 0000000..0307310 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/ldap/configuration.adoc @@ -0,0 +1,119 @@ +[[ldap.configuration]] += Configuration + +This section describes configuring Spring Data LDAP. +Spring LDAP repositories can be enabled by using a `` tag in your XML configuration or by using an `@EnableLdapRepositories` annotation on a configuration class: + +* "`<>`" (XML configuration) +* "`<>`" (Java configuration) + +To include support for `LdapQuery` parameters in automatically generated repositories, have your interface extend `LdapRepository` rather than `CrudRepository`. + +All Spring LDAP repositories must work with entities annotated with the ODM annotations, as described in https://docs.spring.io/spring-ldap/reference/odm.html[Object-Directory Mapping]. + +Since all ODM managed classes must have a Distinguished Name as the ID, all Spring LDAP repositories must have the ID type parameter set to `javax.naming.Name`. + +Indeed, the built-in `LdapRepository` only takes one type parameter: the managed entity class, which defaults the ID to `javax.naming.Name`. + +Due to specifics of the LDAP protocol, paging and sorting are not supported for Spring LDAP repositories. + +NOTE: You must use ODM annotations, such as `org.springframework.ldap.odm.annotations.Id`. +Using Spring Data's annotation does not work, because Spring LDAP uses its own mapping layer. + +[[ldap.java-config]] +== Annotation-based Configuration + +The Spring Data LDAP repositories support can be activated through both JavaConfig as well as a custom XML namespace, as shown in the following example: + +.Spring Data LDAP repositories using JavaConfig +==== +[source,java] +---- +@Configuration +@EnableLdapRepositories("com.acme.*.repositories") +class MyConfig { + + @Bean + ContextSource contextSource() { + + LdapContextSource ldapContextSource = new LdapContextSource(); + + ldapContextSource.setUserDn("cn=Admin"); + ldapContextSource.setPassword("secret"); + ldapContextSource.setUrl("ldap://127.0.0.1:389"); + + return ldapContextSource; + } + + @Bean + LdapTemplate ldapTemplate(ContextSource contextSource) { + return new LdapTemplate(contextSource); + } +} +---- +==== + +This configuration causes the base packages to be scanned for interfaces that extend contain LDAP repositories and create Spring beans for each one found. + +If no base package is configured, the infrastructure scans the package of the annotated configuration class. + +[[ldap.namespace]] +== Spring Namespace + +The LDAP module of Spring Data contains a custom namespace that allows defining repository beans. +It also contains certain features and element attributes that are special to LDAP. +Generally, the LDAP repositories can be set up by using the `repositories` element, as shown in the following example: + +.Setting up LDAP repositories by using the namespace +==== +[source,xml] +---- + + + + + + + + + +---- +==== + +This configuration causes the base packages to be scanned for interfaces that extend contain LDAP repositories and create Spring beans for each one found. + +By default, the repositories get an autowired `LdapTemplate` Spring bean that is called `ldapTemplate`, so you only need to configure `ldap-template-ref` explicitly if you deviate from this convention. + +TIP: Which is better, JavaConfig or XML? +XML is how Spring was configured long ago. +In today's era of fast-growing Java, record types, annotations, and more, new projects typically use as much pure Java as possible. +While there is no immediate plan to remove XML support, some of the newest features MAY not be available through XML. + +Using the `repositories` element looks up Spring Data repositories as described in xref:repositories/create-instances.adoc[Creating Repository Instances]. + +[[ldap.namespace.custom-namespace-attributes]] +=== Custom Namespace Attributes + +Beyond the xref:repositories/namespace-reference.adoc[default attributes of the `repositories` element], the LDAP namespace offers additional attributes to let you gain more detailed control over the setup of the repositories: + +.Custom LDAP-specific attributes of the `repositories` element +[options = "autowidth"] +|=============== +|`ldap-template-ref`|Explicitly wire the `LdapTemplate` to be used with the repositories being detected by the `repositories` element. Usually used if multiple `LdapTemplate` beans are used within the application. If not configured, Spring Data automatically looks up the `LdapTemplate` bean with the name `ldapTemplate` in the `ApplicationContext`. +|=============== + +NOTE: Spring Data LDAP requires a `LdapMappingContext` bean named `ldapMappingContext` to be present. +If no such bean is defined, then Spring Data LDAP registers a default instance in the application context. + + diff --git a/src/main/antora/modules/ROOT/pages/ldap/query-methods.adoc b/src/main/antora/modules/ROOT/pages/ldap/query-methods.adoc new file mode 100644 index 0000000..bdc318e --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/ldap/query-methods.adoc @@ -0,0 +1,78 @@ +[[ldap.repositories.queries]] += Query Methods + +Most of the data access operations you usually trigger on a repository result in a query being run against the LDAP directory. +Defining such a query is a matter of declaring a method on the repository interface, as the following example shows: + +.PersonRepository with query methods +[source,java] +---- +interface PersonRepository extends PagingAndSortingRepository { + + List findByLastname(String lastname); <1> + + List findByLastnameFirstname(String lastname, String firstname); <2> +} +---- + +<1> The method shows a query for all people with the given `lastname`. +The query is derived by parsing the method name for constraints that can be concatenated with `And` and `Or`. +Thus, the method name results in a query expression of `(&(objectclass=person)(lastname=lastname))`. +<2> The method shows a query for all people with the given `lastname` and `firstname`. +The query is derived by parsing the method name. +Thus, the method name results in a query expression of `(&(objectclass=person)(lastname=lastname)(firstname=firstname))`. + +The following table provides samples of the keywords that you can use with query methods: + +[cols="1,2,3",options="header"] +.Supported keywords for query methods +|=== +| Keyword +| Sample +| Logical result + +| `LessThanEqual` +| `findByAgeLessThanEqual(int age)` +| `(attribute<=age)` + +| `GreaterThanEqual` +| `findByAgeGreaterThanEqual(int age)` +| `(attribute>=age)` + +| `IsNotNull`, `NotNull` +| `findByFirstnameNotNull()` +| `(firstname=*)` + +| `IsNull`, `Null` +| `findByFirstnameNull()` +| `(!(firstname=*))` + +| `Like` +| `findByFirstnameLike(String name)` +| `(firstname=name)` + +| `NotLike`, `IsNotLike` +| `findByFirstnameNotLike(String name)` +| `(!(firstname=name*))` + +| `StartingWith` +| `findByStartingWith(String name)` +| `(firstname=name*)` + +| `EndingWith` +| `findByFirstnameLike(String name)` +| `(firstname=*name)` + +| `Containing` +| `findByFirstnameLike(String name)` +| `(firstname=\*name*)` + +| `(No keyword)` +| `findByFirstname(String name)` +| `(Firstname=name)` + +| `Not` +| `findByFirstnameNot(String name)` +| `(!(Firstname=name))` + +|=== diff --git a/src/main/antora/modules/ROOT/pages/ldap/querydsl.adoc b/src/main/antora/modules/ROOT/pages/ldap/querydsl.adoc new file mode 100644 index 0000000..60b6cea --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/ldap/querydsl.adoc @@ -0,0 +1,9 @@ +[[ldap.querydsl]] += QueryDSL Support +Basic QueryDSL support is included in Spring LDAP. This support includes the following: + +* An Annotation Processor, `LdapAnnotationProcessor`, for generating QueryDSL classes based on Spring LDAP ODM annotations. +See https://docs.spring.io/spring-ldap/docs/{springLdapVersion}/reference/#odm[Object-Directory Mapping] for more information on the ODM annotations. +* A Query implementation, `QueryDslLdapQuery`, for building and running QueryDSL queries in code. +* Spring Data repository support for QueryDSL predicates. `QueryDslPredicateExecutor` includes a number of additional methods with appropriate parameters. +You can extend this interface (along with `LdapRepository`) to include this support in your repository. diff --git a/src/main/antora/modules/ROOT/pages/ldap/usage.adoc b/src/main/antora/modules/ROOT/pages/ldap/usage.adoc new file mode 100644 index 0000000..1377d2d --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/ldap/usage.adoc @@ -0,0 +1,78 @@ +[[ldap.repo-usage]] += Usage + +To access domain entities stored in a LDAP-compliant directory, you can use our sophisticated repository support that significantly eases implementation. +To do so, create an interface for your repository, as the following example shows: + +.Sample Person entity +==== +[source,java] +---- +@Entry(objectClasses = { "person", "top" }, base="ou=someOu") +public class Person { + + @Id + private Name dn; + + @Attribute(name="cn") + @DnAttribute(value="cn", index=1) + private String fullName; + + @Attribute(name="firstName") + private String firstName; + + // No @Attribute annotation means this is bound to the LDAP attribute + // with the same value + private String firstName; + + @DnAttribute(value="ou", index=0) + @Transient + private String company; + + @Transient + private String someUnmappedField; + // ...more attributes below +} +---- +==== + +We have a simple domain object here. +Note that it has a property named `dn` of type `Name`. +With that domain object, we can create a repository to persist objects of that type by defining an interface for it, as follows: + +.Basic repository interface to persist `Person` entities +==== +[source] +---- +public interface PersonRepository extends CrudRepository { + + // additional custom finder methods go here +} +---- +==== + +Because our domain repository extends `CrudRepository`, it provides you with CRUD operations as well as methods for access to the entities. +Working with the repository instance is a matter of dependency injecting it into a client. + +.Access to Person entities +==== +[source,java] +---- +@ExtendWith(SpringExtension.class) +@ContextConfiguration +class PersonRepositoryTests { + + @Autowired PersonRepository repository; + + @Test + void readAll() { + + List persons = repository.findAll(); + assertThat(persons.isEmpty(), is(false)); + } +} +---- +==== + +The sample creates an application context with Spring's unit test support, which will perform annotation-based dependency injection into test cases. +Inside the test method, we use the repository to query the datastore. diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc new file mode 100644 index 0000000..4ae3ce6 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/core-concepts.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc new file mode 100644 index 0000000..f84313e --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/core-domain-events.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc new file mode 100644 index 0000000..a7c2ff8 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/core-extensions.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc b/src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc new file mode 100644 index 0000000..2ae0180 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/create-instances.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc b/src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc new file mode 100644 index 0000000..c761519 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/custom-implementations.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/definition.adoc b/src/main/antora/modules/ROOT/pages/repositories/definition.adoc new file mode 100644 index 0000000..bd65a8a --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/definition.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/definition.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/introduction.adoc b/src/main/antora/modules/ROOT/pages/repositories/introduction.adoc new file mode 100644 index 0000000..8c2ee5c --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/introduction.adoc @@ -0,0 +1,8 @@ +[[common.basics]] += Introduction +:page-section-summary-toc: 1 + +This chapter explains the basic foundations of Spring Data repositories. +Before continuing to the LDAP specifics, make sure you have a sound understanding of the basic concepts explained here. + +include::{commons}@data-commons::page$repositories.adoc[leveloffset=+1] diff --git a/src/main/antora/modules/ROOT/pages/repositories/namespace-reference.adoc b/src/main/antora/modules/ROOT/pages/repositories/namespace-reference.adoc new file mode 100644 index 0000000..e9e887b --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/namespace-reference.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/namespace-reference.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc b/src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc new file mode 100644 index 0000000..081bac9 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/null-handling.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/projections.adoc b/src/main/antora/modules/ROOT/pages/repositories/projections.adoc new file mode 100644 index 0000000..e012a23 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/projections.adoc @@ -0,0 +1,4 @@ +[[ldap.projections]] += Projections + +include::{commons}@data-commons::page$repositories/projections.adoc[leveloffset=+1] diff --git a/src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc b/src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc new file mode 100644 index 0000000..e495edd --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/query-keywords-reference.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc b/src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc new file mode 100644 index 0000000..dfe4814 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/query-methods-details.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc b/src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc new file mode 100644 index 0000000..a73c320 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/query-return-types-reference.adoc[] diff --git a/src/main/antora/resources/antora-resources/antora.yml b/src/main/antora/resources/antora-resources/antora.yml new file mode 100644 index 0000000..3998e64 --- /dev/null +++ b/src/main/antora/resources/antora-resources/antora.yml @@ -0,0 +1,21 @@ +version: ${antora-component.version} +prerelease: ${antora-component.prerelease} + +asciidoc: + attributes: + version: ${project.version} + springversionshort: ${spring.short} + springversion: ${spring} + attribute-missing: 'warn' + commons: ${springdata.commons.docs} + include-xml-namespaces: false + spring-data-commons-docs-url: https://docs.spring.io/spring-data-commons/reference + spring-data-commons-javadoc-base: https://docs.spring.io/spring-data/commons/docs/${springdata.commons}/api/ + springdocsurl: https://docs.spring.io/spring-framework/reference/{springversionshort} + springjavadocurl: https://docs.spring.io/spring-framework/docs/${spring}/javadoc-api + spring-framework-docs: '{springdocsurl}' + spring-framework-javadoc: '{springjavadocurl}' + springhateoasversion: ${spring-hateoas} + springLdapVersion: ${spring-ldap} + releasetrainversion: ${releasetrain} + store: Ldap diff --git a/src/main/asciidoc/images/epub-cover.png b/src/main/asciidoc/images/epub-cover.png deleted file mode 100644 index 35f0bcbf23555e3e0f12879b8bcf60a96b5c782f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39939 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 - - - - Spring Data LDAP - Reference Guide - Mattias Hellborg Arthursson, - Ulrik Sandberg, Eric Dalquist, - Keith Barlow, Rob Winch, - Mark Paluch, Jay Bryant - diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc deleted file mode 100644 index 70a4170..0000000 --- a/src/main/asciidoc/index.adoc +++ /dev/null @@ -1,31 +0,0 @@ -= Spring Data LDAP - Reference Documentation -Mattias Hellborg Arthursson; Ulrik Sandberg; Eric Dalquist; Keith Barlow; Rob Winch; Mark Paluch; Jay Bryant -:revnumber: {version} -:revdate: {localdate} -ifdef::backend-epub3[:front-cover-image: image:epub-cover.png[Front Cover,1050,1600]] -:spring-data-commons-docs: ../../../../spring-data-commons/src/main/asciidoc -:spring-framework-docs: {springDocsUrl} -:store: Ldap - -(C) 2008-2022 The original authors. - -NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically. - -include::preface.adoc[] -include::{spring-data-commons-docs}/upgrade.adoc[leveloffset=+1] -include::{spring-data-commons-docs}/dependencies.adoc[leveloffset=+1] -include::{spring-data-commons-docs}/repositories.adoc[leveloffset=+1] - -[[reference]] -= Reference Documentation - -include::reference/ldap-repositories.adoc[leveloffset=+1] - -[[appendix]] -= Appendix - -:numbered!: -include::{spring-data-commons-docs}/repository-namespace-reference.adoc[leveloffset=+1] -include::{spring-data-commons-docs}/repository-populator-namespace-reference.adoc[leveloffset=+1] -include::{spring-data-commons-docs}/repository-query-keywords-reference.adoc[leveloffset=+1] -include::{spring-data-commons-docs}/repository-query-return-types-reference.adoc[leveloffset=+1] diff --git a/src/main/asciidoc/preface.adoc b/src/main/asciidoc/preface.adoc deleted file mode 100644 index b829e19..0000000 --- a/src/main/asciidoc/preface.adoc +++ /dev/null @@ -1,69 +0,0 @@ -[[preface]] -= Preface - -Spring Data LDAP makes it easier to build Spring-based applications that use the Lightweight Directory Access Protocol (LDAP). - -This document is the reference guide for Spring Data - Document Support. It explains Document module concepts and semantics and the syntax for various data store namespaces. - - -[[get-started:first-steps:spring]] -== Knowing Spring - -Spring Data uses the Spring Framework's {spring-framework-docs}core.html[core] -functionality, including: - -* {spring-framework-docs}core.html#beans[IoC] container -* {spring-framework-docs}core.html#validation[validation, type conversion and data binding] -* {spring-framework-docs}core.html#expressions[expression language] -* {spring-framework-docs}core.html#aop[AOP] -* {spring-framework-docs}integration.html#jmx[JMX integration] -* {spring-framework-docs}data-access.html[DAO support] -* {spring-framework-docs}data-access.html#dao-exceptions[DAO Exception Hierarchy] - -While it is not important to know the Spring APIs, understanding the concepts behind them is important. At a minimum, the idea -behind IoC should be familiar, no matter what IoC container you choose to use. - -The core functionality of the LDAP support can be used directly, with no need to invoke the IoC services -of the Spring container. This is much like `JdbcTemplate`, which can be used 'standalone' without any other services -of the Spring container. To use all the features of Spring Data LDAP, such as the repository support, -you must configure some parts of the library by using Spring. - -To learn more about Spring, you can refer to the comprehensive {spring-framework-docs}[documentation] -that explains the Spring Framework in detail. There are a lot of articles, blog entries, and books on Spring. -See the Spring Framework https://spring.io/projects/spring-framework/[home page] for more information. - -While it is not important to know the Spring APIs, you do need to understand the concepts behind them. At a minimum, the idea behind IoC should be familiar for whatever IoC container you choose to use. - -To learn more about Spring, you can refer to the comprehensive documentation that explains the Spring Framework in detail. You can find a lot of articles, blog entries, and books on Spring. See the Spring framework https://spring.io/projects[home page] for more information. - -[[requirements]] -== Requirements - -Spring Data LDAP 2.x binaries requires JDK level 8.0 or later, https://spring.io/projects/spring-framework/[Spring Framework] {springVersion} or later, and https://spring.io/projects/spring-ldap[Spring LDAP] {springLdapVersion} or later. - -[[get-started:help]] -== Additional Help Resources - -Learning a new framework is not always straight forward. In this section, we try to provide what we think is an easy-to-follow guide for starting with the Spring Data LDAP module. However, if you encounter issues or are looking for advice, try one or more of the following resources: - -[[get-started:help:community]] -Community Forum:: -Spring Data on Stackoverflow https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow] is a tag for all of Spring Data (not just Document) users to share information and help each other. Note that registration is needed only for posting. - -[[get-started:help:professional]] -Professional Support:: -Professional, from-the-source support, with guaranteed response time, is available from https://pivotal.io/[Pivotal Sofware, Inc.], the company behind Spring and Spring Data. - -[[get-started:up-to-date]] -=== Following Development - -For information on the Spring Data LDAP source code repository, nightly builds, and snapshot artifacts, see the https://spring.io/projects/spring-data-ldap/[Spring Data LDAP homepage]. You can help make Spring Data best serve the needs of the Spring community by interacting with developers through the community on https://stackoverflow.com/questions/tagged/spring-data[Stackoverflow]. To follow developer activity, look for the mailing list information on the Spring Data LDAP homepage. If you encounter a bug or want to suggest an improvement, please create a ticket on the Spring Data issue https://github.com/spring-projects/spring-data-ldap/issues[tracker]. To stay up-to-date with the latest news and announcements in the Spring ecosystem, subscribe to the Spring Community https://spring.io[Portal]. Finally, you can follow the Spring https://spring.io/blog[blog] or the project team on Twitter (https://twitter.com/SpringData[SpringData]). - -[[get-started:project-metadata]] -=== Project Metadata - -* Version Control: https://github.com/spring-projects/spring-data-ldap -* Bugtracker: https://github.com/spring-projects/spring-data-ldap/issues -* Release repository: https://repo1.maven.org/maven2/ -* Milestone repository: https://repo.spring.io/milestone/ -* Snapshot repository: https://repo.spring.io/snapshot/ diff --git a/src/main/asciidoc/reference/ldap-repositories.adoc b/src/main/asciidoc/reference/ldap-repositories.adoc deleted file mode 100644 index 629b0a2..0000000 --- a/src/main/asciidoc/reference/ldap-repositories.adoc +++ /dev/null @@ -1,274 +0,0 @@ -[[ldap.repositories]] -= LDAP Repositories - -This chapter points out the specialties for repository support for LDAP. It builds on the core repository support explained in <>. You should have a sound understanding of the basic concepts explained there. - -You should keep in mind the following points as you work with Spring LDAP repositories: - -* Spring LDAP repositories can be enabled by using a `` tag in your XML configuration or by using an `@EnableLdapRepositories` annotation on a configuration class. -* To include support for `LdapQuery` parameters in automatically generated repositories, have your interface extend `LdapRepository` rather than `CrudRepository`. -* All Spring LDAP repositories must work with entities annotated with the ODM annotations, as described in https://docs.spring.io/spring-ldap/docs/{springLdapVersion}/reference/#odm[Object-Directory Mapping]. -* Since all ODM managed classes must have a Distinguished Name as the ID, all Spring LDAP repositories must have the ID type parameter set to `javax.naming.Name`. - Indeed, the built-in `LdapRepository` only takes one type parameter: the managed entity class, which defaults the ID to `javax.naming.Name`. -* Due to specifics of the LDAP protocol, paging and sorting are not supported for Spring LDAP repositories. - -NOTE: You must use ODM annotations, such as `org.springframework.ldap.odm.annotations.Id`. Using Spring Data's annotation does not work, because Spring LDAP uses its own mapping layer. - -[[ldap.repo-usage]] -== Usage - -To access domain entities stored in a LDAP-compliant directory, you can use our sophisticated repository support that significantly eases implementation. To do so, create an interface for your repository, as the following example shows: - -.Sample Person entity -==== -[source,java] ----- -@Entry(objectClasses = { "person", "top" }, base="ou=someOu") -public class Person { - - @Id - private Name dn; - - @Attribute(name="cn") - @DnAttribute(value="cn", index=1) - private String fullName; - - @Attribute(name="firstName") - private String firstName; - - // No @Attribute annotation means this is bound to the LDAP attribute - // with the same value - private String firstName; - - @DnAttribute(value="ou", index=0) - @Transient - private String company; - - @Transient - private String someUnmappedField; - // ...more attributes below -} ----- -==== - -We have a simple domain object here. Note that it has a property named `dn` of type `Name`. With that domain object, we can create a repository to persist objects of that type by defining an interface for it, as follows: - -.Basic repository interface to persist `Person` entities -==== -[source] ----- -public interface PersonRepository extends CrudRepository { - - // additional custom finder methods go here -} ----- -==== - -Right now, this interface serves only typing purposes, but we can add additional methods to it later. In your Spring configuration, add the following: - -.General LDAP repository Spring configuration -==== -.Java -[source,java,role="primary"] ----- -@Configuration -@EnableLdapRepositories("com.acme.*.repositories") -class MyConfig { - - @Bean - ContextSource contextSource() { - - LdapContextSource ldapContextSource = new LdapContextSource(); - - ldapContextSource.setUserDn("cn=Admin"); - ldapContextSource.setPassword("secret"); - ldapContextSource.setUrl("ldap://127.0.0.1:389"); - - return ldapContextSource; - } - - @Bean - LdapTemplate ldapTemplate(ContextSource contextSource) { - return new LdapTemplate(contextSource); - } -} ----- - -.XML -[source,xml,role="secondary"] ----- - - - - - - - - - - ----- -==== - -This configuration causes the base packages to be scanned for interfaces that extend `LdapRepository` and create Spring beans for each one found. -By default, the repositories get an autowired `LdapTemplate` Spring bean that is called `ldapTemplate`, so you only need to configure `ldap-template-ref` explicitly if you deviate from this convention. - -If you want to go with Java configuration, use the `@EnableLdapRepositories` annotation. The annotation carries the same attributes as the namespace element. If no base package is configured, the infrastructure scans the package of the annotated configuration class. - -Because our domain repository extends `CrudRepository`, it provides you with CRUD operations as well as methods for access to the entities. Working with the repository instance is a matter of dependency injecting it into a client. - -We can add paging access to our repository, as follows: - -.Paging access to Person entities -==== -[source,java] ----- -@ExtendWith({SpringExtension.class}) -@ContextConfiguration -class PersonRepositoryTests { - - @Autowired PersonRepository repository; - - @Test - void readAll() { - - List persons = repository.findAll(); - assertThat(persons.isEmpty(), is(false)); - } -} ----- -==== - -The sample creates an application context with Spring's unit test support, which will perform annotation-based dependency injection into test cases. Inside the test method, we use the repository to query the datastore. - -[[ldap.repositories.queries]] -== Query Methods - -Most of the data access operations you usually trigger on a repository result in a query being run against the LDAP directory. Defining such a query is a matter of declaring a method on the repository interface, as the following example shows: - -.PersonRepository with query methods -==== -[source,java] ----- -interface PersonRepository extends PagingAndSortingRepository { - - List findByLastname(String lastname); <1> - - List findByLastnameFirstname(String lastname, String firstname); <2> -} ----- -<1> The method shows a query for all people with the given `lastname`. The query is derived by parsing the method name for constraints that can be concatenated with `And` and `Or`. Thus, the method name results in a query expression of `(&(objectclass=person)(lastname=lastname))`. -<2> The method shows a query for all people with the given `lastname` and `firstname`. The query is derived by parsing the method name. Thus, the method name results in a query expression of `(&(objectclass=person)(lastname=lastname)(firstname=firstname))`. -==== - -The following table provides samples of the keywords that you can use with query methods: - -[cols="1,2,3", options="header"] -.Supported keywords for query methods -|=== -| Keyword -| Sample -| Logical result - -| `LessThanEqual` -| `findByAgeLessThanEqual(int age)` -| `(attribute<=age)` - -| `GreaterThanEqual` -| `findByAgeGreaterThanEqual(int age)` -| `(attribute>=age)` - -| `IsNotNull`, `NotNull` -| `findByFirstnameNotNull()` -| `(firstname=*)` - -| `IsNull`, `Null` -| `findByFirstnameNull()` -| `(!(firstname=*))` - -| `Like` -| `findByFirstnameLike(String name)` -| `(firstname=name)` - -| `NotLike`, `IsNotLike` -| `findByFirstnameNotLike(String name)` -| `(!(firstname=name*))` - -| `StartingWith` -| `findByStartingWith(String name)` -| `(firstname=name*)` - -| `EndingWith` -| `findByFirstnameLike(String name)` -| `(firstname=*name)` - -| `Containing` -| `findByFirstnameLike(String name)` -| `(firstname=\*name*)` - -| `(No keyword)` -| `findByFirstname(String name)` -| `(Firstname=name)` - -| `Not` -| `findByFirstnameNot(String name)` -| `(!(Firstname=name))` - -|=== - -include::../{spring-data-commons-docs}/repository-projections.adoc[leveloffset=+2] - -=== QueryDSL Support -Basic QueryDSL support is included in Spring LDAP. This support includes the following: - -* An Annotation Processor, `LdapAnnotationProcessor`, for generating QueryDSL classes based on Spring LDAP ODM annotations. See https://docs.spring.io/spring-ldap/docs/{springLdapVersion}/reference/#odm[Object-Directory Mapping] for more information on the ODM annotations. -* A Query implementation, `QueryDslLdapQuery`, for building and running QueryDSL queries in code. -* Spring Data repository support for QueryDSL predicates. `QueryDslPredicateExecutor` includes a number of additional methods with appropriate parameters. You can extend this interface (along with `LdapRepository`) to include this support in your repository. - -[[ldap.repositories.misc]] -== Miscellaneous - -[[ldap.repositories.misc.cdi-integration]] -=== CDI Integration - -Instances of the repository interfaces are usually created by a container, for which Spring is the most natural choice when working with Spring Data. As of version 2.1, Spring Data LDAP includes a custom CDI extension that lets you use the repository abstraction in CDI environments. The extension is part of the JAR. To activate it, drop the Spring Data LDAP JAR into your classpath. You can now set up the infrastructure by implementing a CDI Producer for the `LdapTemplate`, as the following example shows: - -[source,java] ----- -class LdapTemplateProducer { - - @Produces - @ApplicationScoped - public LdapOperations createLdapTemplate() { - - ContextSource contextSource = … - return new LdapTemplate(contextSource); - } -} ----- - -The Spring Data LDAP CDI extension picks up the `LdapTemplate` as a CDI bean and creates a proxy for a Spring Data repository whenever a bean of a repository type is requested by the container. Thus, obtaining an instance of a Spring Data repository is a matter of declaring an injected property, as the following example shows: - -[source,java] ----- -class RepositoryClient { - - @Inject - PersonRepository repository; - - public void businessMethod() { - List people = repository.findAll(); - } -} -----