Skip to content

Commit 1f7ad7c

Browse files
committed
Reinstate Asciidoc docs.
Reinstate Asciidoc to retain functionality for downstream module documentation builds. See #2876
1 parent ea9bf5b commit 1f7ad7c

25 files changed

+3840
-0
lines changed

pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@
357357
<groupId>org.apache.maven.plugins</groupId>
358358
<artifactId>maven-assembly-plugin</artifactId>
359359
</plugin>
360+
<plugin>
361+
<groupId>org.asciidoctor</groupId>
362+
<artifactId>asciidoctor-maven-plugin</artifactId>
363+
</plugin>
360364
<plugin>
361365
<groupId>io.spring.maven.antora</groupId>
362366
<artifactId>antora-maven-plugin</artifactId>

src/main/asciidoc/auditing.adoc

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
[[auditing]]
2+
= Auditing
3+
4+
[[auditing.basics]]
5+
== Basics
6+
Spring Data provides sophisticated support to transparently keep track of who created or changed an entity and when the change happened.To benefit from that functionality, you have to equip your entity classes with auditing metadata that can be defined either using annotations or by implementing an interface.
7+
Additionally, auditing has to be enabled either through Annotation configuration or XML configuration to register the required infrastructure components.
8+
Please refer to the store-specific section for configuration samples.
9+
10+
[NOTE]
11+
====
12+
Applications that only track creation and modification dates are not required do make their entities implement <<auditing.auditor-aware, `AuditorAware`>>.
13+
====
14+
15+
[[auditing.annotations]]
16+
=== Annotation-based Auditing Metadata
17+
We provide `@CreatedBy` and `@LastModifiedBy` to capture the user who created or modified the entity as well as `@CreatedDate` and `@LastModifiedDate` to capture when the change happened.
18+
19+
.An audited entity
20+
====
21+
[source,java]
22+
----
23+
class Customer {
24+
25+
@CreatedBy
26+
private User user;
27+
28+
@CreatedDate
29+
private Instant createdDate;
30+
31+
// … further properties omitted
32+
}
33+
----
34+
====
35+
36+
As you can see, the annotations can be applied selectively, depending on which information you want to capture.
37+
The annotations, indicating to capture when changes are made, can be used on properties of type JDK8 date and time types, `long`, `Long`, and legacy Java `Date` and `Calendar`.
38+
39+
Auditing metadata does not necessarily need to live in the root level entity but can be added to an embedded one (depending on the actual store in use), as shown in the snippet below.
40+
41+
.Audit metadata in embedded entity
42+
====
43+
[source,java]
44+
----
45+
class Customer {
46+
47+
private AuditMetadata auditingMetadata;
48+
49+
// … further properties omitted
50+
}
51+
52+
class AuditMetadata {
53+
54+
@CreatedBy
55+
private User user;
56+
57+
@CreatedDate
58+
private Instant createdDate;
59+
60+
}
61+
----
62+
====
63+
64+
[[auditing.interfaces]]
65+
=== Interface-based Auditing Metadata
66+
In case you do not want to use annotations to define auditing metadata, you can let your domain class implement the `Auditable` interface. It exposes setter methods for all of the auditing properties.
67+
68+
[[auditing.auditor-aware]]
69+
=== `AuditorAware`
70+
71+
In case you use either `@CreatedBy` or `@LastModifiedBy`, the auditing infrastructure somehow needs to become aware of the current principal. To do so, we provide an `AuditorAware<T>` SPI interface that you have to implement to tell the infrastructure who the current user or system interacting with the application is. The generic type `T` defines what type the properties annotated with `@CreatedBy` or `@LastModifiedBy` have to be.
72+
73+
The following example shows an implementation of the interface that uses Spring Security's `Authentication` object:
74+
75+
.Implementation of `AuditorAware` based on Spring Security
76+
====
77+
[source, java]
78+
----
79+
class SpringSecurityAuditorAware implements AuditorAware<User> {
80+
81+
@Override
82+
public Optional<User> getCurrentAuditor() {
83+
84+
return Optional.ofNullable(SecurityContextHolder.getContext())
85+
.map(SecurityContext::getAuthentication)
86+
.filter(Authentication::isAuthenticated)
87+
.map(Authentication::getPrincipal)
88+
.map(User.class::cast);
89+
}
90+
}
91+
----
92+
====
93+
94+
The implementation accesses the `Authentication` object provided by Spring Security and looks up the custom `UserDetails` instance that you have created in your `UserDetailsService` implementation. We assume here that you are exposing the domain user through the `UserDetails` implementation but that, based on the `Authentication` found, you could also look it up from anywhere.
95+
96+
[[auditing.reactive-auditor-aware]]
97+
=== `ReactiveAuditorAware`
98+
99+
When using reactive infrastructure you might want to make use of contextual information to provide `@CreatedBy` or `@LastModifiedBy` information.
100+
We provide an `ReactiveAuditorAware<T>` SPI interface that you have to implement to tell the infrastructure who the current user or system interacting with the application is. The generic type `T` defines what type the properties annotated with `@CreatedBy` or `@LastModifiedBy` have to be.
101+
102+
The following example shows an implementation of the interface that uses reactive Spring Security's `Authentication` object:
103+
104+
.Implementation of `ReactiveAuditorAware` based on Spring Security
105+
====
106+
[source, java]
107+
----
108+
class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {
109+
110+
@Override
111+
public Mono<User> getCurrentAuditor() {
112+
113+
return ReactiveSecurityContextHolder.getContext()
114+
.map(SecurityContext::getAuthentication)
115+
.filter(Authentication::isAuthenticated)
116+
.map(Authentication::getPrincipal)
117+
.map(User.class::cast);
118+
}
119+
}
120+
----
121+
====
122+
123+
The implementation accesses the `Authentication` object provided by Spring Security and looks up the custom `UserDetails` instance that you have created in your `UserDetailsService` implementation. We assume here that you are exposing the domain user through the `UserDetails` implementation but that, based on the `Authentication` found, you could also look it up from anywhere.
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
The following example of a Spring `Converter` implementation converts from a `String` to a custom `Email` value object:
2+
3+
[source,java,subs="verbatim,attributes"]
4+
----
5+
@ReadingConverter
6+
public class EmailReadConverter implements Converter<String, Email> {
7+
8+
public Email convert(String source) {
9+
return Email.valueOf(source);
10+
}
11+
}
12+
----
13+
14+
If you write a `Converter` whose source and target type are native types, we cannot determine whether we should consider it as a reading or a writing converter.
15+
Registering the converter instance as both might lead to unwanted results.
16+
For example, a `Converter<String, Long>` is ambiguous, although it probably does not make sense to try to convert all `String` instances into `Long` instances when writing.
17+
To let you force the infrastructure to register a converter for only one way, we provide `@ReadingConverter` and `@WritingConverter` annotations to be used in the converter implementation.
18+
19+
Converters are subject to explicit registration as instances are not picked up from a classpath or container scan to avoid unwanted registration with a conversion service and the side effects resulting from such a registration. Converters are registered with `CustomConversions` as the central facility that allows registration and querying for registered converters based on source- and target type.
20+
21+
`CustomConversions` ships with a pre-defined set of converter registrations:
22+
23+
* JSR-310 Converters for conversion between `java.time`, `java.util.Date` and `String` types.
24+
25+
NOTE: Default converters for local temporal types (e.g. `LocalDateTime` to `java.util.Date`) rely on system-default timezone settings to convert between those types. You can override the default converter, by registering your own converter.
26+
27+
[[customconversions.converter-disambiguation]]
28+
== Converter Disambiguation
29+
30+
Generally, we inspect the `Converter` implementations for the source and target types they convert from and to.
31+
Depending on whether one of those is a type the underlying data access API can handle natively, we register the converter instance as a reading or a writing converter.
32+
The following examples show a writing- and a read converter (note the difference is in the order of the qualifiers on `Converter`):
33+
34+
[source,java]
35+
----
36+
// Write converter as only the target type is one that can be handled natively
37+
class MyConverter implements Converter<Person, String> { … }
38+
39+
// Read converter as only the source type is one that can be handled natively
40+
class MyConverter implements Converter<String, Person> { … }
41+
----

src/main/asciidoc/dependencies.adoc

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
[[dependencies]]
2+
= Dependencies
3+
4+
Due to the different inception dates of individual Spring Data modules, most of them carry different major and minor version numbers. The easiest way to find compatible ones is to rely on the Spring Data Release Train BOM that we ship with the compatible versions defined. In a Maven project, you would declare this dependency in the `<dependencyManagement />` section of your POM as follows:
5+
6+
.Using the Spring Data release train BOM
7+
====
8+
[source, xml, subs="+attributes"]
9+
----
10+
<dependencyManagement>
11+
<dependencies>
12+
<dependency>
13+
<groupId>org.springframework.data</groupId>
14+
<artifactId>spring-data-bom</artifactId>
15+
<version>{releasetrainVersion}</version>
16+
<scope>import</scope>
17+
<type>pom</type>
18+
</dependency>
19+
</dependencies>
20+
</dependencyManagement>
21+
----
22+
====
23+
24+
[[dependencies.train-names]]
25+
[[dependencies.train-version]]
26+
The current release train version is `{releasetrainVersion}`. The train version uses https://calver.org/[calver] with the pattern `YYYY.MINOR.MICRO`.
27+
The version name follows `${calver}` for GA releases and service releases and the following pattern for all other versions: `${calver}-${modifier}`, where `modifier` can be one of the following:
28+
29+
* `SNAPSHOT`: Current snapshots
30+
* `M1`, `M2`, and so on: Milestones
31+
* `RC1`, `RC2`, and so on: Release candidates
32+
33+
You can find a working example of using the BOMs in our https://github.com/spring-projects/spring-data-examples/tree/main/bom[Spring Data examples repository]. With that in place, you can declare the Spring Data modules you would like to use without a version in the `<dependencies />` block, as follows:
34+
35+
.Declaring a dependency to a Spring Data module
36+
====
37+
[source, xml]
38+
----
39+
<dependencies>
40+
<dependency>
41+
<groupId>org.springframework.data</groupId>
42+
<artifactId>spring-data-jpa</artifactId>
43+
</dependency>
44+
<dependencies>
45+
----
46+
====
47+
48+
[[dependencies.spring-boot]]
49+
== Dependency Management with Spring Boot
50+
51+
Spring Boot selects a recent version of the Spring Data modules for you. If you still want to upgrade to a newer version,
52+
set the `spring-data-bom.version` property to the <<dependencies.train-version,train version and iteration>>
53+
you would like to use.
54+
55+
See Spring Boot's https://docs.spring.io/spring-boot/docs/current/reference/html/dependency-versions.html#appendix.dependency-versions.properties[documentation]
56+
(search for "Spring Data Bom") for more details.
57+
58+
[[dependencies.spring-framework]]
59+
== Spring Framework
60+
61+
The current version of Spring Data modules require Spring Framework {springVersion} or better. The modules might also work with an older bugfix version of that minor version. However, using the most recent version within that generation is highly recommended.

0 commit comments

Comments
 (0)