Stop referring to "Java 8" features in documentation

Closes gh-36310
This commit is contained in:
Sam Brannen
2026-02-12 12:11:02 +01:00
parent 6f03c186b9
commit d84c4a39e2
37 changed files with 90 additions and 85 deletions
@@ -727,7 +727,7 @@ of determining parameter names, an exception will be thrown.
parameter names. This discoverer is only used if such APIs are present on the classpath.
`StandardReflectionParameterNameDiscoverer` :: Uses the standard `java.lang.reflect.Parameter`
API to determine parameter names. Requires that code be compiled with the `-parameters`
flag for `javac`. Recommended approach on Java 8+.
flag for `javac`. Recommended approach.
`AspectJAdviceParameterNameDiscoverer` :: Deduces parameter names from the pointcut
expression, `returning`, and `throwing` clauses. See the
{spring-framework-api}/aop/aspectj/AspectJAdviceParameterNameDiscoverer.html[javadoc]
@@ -35,7 +35,7 @@ xref:integration/cache/store-configuration.adoc#cache-store-configuration-jsr107
[[cache-store-configuration-caffeine]]
== Caffeine Cache
Caffeine is a Java 8 rewrite of Guava's cache, and its implementation is located in the
Caffeine is a rewrite of Guava's cache, and its implementation is located in the
`org.springframework.cache.caffeine` package and provides access to several features
of Caffeine.
@@ -26,7 +26,7 @@ behind the scenes for each annotated method, by using a `JmsListenerContainerFac
Such a container is not registered against the application context but can be easily
located for management purposes by using the `JmsListenerEndpointRegistry` bean.
TIP: `@JmsListener` is a repeatable annotation on Java 8, so you can associate
TIP: `@JmsListener` is a repeatable annotation, so you can associate
several JMS destinations with the same method by adding additional `@JmsListener`
declarations to it.
@@ -466,7 +466,7 @@ synchronous, asynchronous, and streaming scenarios.
* Non-blocking I/O
* Reactive Streams back pressure
* High concurrency with fewer hardware resources
* Functional-style, fluent API that takes advantage of Java 8 lambdas
* Functional-style, fluent API that takes advantage of lambda expressions
* Synchronous and asynchronous interactions
* Streaming up to or streaming down from a server
@@ -3,13 +3,15 @@
:page-section-summary-toc: 1
The Spring Framework supports various Kotlin constructs, such as instantiating Kotlin classes
through primary constructors, immutable classes data binding, and function optional parameters
with default values.
through primary constructors, data binding for immutable classes, and optional parameters
with default values for functions.
Kotlin parameter names are recognized through a dedicated `KotlinReflectionParameterNameDiscoverer`,
which allows finding interface method parameter names without requiring the Java 8 `-parameters`
compiler flag to be enabled during compilation. (For completeness, we nevertheless recommend
running the Kotlin compiler with its `-java-parameters` flag for standard Java parameter exposure.)
which allows finding interface method parameter names without requiring the Java `-parameters`
compiler flag to be enabled during compilation.
TIP: For completeness, we nevertheless recommend running the Kotlin compiler with its
`-java-parameters` flag for standard Java parameter exposure.
You can declare configuration classes as
{kotlin-docs}/nested-classes.html[top level or nested but not inner],
@@ -4,8 +4,7 @@
`@AfterTransaction` indicates that the annotated `void` method should be run after a
transaction is ended, for test methods that have been configured to run within a
transaction by using Spring's `@Transactional` annotation. `@AfterTransaction` methods
are not required to be `public` and may be declared on Java 8-based interface default
methods.
are not required to be `public` and may be declared on interface default methods.
[tabs]
======
@@ -4,8 +4,7 @@
`@BeforeTransaction` indicates that the annotated `void` method should be run before a
transaction is started, for test methods that have been configured to run within a
transaction by using Spring's `@Transactional` annotation. `@BeforeTransaction` methods
are not required to be `public` and may be declared on Java 8-based interface default
methods.
are not required to be `public` and may be declared on interface default methods.
The following example shows how to use the `@BeforeTransaction` annotation:
@@ -3,7 +3,7 @@
`@SqlGroup` is a container annotation that aggregates several `@Sql` annotations. You can
use `@SqlGroup` natively to declare several nested `@Sql` annotations, or you can use it
in conjunction with Java 8's support for repeatable annotations, where `@Sql` can be
in conjunction with Java's support for repeatable annotations, where `@Sql` can be
declared several times on the same class or method, implicitly generating this container
annotation. The following example shows how to declare an SQL group:
@@ -11,7 +11,7 @@ https://testng.org/[TestNG] ::
testing, distributed testing, and other features. Supported in the
xref:testing/testcontext-framework.adoc[Spring TestContext Framework].
{assertj-docs}[AssertJ] ::
"Fluent assertions for Java", including support for Java 8 lambdas, streams, and
"Fluent assertions for Java", including support for lambda expressions, streams, and
numerous other features. Supported in Spring's
xref:testing/mockmvc/assertj.adoc[MockMvc testing support].
https://en.wikipedia.org/wiki/Mock_Object[Mock Objects] ::
@@ -58,7 +58,7 @@ If a publisher cannot slow down, it has to decide whether to buffer, drop, or fa
Reactive Streams plays an important role for interoperability. It is of interest to libraries
and infrastructure components but less useful as an application API, because it is too
low-level. Applications need a higher-level and richer, functional API to
compose async logic -- similar to the Java 8 `Stream` API but not only for collections.
compose async logic -- similar to the Java `Stream` API but not only for collections.
This is the role that reactive libraries play.
{reactor-github-org}/reactor[Reactor] is the reactive library of choice for
@@ -131,7 +131,7 @@ execution model benefits as others in this space and also provides a choice of s
(annotated controllers and functional web endpoints), and a choice of reactive libraries
(Reactor, RxJava, or other).
* If you are interested in a lightweight, functional web framework for use with Java 8 lambdas
* If you are interested in a lightweight, functional web framework for use with Java
or Kotlin, you can use the Spring WebFlux functional web endpoints. That can also be a good choice
for smaller applications or microservices with less complex requirements that can benefit
from greater transparency and control.
@@ -283,7 +283,7 @@ public final class CachedIntrospectionResults {
}
// Explicitly check implemented interfaces for setter/getter methods as well,
// in particular for Java 8 default methods...
// in particular for interface default methods.
Class<?> currClass = beanClass;
while (currClass != null && currClass != Object.class) {
introspectInterfaces(beanClass, currClass, readMethodNames);
@@ -149,10 +149,10 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
/**
* Return whether this dependency is required.
* <p>Optional semantics are derived from Java 8's {@link java.util.Optional},
* any variant of a parameter-level {@code Nullable} annotation (such as from
* JSR-305 or the FindBugs set of annotations), or a language-level nullable
* type declaration in Kotlin.
* <p>Optional semantics are derived from Java's {@link java.util.Optional},
* any variant of a parameter-level {@code @Nullable} annotation (such as from
* JSpecify, JSR-305, or the FindBugs set of annotations), or a language-level
* nullable type declaration in Kotlin.
*/
public boolean isRequired() {
if (!this.required) {
@@ -26,9 +26,9 @@ import java.lang.annotation.Target;
* Container annotation that aggregates several {@link ComponentScan} annotations.
*
* <p>Can be used natively, declaring several nested {@link ComponentScan} annotations.
* Can also be used in conjunction with Java 8's support for repeatable annotations,
* where {@link ComponentScan} can simply be declared several times on the same method,
* implicitly generating this container annotation.
* Can also be used in conjunction with Java's support for repeatable annotations,
* where {@link ComponentScan @ComponentScan} can simply be declared several times
* on the same method, implicitly generating this container annotation.
*
* @author Juergen Hoeller
* @since 4.3
@@ -443,7 +443,7 @@ class ConfigurationClassParser {
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
for (MethodMetadata methodMetadata : beanMethods) {
if (!methodMetadata.isAbstract()) {
// A default method or other concrete method on a Java 8+ interface...
// A default method or other concrete method on a Java interface...
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
}
@@ -26,9 +26,10 @@ import java.lang.annotation.Target;
* Container annotation that aggregates several {@link PropertySource} annotations.
*
* <p>Can be used natively, declaring several nested {@link PropertySource} annotations.
* Can also be used in conjunction with Java 8's support for <em>repeatable annotations</em>,
* where {@link PropertySource} can simply be declared several times on the same
* {@linkplain ElementType#TYPE type}, implicitly generating this container annotation.
* Can also be used in conjunction with Java's support for <em>repeatable annotations</em>,
* where {@link PropertySource @PropertySource} can simply be declared several
* times on the same {@linkplain ElementType#TYPE type}, implicitly generating
* this container annotation.
*
* @author Phillip Webb
* @since 4.0
@@ -28,9 +28,9 @@ import org.springframework.aot.hint.annotation.Reflective;
* Container annotation that aggregates several {@link Scheduled} annotations.
*
* <p>Can be used natively, declaring several nested {@link Scheduled} annotations.
* Can also be used in conjunction with Java 8's support for repeatable annotations,
* where {@link Scheduled} can simply be declared several times on the same method,
* implicitly generating this container annotation.
* Can also be used in conjunction with Java's support for repeatable annotations,
* where {@link Scheduled @Scheduled} can simply be declared several times on the
* same method, implicitly generating this container annotation.
*
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
* <em>composed annotations</em>.
@@ -20,7 +20,7 @@ import org.jspecify.annotations.Nullable;
/**
* Default implementation of the {@link ParameterNameDiscoverer} strategy interface,
* delegating to the Java 8 standard reflection mechanism.
* delegating to Java's standard reflection mechanism.
*
* <p>If a Kotlin reflection implementation is present,
* {@link KotlinReflectionParameterNameDiscoverer} is added first in the list and
@@ -47,7 +47,7 @@ public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDisc
addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
}
// Recommended approach on Java 8+: compilation with -parameters.
// Recommended approach on Java: compilation with -parameters.
addDiscoverer(new StandardReflectionParameterNameDiscoverer());
}
@@ -26,11 +26,12 @@ import kotlin.reflect.jvm.ReflectJvmMapping;
import org.jspecify.annotations.Nullable;
/**
* {@link ParameterNameDiscoverer} implementation which uses Kotlin's reflection facilities
* for introspecting parameter names.
* {@link ParameterNameDiscoverer} implementation which uses Kotlin's reflection
* facilities for introspecting parameter names.
*
* <p>Compared to {@link StandardReflectionParameterNameDiscoverer}, it allows in addition to
* determine interface parameter names without requiring Java 8 -parameters compiler flag.
* <p>In contrast to {@link StandardReflectionParameterNameDiscoverer}, this
* discoverer can also determine interface parameter names without requiring Java's
* {@code -parameters} compiler flag.
*
* @author Sebastien Deleuze
* @since 5.0
@@ -24,8 +24,8 @@ import org.springframework.util.ObjectUtils;
/**
* A common key class for a method against a specific target class,
* including {@link #toString()} representation and {@link Comparable}
* support (as suggested for custom {@code HashMap} keys as of Java 8).
* including a {@link #toString()} representation and {@link Comparable}
* support (as suggested for custom {@code HashMap} keys in Java).
*
* @author Juergen Hoeller
* @since 4.3
@@ -393,10 +393,10 @@ public class MethodParameter {
/**
* Return whether this method indicates a parameter which is not required:
* either in the form of Java 8's {@link java.util.Optional}, JSpecify annotations,
* any variant of a parameter-level {@code @Nullable} annotation (such as from Spring,
* JSR-305 or Jakarta set of annotations), a language-level nullable type
* declaration or {@code Continuation} parameter in Kotlin.
* either in the form of {@link java.util.Optional}, JSpecify annotations,
* any variant of a parameter-level {@code @Nullable} annotation (such as
* from Spring, JSR-305, or Jakarta annotations), or a language-level
* nullable type declaration or {@code Continuation} parameter in Kotlin.
* @since 4.3
* @see Nullness#forMethodParameter(MethodParameter)
*/
@@ -23,7 +23,7 @@ import java.lang.reflect.Parameter;
import org.jspecify.annotations.Nullable;
/**
* {@link ParameterNameDiscoverer} implementation which uses JDK 8's reflection facilities
* {@link ParameterNameDiscoverer} implementation which uses Java's reflection facilities
* for introspecting parameter names (based on the "-parameters" compiler flag).
*
* <p>This is a key element of {@link DefaultParameterNameDiscoverer} where it is being
@@ -134,9 +134,10 @@ public class SynthesizingMethodParameter extends MethodParameter {
}
/**
* Create a new SynthesizingMethodParameter for the given parameter descriptor.
* <p>This is a convenience factory method for scenarios where a
* Java 8 {@link Parameter} descriptor is already available.
* Create a new {@code SynthesizingMethodParameter} for the given parameter
* descriptor.
* <p>This is a convenience factory method for scenarios where a Java
* {@link Parameter} descriptor is already available.
* @param parameter the parameter descriptor
* @return the corresponding {@code SynthesizingMethodParameter} instance
* @since 5.0
@@ -194,10 +194,11 @@ public class GenericConversionService implements ConfigurableConversionService {
/**
* Template method to convert a {@code null} source.
* <p>The default implementation returns {@code null} or the Java 8
* {@link java.util.Optional#empty()} instance if the target type is
* {@code java.util.Optional}. Subclasses may override this to return
* custom {@code null} objects for specific target types.
* <p>The default implementation returns {@code null} or the
* {@link Optional#empty()} instance if the target type is
* {@code java.util.Optional}.
* <p>Subclasses may override this to return custom {@code null} objects for
* specific target types.
* @param sourceType the source type to convert from
* @param targetType the target type to convert to
* @return the converted null object
@@ -22,7 +22,7 @@ import java.util.TimeZone;
import org.springframework.core.convert.converter.Converter;
/**
* Simple converter from Java 8's {@link java.time.ZoneId} to {@link java.util.TimeZone}.
* Simple converter from Java's {@link java.time.ZoneId} to {@link java.util.TimeZone}.
*
* <p>Note that Spring's default ConversionService setup understands the 'from'/'to' convention
* that the JSR-310 {@code java.time} package consistently uses. That convention is implemented
@@ -23,7 +23,7 @@ import java.util.GregorianCalendar;
import org.springframework.core.convert.converter.Converter;
/**
* Simple converter from Java 8's {@link java.time.ZonedDateTime} to {@link java.util.Calendar}.
* Simple converter from Java's {@link java.time.ZonedDateTime} to {@link java.util.Calendar}.
*
* <p>Note that Spring's default ConversionService setup understands the 'from'/'to' convention
* that the JSR-310 {@code java.time} package consistently uses. That convention is implemented
@@ -24,7 +24,7 @@ import org.apache.commons.logging.LogFactory;
/**
* A convenient accessor for Commons Logging, providing not only
* {@code CharSequence} based log methods but also {@code Supplier}
* based variants for use with Java 8 lambda expressions.
* based variants for use with Java lambda expressions.
*
* @author Juergen Hoeller
* @since 5.2
@@ -78,8 +78,8 @@ public abstract class ReflectionUtils {
/**
* Cache for {@link Class#getDeclaredMethods()} plus equivalent default methods
* from Java 8 based interfaces, allowing for fast iteration.
* Cache for {@link Class#getDeclaredMethods()} plus equivalent interface
* default methods, allowing for fast iteration.
*/
private static final Map<Class<?>, Method[]> declaredMethodsCache = new ConcurrentReferenceHashMap<>(256);
@@ -309,7 +309,7 @@ public abstract class ReflectionUtils {
/**
* Perform the given callback operation on all matching methods of the given
* class, as locally declared or equivalent thereof (such as default methods
* on Java 8 based interfaces that the given class implements).
* from interfaces that the given class implements).
* @param clazz the class to introspect
* @param mc the callback to invoke for each method
* @throws IllegalStateException if introspection fails
@@ -444,7 +444,7 @@ public abstract class ReflectionUtils {
/**
* Variant of {@link Class#getDeclaredMethods()} that uses a local cache in
* order to avoid new Method instances. In addition, it also includes Java 8
* order to avoid new {@link Method} instances. In addition, it also includes
* default methods from locally implemented interfaces, since those are
* effectively to be treated just like declared methods.
* @param clazz the class to introspect
@@ -576,7 +576,7 @@ class AnnotationUtilsTests {
final List<String> expectedValuesJava = asList("A", "B", "C");
final List<String> expectedValuesSpring = asList("A", "B", "C", "meta1");
// Java 8
// Java
MyRepeatable[] array = MyRepeatableClass.class.getAnnotationsByType(MyRepeatable.class);
assertThat(array).isNotNull();
List<String> values = stream(array).map(MyRepeatable::value).collect(toList());
@@ -601,7 +601,7 @@ class AnnotationUtilsTests {
final List<String> expectedValuesJava = asList("A", "B", "C");
final List<String> expectedValuesSpring = asList("A", "B", "C", "meta1");
// Java 8
// Java
MyRepeatable[] array = clazz.getAnnotationsByType(MyRepeatable.class);
assertThat(array).isNotNull();
List<String> values = stream(array).map(MyRepeatable::value).collect(toList());
@@ -626,7 +626,7 @@ class AnnotationUtilsTests {
final List<String> expectedValuesJava = asList("X", "Y", "Z");
final List<String> expectedValuesSpring = asList("X", "Y", "Z", "meta2");
// Java 8
// Java
MyRepeatable[] array = clazz.getAnnotationsByType(MyRepeatable.class);
assertThat(array).isNotNull();
List<String> values = stream(array).map(MyRepeatable::value).collect(toList());
@@ -651,7 +651,7 @@ class AnnotationUtilsTests {
final List<String> expectedValuesJava = asList("X", "Y", "Z");
final List<String> expectedValuesSpring = asList("X", "Y", "Z", "meta2");
// Java 8
// Java
MyRepeatable[] array = clazz.getAnnotationsByType(MyRepeatable.class);
assertThat(array).isNotNull();
List<String> values = stream(array).map(MyRepeatable::value).collect(toList());
@@ -675,7 +675,7 @@ class AnnotationUtilsTests {
final List<String> expectedValuesJava = asList("A", "B", "C");
final List<String> expectedValuesSpring = asList("A", "B", "C", "meta1");
// Java 8
// Java
MyRepeatable[] array = MyRepeatableClass.class.getDeclaredAnnotationsByType(MyRepeatable.class);
assertThat(array).isNotNull();
List<String> values = stream(array).map(MyRepeatable::value).collect(toList());
@@ -699,7 +699,7 @@ class AnnotationUtilsTests {
void getDeclaredRepeatableAnnotationsDeclaredOnSuperclass() {
final Class<?> clazz = SubMyRepeatableClass.class;
// Java 8
// Java
MyRepeatable[] array = clazz.getDeclaredAnnotationsByType(MyRepeatable.class);
assertThat(array).isNotNull();
assertThat(array).isEmpty();
@@ -105,7 +105,7 @@ class MultipleComposedAnnotationsOnSingleAnnotatedElementTests {
}
@Test
@Disabled("Disabled since some Java 8 updates handle the bridge method differently")
@Disabled("Disabled since some Java versions/compilers handle the bridge method differently")
void getMultipleComposedAnnotationsOnBridgeMethod() {
Set<Cacheable> cacheables = getAllMergedAnnotations(getBridgeMethod(), Cacheable.class);
assertThat(cacheables).isNotNull();
@@ -27,7 +27,7 @@ import java.lang.annotation.Target;
* Container annotation that aggregates several {@link Sql @Sql} annotations.
*
* <p>Can be used natively, declaring several nested {@code @Sql} annotations.
* Can also be used in conjunction with Java 8's support for repeatable
* Can also be used in conjunction with Java's support for repeatable
* annotations, where {@code @Sql} can simply be declared several times on the
* same class or method, implicitly generating this container annotation.
*
@@ -100,9 +100,8 @@ import org.springframework.util.StringUtils;
* execute certain <em>set up</em> or <em>tear down</em> code outside a
* transaction. {@code TransactionalTestExecutionListener} provides such
* support for methods annotated with {@link BeforeTransaction @BeforeTransaction}
* or {@link AfterTransaction @AfterTransaction}. As of Spring Framework 4.3,
* {@code @BeforeTransaction} and {@code @AfterTransaction} may also be declared
* on Java 8 based interface default methods.
* or {@link AfterTransaction @AfterTransaction}. {@code @BeforeTransaction} and
* {@code @AfterTransaction} may also be declared on interface default methods.
*
* <h3>Configuring a Transaction Manager</h3>
* <p>{@code TransactionalTestExecutionListener} expects a
@@ -54,8 +54,8 @@ public interface TransactionOperations {
* {@link org.springframework.transaction.TransactionStatus} from within the callback,
* use {@link #execute(TransactionCallback)} instead.
* <p>This variant is analogous to using a {@link TransactionCallbackWithoutResult}
* but with a simplified signature for common cases - and conveniently usable with
* Java 8 lambda expressions.
* but with a simplified signature for common cases and conveniently usable with
* lambda expressions.
* @param action the Runnable that specifies the transactional action
* @throws TransactionException in case of initialization, rollback, or system errors
* @throws RuntimeException if thrown by the Runnable
@@ -83,9 +83,9 @@ import org.springframework.util.xml.StaxUtils;
* detected on the classpath:
* <ul>
* <li><a href="https://github.com/FasterXML/jackson-datatype-jdk8">jackson-datatype-jdk8</a>:
* support for other Java 8 types like {@link java.util.Optional}</li>
* support for Java 8 types like {@link java.util.Optional}</li>
* <li><a href="https://github.com/FasterXML/jackson-datatype-jsr310">jackson-datatype-jsr310</a>:
* support for Java 8 Date &amp; Time API types</li>
* support for Java Date &amp; Time API types</li>
* <li><a href="https://github.com/FasterXML/jackson-module-kotlin">jackson-module-kotlin</a>:
* support for Kotlin classes and data classes</li>
* <li><a href="https://github.com/FasterXML/jackson-modules-java8/tree/2.18/parameter-names">jackson-modules-java8/parameter-names</a>:
@@ -114,9 +114,9 @@ import org.springframework.context.ApplicationContextAware;
* <li><a href="https://github.com/FasterXML/jackson-datatype-jdk7">jackson-datatype-jdk7</a>:
* support for Java 7 types like {@link java.nio.file.Path}</li>
* <li><a href="https://github.com/FasterXML/jackson-datatype-jdk8">jackson-datatype-jdk8</a>:
* support for other Java 8 types like {@link java.util.Optional}</li>
* support for Java 8 types like {@link java.util.Optional}</li>
* <li><a href="https://github.com/FasterXML/jackson-datatype-jsr310">jackson-datatype-jsr310</a>:
* support for Java 8 Date &amp; Time API types</li>
* support for Java Date &amp; Time API types</li>
* <li><a href="https://github.com/FasterXML/jackson-module-kotlin">jackson-module-kotlin</a>:
* support for Kotlin classes and data classes</li>
* </ul>
@@ -57,10 +57,12 @@ public @interface PathVariable {
/**
* Whether the path variable is required.
* <p>Defaults to {@code true}, leading to an exception being thrown if the path
* variable is missing in the incoming request. Switch this to {@code false} if
* you prefer a {@code null} or Java 8 {@code java.util.Optional} in this case.
* for example, on a {@code ModelAttribute} method which serves for different requests.
* <p>Defaults to {@code true}, leading to an exception being thrown if the
* path variable is missing in the incoming request.
* <p>Switch this to {@code false} if you prefer a {@code null} or
* {@code java.util.Optional} if the path variable does not exist &mdash;
* for example, on a {@code ModelAttribute} method which serves for different
* requests.
* @since 4.3.3
*/
boolean required() default true;
@@ -57,9 +57,9 @@ public @interface RequestAttribute {
/**
* Whether the request attribute is required.
* <p>Defaults to {@code true}, leading to an exception being thrown if
* the attribute is missing. Switch this to {@code false} if you prefer
* a {@code null} or Java 8 {@code java.util.Optional} if the attribute
* doesn't exist.
* the attribute is missing.
* <p>Switch this to {@code false} if you prefer a {@code null} or
* {@code java.util.Optional} if the attribute does not exist.
*/
boolean required() default true;
@@ -66,8 +66,8 @@ public @interface SessionAttribute {
* Whether the session attribute is required.
* <p>Defaults to {@code true}, leading to an exception being thrown
* if the attribute is missing in the session or there is no session.
* Switch this to {@code false} if you prefer a {@code null} or Java 8
* {@code java.util.Optional} if the attribute doesn't exist.
* <p>Switch this to {@code false} if you prefer a {@code null} or
* {@code java.util.Optional} if the attribute does not exist.
*/
boolean required() default true;