This set of commits introduces support for a null-safe operator in the
Spring Expression Language (SpEL), including support for compiling
expressions that use the null-safe index operator.
Note, however, that compilation is not supported for null-safe indexing
into a String or any kind of Collection (other than a List).
See gh-21468
Closes gh-29847
Prior to this commit, SpEL's CompoundExpression omitted the null-safe
syntax in AST string representations of indexing operations.
To address this, this commit implements isNullSafe() in Indexer.
See gh-29847
Prior to this commit, SpEL's CompoundExpression omitted the null-safe
syntax in AST string representations of the selection and projection
operators.
To address this, this commit implements isNullSafe() in Projection and
Selection.
Closes gh-32515
Prior to this commit, MethodReference and PropertyOrFieldReference
already defined local isNullSafe() methods, but we need identical
methods in Selection, Projection, and Indexer, and we may potentially
need null-safe support for additional operators in the future.
To address the common need for an is-null-safe check, this commit
introduces an isNullSafe() method in SpelNodeImpl with a default
implementation that returns false.
Closes gh-32516
Prior to this commit when a required parameter defined as a property or
expression placeholder was missing, the exception thrown would refer to
the placeholder instead of the resolved name.
This change covers messaging handlers and web controllers, both blocking
and reactive. It also fixes the error message when handling null values
for non-required parameters, as well as in cases that need conversion.
See gh-32323
Closes gh-32462
Prior to this commit, the SpEL compiler generated classes in a package
named "spel" with names following the pattern "Ex#", where # was an
index starting with 2.
This resulted in class names such as:
- spel.Ex2
- spel.Ex3
This commit improves the names of classes created by the SpEL compiler
by generating classes in a package named
"org.springframework.expression.spel.generated" with names following
the pattern "CompiledExpression#####", where ##### is a 0-padded
counter starting with 00001.
This results in class names such as:
- org.springframework.expression.spel.generated.CompiledExpression00001
- org.springframework.expression.spel.generated.CompiledExpression00002
This commit also moves the saveGeneratedClassFile() method from
SpelCompilationCoverageTests to SpelCompiler and enhances it to:
- Save classes in a "build/generated-classes" directory.
- Convert package names to directories.
- Create missing parent directories.
- Use logging instead of System.out.println().
Running a test with saveGeneratedClassFile() enabled now logs something
similar to the following.
DEBUG o.s.e.s.s.SpelCompiler - Saving compiled SpEL expression [(#root.empty ? 0 : #root.size)] to [/Users/<username>/spring-framework/spring-expression/build/generated-classes/org/springframework/expression/spel/generated/CompiledExpression00001.class]
Closes gh-32497
The ApplicationContext has a resource cache that it uses while the
context is being refreshed. Once the refresh phase completes, the
cache is cleared as its content is no longer in use. If beans are
lazily initialized, there is a case where the cache might be filled
again as processing is deferred past the refresh phase.
For those cases, the cache is not cleared. This can be a problem when
running in this mode with a large set of test configurations as the TCF
caches the related contexts.
This commit includes an additional TestExecutionListener to the TCF that
clears the resource cache if necessary once a test class completes. It
is ordered so that it runs after `@DirtiesContext` support as marking
the context as dirty will remove it from the cache and make that extra
step unnecessary.
Closes gh-30954
This commit introduces null-safety checks for spring-core at build-time
in order to validate the consistency of Spring null-safety annotations
and generate errors when inconsistencies are detected during a build
(similar to what is done with Checkstyle).
In order to make that possible, this commit also introduces a new
org.springframework.lang.Contract annotation inspired from
org.jetbrains.annotations.Contract, which allows to specify semantics
of methods like Assert#notNull in order to prevent artificial
additional null checks in Spring Framework code base.
This commit only checks org.springframework.core package, follow-up
commits will also extend the analysis to other modules, after related
null-safety refinements.
See gh-32475
The fix for #31254 resulted in an InvalidMimeTypeException being thrown
by MimeTypeUtils.sortBySpecificity() instead of an
IllegalArgumentException. However, InvalidMimeTypeException extends
IllegalArgumentException. Consequently, the change from
IllegalArgumentException to InvalidMimeTypeException did not result in
the desired effect in HeaderContentNegotiationStrategy.
HeaderContentNegotiationStrategy.resolveMediaTypes() still allows the
InvalidMimeTypeException to propagate as-is without wrapping it in an
HttpMediaTypeNotAcceptableException.
To address this issue, this commit catches InvalidMediaTypeException
and InvalidMimeTypeException in HeaderContentNegotiationStrategy and
wraps the exception in an HttpMediaTypeNotAcceptableException.
See gh-31254
See gh-31769
Closes gh-32483