Compare commits

...

1068 Commits

Author SHA1 Message Date
Spring Buildmaster f57e1a3fad Release version 5.0.11.RELEASE 2018-11-27 08:53:58 +00:00
Juergen Hoeller 0761446c04 Revised alias definition example in reference documentation
Issue: SPR-17536
2018-11-25 22:18:26 +01:00
Juergen Hoeller 7b2eebe99f ResolvableType-based matching consistently respects generic factory method return type (even for pre-initialized raw singleton instance)
Issue: SPR-17524

(cherry picked from commit ebbe14c363)
2018-11-25 22:18:09 +01:00
Juergen Hoeller cf31f020a2 Upgrade to Hibernate Validator 6.0.13 and EclipseLink 2.7.3
Also includes Hibernate ORM 5.1.16 for integration tests.
2018-11-24 15:12:02 +01:00
Juergen Hoeller 02616fbabd Upgrade to Kotlin 1.2.71, OkHttp 3.12, FreeMarker 2.3.28
Also includes Apache HttpClient 4.5.6 and HttpAsyncClient 4.1.4.
2018-11-24 14:44:57 +01:00
Juergen Hoeller 4a51acbeb2 DefaultResponseErrorHandler detects non-standard error code as well
Issue: SPR-17439
2018-11-23 19:12:41 +01:00
Juergen Hoeller 3d7e373e5a Polishing
(cherry picked from commit 77ab88b144)
2018-11-23 19:12:30 +01:00
Sam Brannen f0e69e06b7 Ensure that MethodParameter.findParameterIndex() is thread-safe
Prior to this commit, parallel invocations of
MethodParameter.findParameterIndex() (invoked indirectly via
SynthesizingMethodParameter.forParameter() and
MethodParameter.forParameter()) could intermittently lead to an
IllegalArgumentException being thrown due to a race condition in the
internal implementation of the JDK's
java.lang.reflect.Executable.getParameters() method.

This commit addresses this issue by introducing a fallback for-loop
that iterates over the candidate parameters a second time using
equality checks instead of identity checks.

Issue: SPR-17534

(cherry-picked from commit 81fde5ec41)
2018-11-23 17:38:42 +01:00
Sam Brannen cd67b285e1 Ensure that parameter resolution in SpringExtension is thread-safe
Prior to this commit, parallel execution of @BeforeEach and @AfterEach
methods that accepted @Autowired arguments would fail intermittently
due to a race condition in the internal implementation of the JDK's
java.lang.reflect.Executable.getParameters() method.

This commit addresses this issue by creating instances of
SynthesizingMethodParameter via
SynthesizingMethodParameter.forExecutable(Executable, int) instead of
SynthesizingMethodParameter.forParameter(Parameter), since the latter
looks up the parameter index by iterating over the array returned by
Executable.getParameters() (which is not thread-safe).

Issue: SPR-17533
2018-11-23 17:00:38 +01:00
Juergen Hoeller 39925c334d Polishing 2018-11-22 20:38:26 +01:00
Juergen Hoeller 2e55486cc3 Upgrade to Reactor Bismuth SR14, Tomcat 8.5.35, Jetty 9.4.14 2018-11-22 17:45:16 +01:00
Juergen Hoeller e2b74e6943 Polishing 2018-11-22 17:44:29 +01:00
Juergen Hoeller 5382260f30 Client/ServerRequest defensively accesses internal attribute map
Issue: SPR-17486
2018-11-22 17:43:53 +01:00
Juergen Hoeller 35da9f1ddf FastByteArrayOutputStream.read byte-to-int conversion
Issue: SPR-17492
2018-11-22 17:43:31 +01:00
Juergen Hoeller e6c979606c Nullability fine-tuning based on IntelliJ IDEA 2018.3 inspection
Issue: SPR-15540

(cherry picked from commit bf272b0b21)
2018-11-22 17:43:13 +01:00
Juergen Hoeller 23d1049363 CachingMetadataReaderFactory releases shared cache Map on clearCache()
LocalResourceCache properly initializes cacheLimit on construction.

Issue: SPR-17527

(cherry picked from commit 262c702da4)
2018-11-22 17:42:27 +01:00
Juergen Hoeller 37a50d701e SerializedBeanFactoryReference falls back to dummy with specific id
Issue: SPR-17508

(cherry picked from commit f5aeb81473)
2018-11-22 17:42:06 +01:00
Rossen Stoyanchev 567fcc41cc ForwardedHeaderTransformer handles encoding correctly
Issue: SPR-17525
2018-11-21 11:17:10 -05:00
Rossen Stoyanchev 97dac8a45d Update @since version after backport 2018-11-21 09:36:34 -05:00
Rossen Stoyanchev 736b3c45e8 BEST_MATCHING_HANDLER_ATTRIBUTE for spring-webmvc
Issue: SPR-17518
2018-11-21 09:24:35 -05:00
Brian Clozel 617b94afb6 Polish
See SPR-17502
2018-11-20 18:03:07 +01:00
Brian Clozel 5342c6e493 Remove Content-Length response header from errors
Prior to this commit, when errors happened before the response was
committed, the `Content-Length` response header would be left as is.
This can be problematic since the error can be handled later in the
chain and the response body changed accordingly. For example, Spring
Boot renders error pages in those cases. If the `Content-Length` is set,
HTTP clients can get confused and only consider part of the error
response body.

This commit ensures that any `Content-Length` response header is removed
in case of errors, if the response is not already committed.

This is done at the `AbstractServerHttpResponse` level, since errors can
be handled in multiple places and the response itself is the safest
place to handle this case.

As a consequence, this commit also removes `Content-Length` checks in
`EncoderHttpMessageWriter` since we now consider that we should rely on
the response body we're about to write rather than any previously set
value.

Issue: SPR-17502
(Cherry-picked from 3203d39821)
2018-11-19 16:06:32 +01:00
Rossen Stoyanchev 18da718bf5 Enforce use of unpooled data buffers in 5.0.x
Issue: SPR-17501
2018-11-16 11:26:54 -05:00
Rossen Stoyanchev 24051619a5 Consistent encoding in DefaultUriBuilderFactory
Unlike 5,1, TEMPLATE_AND_VALUES is not the default encoding mode.
Nevertheless when that mode is used, it should work consistently.

Issue: SPR-17465
2018-11-09 14:50:39 -05:00
Rossen Stoyanchev f73a5222f1 Ensure client response is drained with onStatus hook
Issue: SPR-17473
2018-11-08 22:33:37 -05:00
Juergen Hoeller 8a2262e210 Up-to-date version and link in ASM/CGLIB/Objenesis package javadoc
Issue: SPR-14514
Issue: SPR-15600
2018-11-08 17:06:54 +01:00
Juergen Hoeller 0167b79d7b Consistently return empty array in case of empty batch arguments
Issue: SPR-17476

(cherry picked from commit 362c59c310)
2018-11-08 13:57:42 +01:00
Juergen Hoeller b462ca22a5 Upgrade to Reactor Bismuth SR13 (and Netty 4.1.31)
Issue: SPR-17306
2018-11-05 22:42:42 +01:00
Juergen Hoeller 4bd95663f9 Polishing
(cherry picked from commit 5e7a8b275d)
2018-11-05 22:42:27 +01:00
Juergen Hoeller 561511f66c Explicit notes on class/method-level semantics in class hierarchies
Issue: SPR-17445

(cherry picked from commit ea3250c8d6)
2018-11-05 22:33:20 +01:00
Juergen Hoeller 88f4e9205a Synchronized onRefresh execution for concurrent ContextRefreshedEvent
Issue: SPR-17442

(cherry picked from commit b1f5f51503)
2018-11-05 22:32:47 +01:00
Juergen Hoeller 591e7f1f72 StandardEvaluationContext supports concurrent variable modification
Issue: SPR-17448

(cherry picked from commit 59fa647e2d)
2018-11-05 22:32:21 +01:00
Juergen Hoeller c834790135 Deprecate ReflectionUtils.invokeJdbcMethod (for removal in 5.2)
Includes deprecation of NON_BRIDGED_METHODS constant.

Issue: SPR-17464

(cherry picked from commit 0a7dcf14f9)
2018-11-05 22:32:04 +01:00
Rossen Stoyanchev 9b4f48309a Fix formatting on index.adoc 2018-11-05 13:16:27 -05:00
Rossen Stoyanchev 8013566d99 Feature Github Wiki more prominently
Issue: SPR-17469
2018-11-05 13:13:39 -05:00
Rossen Stoyanchev 3bb11a0123 Fix failing test
After the fix #658c7f for lenient parsing of dates, the error message
raised uses an HttpHeaders-formatted date. As a result the test
verifying the error message fails in the beginning of the month between
1-9 because it's formatted slightly differently.
2018-11-01 15:46:28 -04:00
Juergen Hoeller e28a995ab7 Consistent check for Void.class in DefaultClientResponse
Issue: SPR-16636
2018-10-27 15:19:55 +02:00
Juergen Hoeller c10a8bb3b8 Exclude FactoryBean implementation methods on CGLIB proxies as well
Issue: SPR-17374

(cherry picked from commit dc1e3b4628)
2018-10-27 15:19:12 +02:00
Brian Clozel 2d14bd7066 Configure ResourceUrlProvider in WebFlux
Prior to this commit, no `ResourceUrlProvider` was configured
in WebFlux (no bean was contributed by the WebFlux infrastructure).
Also, several `ResourceTransformer` instances that extend the
`ResourceTransformerSupport` base class need a `ResourceUrlProvider`
to resolve absolute URLs when rewriting resource URLs. At this point,
no `ResourceUrlProvider` was configured and they could only resolve
relative URLs.

This commit contributes a new `ResourceUrlProvider` to the WebFlux
configuration; this bean can be reused by the WebFlux infrastructure and
application code.

This also automatically configure this shared `ResourceUrlProvider`
instance on the resource chain where needed.

Issue: SPR-17433
(Cherry-picked from fc957e95bb)
2018-10-26 14:35:01 +02:00
Juergen Hoeller 2acfb2e0ff Polishing 2018-10-26 11:23:42 +02:00
Juergen Hoeller 3ceb05f63c Upgrade to Jackson 2.9.7, Netty 4.1.30, Tomcat 8.5.34, Undertow 1.4.26
Also includes Apache Johnzon 1.1.10 and JRuby 9.1.17.
2018-10-25 17:39:47 +02:00
Juergen Hoeller 9e2d024d8d Asciidoc revision (minor backport for addressing build-time warnings) 2018-10-25 17:39:47 +02:00
Brian Clozel 3b7c0fc1a1 Fix absolute paths when transforming resources
Prior to this commit, `ResourceTransformerSupport.toAbsolutePath`
would call `StringUtils.applyRelativePath` in all cases. But this
implementation is prepending the given path even if the relative path
starts with `"/"`.

This commit skips the entire operation if the given path is absolute,
i.e. it starts with `"/"`.

Issue: SPR-17432
(Cherry-picked from 2146e13787)
2018-10-25 17:35:26 +02:00
Juergen Hoeller d5f725d503 Polishing
(cherry picked from commit ffa032e78f)
2018-10-24 21:24:42 +02:00
Juergen Hoeller c9f1016581 ConfigurableWebApplicationContext needed for contextClass parameter
Issue: SPR-17414

(cherry picked from commit 1c67ef4bed)
2018-10-24 21:24:42 +02:00
Juergen Hoeller 110796375b SpringFactoriesLoader tolerates whitespace around class names
Issue: SPR-17413

(cherry picked from commit dd2ce20687)
2018-10-24 21:24:42 +02:00
Juergen Hoeller b87ce596a0 Avoid stacktrace if root resource is not resolvable in file system
Issue: SPR-17417

(cherry picked from commit 83a54dba7e)
2018-10-24 21:24:42 +02:00
Juergen Hoeller 5a6c081cfe Clarify FactoryBean initialization effect in getBeanNamesForAnnotation
Issue: SPR-17392

(cherry picked from commit da23505e94)
2018-10-24 21:24:42 +02:00
Juergen Hoeller c73b98cf33 Clarify destruction order effect in @DependsOn annotation javadoc
Issue: SPR-17384

(cherry picked from commit 00b7782b5f)
2018-10-24 21:24:42 +02:00
Brian Clozel cf25efc7d3 Fix ResourceUrlEncodingFilter lifecycle
Prior to this commit, the `ResourceUrlEncodingFilter` would wrap the
response and keep a reference to the request. When
`HttpServletResponse.encodeURL` is later called during view rendering,
the filter looks at the request and extracts context mapping information
in order to resolve resource paths in views.

This approach is flawed, when the filter is used with JSPs - if the
request is forwarded to the container by the `InternalResourceView`,
the request information is overwritten by the container. When the view
is being rendered, the information available in the request is outdated
and does not allow to correctly compute that context mapping
information.

This commit ensures that that information is being extracted from the
request as soon as the `ResourceUrlProvider` is set as a request
attribute.

Issue: SPR-17421
(Cherry-picked from 50a4769162)
2018-10-24 21:19:33 +02:00
Rossen Stoyanchev 36510cf808 Server adapters release buffers on error/cancel
Review and update Servlet and Undertow adapters to release any data
buffers they be holding on to at the time of error or cancellation.

Also remove onDiscard hooks from Reactor and Undertow request body.
For Reactor we expect it to be handled. For Undertow there isn't
any Reactor Core upstream for the callback to be useful.

Issue: SPR-17410
2018-10-23 20:56:08 -04:00
Rossen Stoyanchev d492d7b6a4 Update ref docs on ResponseEntity and reactive types
Issue: SPR-17400
2018-10-23 17:06:02 -04:00
Rossen Stoyanchev bf4d00cb62 Upgrade to Reactor Bismuth snapshots
Towards SR13 to confirm fix for SPR-17306.
2018-10-23 15:49:09 -04:00
Rossen Stoyanchev 6ea3441adf Restore log level for resolved exceptions
The fix for SPR-17178 switched from debug to warn level warning for
all sub-classes of AbstractHandlerExceptionResolver where the request
concerned the DefaultHandlerExceptionResolver only.

This commit restores the original DEBUG level logging that was in
AbstractHandlerExceptionResolver from before SPR-17178. In addition
DefaultHandlerExceptionResolver registers a warnLogCategory by default
which enables warn logging and hence fulfilling the original goal
for SPR-17178.

Issue: SPR-17383
2018-10-22 12:18:33 -04:00
Sebastien Deleuze 73db2081cd Leverage Java reflection for Kotlin enums
As discussed in KT-25165, from a Kotlin POV enum constructors
have no parameter, this is an "implementation detail"
required for running on the JVM, so it seems relevant to skip
Kotlin reflection in that case and just delegate to Java
reflection.

Issue: SPR-16931
2018-10-16 16:42:31 +02:00
Spring Buildmaster 38490f13b1 Next Development Version 2018-10-15 08:01:59 +00:00
Rossen Stoyanchev c8e320019f HttpRange validates requested ranges
Issue: SPR-17318
2018-10-14 22:53:33 -04:00
Juergen Hoeller 973eb5deb6 MethodValidationInterceptor excludes FactoryBean metadata methods
Issue: SPR-17374

(cherry picked from commit 5f2d47a17e)
2018-10-14 21:16:01 +02:00
Rossen Stoyanchev b89cb20b1d Lenient date parsing in HeadersResultMatchers
Rather than formatting the expected value, and be susceptible to
minor formatting differences (e.g. 01 vs 1 for day of month), parse the
actual header value leniently with HttpHeaders and compare time values.

Issue: SPR-17330
2018-10-12 15:51:32 -04:00
Juergen Hoeller 52ed4226bd Tests for MockHttpServletRequestTests.setContent reset in 5.0.x
Issue: SPR-17373
2018-10-12 17:57:07 +02:00
volkovandr b0433810da Updated Javadoc: date format patterns SPR-17366
(cherry picked from commit 61403e3bd3)
2018-10-12 17:56:58 +02:00
Christian Kulpa db2c807515 Fix deprecated property in MBeanExporter documentation 2018-10-12 16:30:11 +02:00
Juergen Hoeller a45bce1369 Polishing 2018-10-10 00:15:58 +02:00
Juergen Hoeller 8d1499e168 Comparators.nullsLow creates right kind of NullSafeComparator
Issue: SPR-17357
2018-10-10 00:15:50 +02:00
Juergen Hoeller ff0afcff06 Resource.lastModified() propagates 0 value if target resource exists
Includes consistent use of getContentLengthLong over getContentLength.

Issue: SPR-17320
2018-10-10 00:15:27 +02:00
Juergen Hoeller 53430760f3 Consistent exposure of empty attribute arrays in AnnotationMetadata
Issue: SPR-17347

(cherry picked from commit 83909e6e1e)
2018-10-10 00:15:04 +02:00
Juergen Hoeller d61a7ed1f0 AbstractApplicationContext.getApplicationListeners() exposes all statically registered listeners
Issue: SPR-17324

(cherry picked from commit c8c0737ce7)
2018-10-10 00:14:48 +02:00
Juergen Hoeller ca0ce7d631 AbstractApplicationEventMulticaster pre-sorts singleton listeners
Issue: SPR-17307

(cherry picked from commit 9063e66c5d)
2018-10-10 00:14:39 +02:00
Rossen Stoyanchev fc2f3ecf44 More defensive check for MockAsyncContext
Avoid automatically unwrapping the request in TestDispatcherServlet,
if we find the MockAsyncContext.

Issue: SPR-17353
2018-10-09 11:57:34 -04:00
Rossen Stoyanchev d551710c32 Restore calls to setLocale in MockHttpServletResponse
Issue: SPR-17284
2018-10-05 13:53:19 -04:00
Rossen Stoyanchev 6fe8cb949f Workaround for Synchronoss content-length limitation
Issue: SPR-17345
2018-10-05 13:52:58 -04:00
dmrachkovskyi 842297699d Defer obtaining argument resolver default value
Issue: SPR-17338
2018-10-05 13:52:28 -04:00
Juergen Hoeller d90d65bad2 Polishing 2018-09-29 17:36:15 +02:00
Juergen Hoeller a21ce42558 MockHttpServletRequest allows for removing registered header entries
Issue: SPR-17295
2018-09-29 17:36:03 +02:00
Juergen Hoeller e54eb56cb9 Revised javadoc for up-to-date constructor autowiring semantics
Issue: SPR-17299

(cherry picked from commit 333e327289)
2018-09-29 17:35:55 +02:00
Juergen Hoeller f5e6c707ae Polishing 2018-09-19 22:51:35 +02:00
Juergen Hoeller c0b0ee6db7 Polishing 2018-09-18 21:54:48 +02:00
Juergen Hoeller 4642c32c0f Defensively expect concurrent registration of BeanPostProcessors
Declaring beanPostProcessors (and also embeddedValueResolvers) as CopyOnWriteArrayList prevents ConcurrentModificationExceptions in case of concurrent registration/access attempts.

Issue: SPR-17286
2018-09-18 21:54:33 +02:00
Juergen Hoeller a55261f82d Polishing 2018-09-17 15:00:33 +02:00
Juergen Hoeller 5ca2c56cf0 Polishing 2018-09-17 14:39:54 +02:00
Juergen Hoeller 702d533e6f Polishing 2018-09-14 23:59:45 +02:00
Juergen Hoeller 1535f985be Polishing 2018-09-14 14:30:03 +02:00
Juergen Hoeller 94ae933122 Upgrade to Rhino 1.7.10 and Apache Johnzon 1.1.9
Includes reordering of web dependency declarations.
2018-09-14 14:29:57 +02:00
Arjen Poutsma 952315c333 DataBufferUtils does not release DataBuffer on error cases
This commit makes sure that in DataBufferUtils.write, any received data
buffers are returned as part of the returned flux, even when an error
occurs or is received.

Issue: SPR-16782

(cherry picked from commit 1a0522b805)
2018-09-12 14:58:37 +02:00
Arjen Poutsma a00607348c Fixed DataBufferUtils.join leak for error in source
This commit fixes an issue where DataBufferUtils.join() would not
release databuffers that preceded an error signal.

Issue: SPR-17025

(cherry picked from commit 196c0adf47)
2018-09-12 14:45:45 +02:00
Juergen Hoeller 1d58fac54d UriComponentsBuilder copies query params through MultiValueMap.addAll
Issue: SPR-17256
2018-09-11 15:15:15 +02:00
Juergen Hoeller 658bd7a686 Correct linkplain javadoc in BufferingClientHttpRequestFactory
Issue: SPR-17261

(cherry picked from commit e47355078c)
2018-09-11 15:15:00 +02:00
Juergen Hoeller 717e6dd2d9 Revise ServletUriComponentsBuilder javadoc
Issue: SPR-17255
2018-09-07 18:21:25 +02:00
Spring Buildmaster 7f82c192f5 Next Development Version 2018-09-07 12:16:08 +00:00
Juergen Hoeller dcdd08c432 Remove declaration for snapshot repository 2018-09-07 13:13:06 +02:00
Juergen Hoeller 06ed818f4c Fix SpEL compilation for non trivial elvis operand
Issue: SPR-17214
2018-09-07 13:12:53 +02:00
Juergen Hoeller ad5447253c ConfigurationClassParser consistently uses ClassUtils.forName
Issue: SPR-17253

(cherry picked from commit c803ad7998)
2018-09-07 13:12:26 +02:00
Juergen Hoeller 7653762240 XMLEventReader.getElementText() properly checks for start element
Issue: SPR-17233

(cherry picked from commit 84ec382201)
2018-09-07 13:12:10 +02:00
Sebastien Deleuze 89fca1b949 Fix Kotlin inner class nested configuration handling
Before this commit, Kotlin inner class nested configuration
handling thrown an IndexOutOfBoundsException due to bogus filtering
of its constructor parameter reference to an instance of the outer
class.

This commit keep constructor parameter of type INSTANCE in order to
throw a more meaningful NoSuchBeanDefinitionException.

Issue: SPR-17222
2018-09-07 11:42:23 +02:00
Rossen Stoyanchev 92bb76f3cd Disable Jackson's buffer recyling feature for WebFlux
Issue: SPR-17193
2018-09-06 16:21:27 -04:00
Stephane Nicoll 4b6a5fbd13 Upgrade to Reactor Bismuth SR11 2018-09-06 15:38:15 +02:00
Rossen Stoyanchev b17e7c321a Use random id for WebSocket sessions
Issue: SPR-17228
2018-09-05 19:49:50 -04:00
Toshiaki Maki ee559bb2c8 Use long for expires and lastModified in HeaderAssertions
This commit changes the type of parameters so that HeaderAssertions
can assert expires and lastModified properly.

Issue: SPR-17194
2018-09-05 17:26:42 -04:00
Brian Clozel 1371cfe301 Upgrade to Jetty 9.4.12.v20180830
(Cherry-picked from 7041e5e8e3)
2018-09-04 22:15:13 +02:00
Juergen Hoeller 04814e604e Polishing
(cherry picked from commit 95a56cd28d)
2018-08-31 12:57:31 +02:00
Juergen Hoeller e332e32a88 SpelExpression consistently exposes EvaluationContext to compiled AST
Operator includes explicit support for Boolean comparisons now.

Issue: SPR-17229

(cherry picked from commit 51cee658d5)
2018-08-31 12:57:23 +02:00
Juergen Hoeller 648fa60f48 Transactional timeout documented as seconds in annotation javadoc
Issue: SPR-17226

(cherry picked from commit 8c6f3505c4)
2018-08-31 12:57:12 +02:00
Brian Clozel 4004f92e3f Switch back to Reactor Bismuth SNAPTHOTs
Preparing for Bismut-SR11
2018-08-30 16:52:21 +02:00
Brian Clozel 6189e17d7c Fix empty body writing in EncoderHttpMessageWriter
Prior to this commit, an bug introduced in SPR-16949 prevented
`Mono.empty` bodies from being written to the response.

This commit ensures that empty bodies still trigger the writing to the
response and does not hang the processing of the exchange.

Issue: SPR-17220
Cherry-picked from: 280da61d5c
2018-08-27 21:19:12 +02:00
Juergen Hoeller 1e8cb5fc59 Upgrade to RxJava 2.1.17, Tomcat 8.5.33, Netty 4.1.29 2018-08-24 12:58:04 +02:00
Juergen Hoeller b5270a9cff Polishing 2018-08-24 12:39:03 +02:00
Juergen Hoeller a44fe4cbe4 Support Jackson filters in combination with serialization view
Issue: SPR-17209

(cherry picked from commit 03f1920106)
2018-08-24 12:38:51 +02:00
Kyle Carter abb92b6966 Fix usage of deprecated functionality in docs
Closes gh-1934
2018-08-20 09:44:31 +02:00
Juergen Hoeller 68cf18f4a3 SimpleAliasRegistry.hasAlias properly resolves multiple chained aliases
Issue: SPR-17191

(cherry picked from commit 2ac23badee)
2018-08-17 09:58:55 +02:00
Juergen Hoeller 92228f9e64 Fix recent javadoc errors
Issue: SPR-17174
2018-08-16 19:24:38 +02:00
Juergen Hoeller fb083a3776 Consistently use double quotes (even if no interpolation needed) 2018-08-16 15:53:37 +02:00
Juergen Hoeller f532de5a8a Polishing 2018-08-16 12:21:49 +02:00
Juergen Hoeller 6b3dd0779f Consistently skip unnecessary search on superclasses and empty elements
Issue: SPR-16933
2018-08-15 17:56:03 +02:00
Rossen Stoyanchev bf7fa39a48 Consistent logging of resolved exceptions
Issue: SPR-17178
2018-08-15 11:10:35 +03:00
Juergen Hoeller 37db3ba834 Polishing
(cherry picked from commit 6027cf2255)
2018-08-14 21:45:25 +02:00
Juergen Hoeller 4b2a0471e1 Revised documentation for PDF, Excel and JSON views
Issue: SPR-17180
Issue: SPR-17182

(cherry picked from commit c0c9e08bf9)
2018-08-14 21:45:17 +02:00
Juergen Hoeller 7894ecf445 Polishing 2018-08-13 14:29:36 +02:00
Juergen Hoeller 0e3f23eeb7 Polishing 2018-08-13 13:42:19 +02:00
Sam Brannen e306d3e83a Generate “Use” links in aggregated Spring API JavaDoc
This commit enables the `-use` javadoc flag so that class usage pages
are included in the aggregated JavaDoc that is published to
https://docs.spring.io/spring-framework/docs/.

Issue: SPR-17173
2018-08-13 11:59:35 +02:00
Rossen Stoyanchev f23496ae32 Fix URI var encoding issue with '$'
When expanding and strictly encoding URI variables, there is no need to
quote `/` and `$` which will be encoded anyway.

Issue: SPR-17168
2018-08-13 11:57:44 +03:00
Juergen Hoeller 1d8e5f4d85 Revert to Map entry iteration for less expensive static initialization
Issue: SPR-17169

(cherry picked from commit df51ff0386)
2018-08-12 21:02:26 +02:00
Juergen Hoeller d8aecd8c87 Post-processors consistently ignore ScopedObject/AopInfrastructureBean
Issue: SPR-17166
2018-08-12 14:36:20 +02:00
Stephane Nicoll 6ed03c24ac Disable quotes substitution in code sample
Issue: SPR-17167
2018-08-12 11:13:21 +02:00
Juergen Hoeller 9c1cbbb689 Post-processors consistently ignore ScopedObject/AopInfrastructureBean
Issue: SPR-17166
2018-08-11 22:46:17 +02:00
Juergen Hoeller 67d0c69a95 Polishing 2018-08-11 01:30:32 +02:00
Juergen Hoeller 951b39cc7a Polishing 2018-08-10 18:00:17 +02:00
Juergen Hoeller 1695ef7e87 Polishing 2018-08-09 18:07:03 +02:00
Juergen Hoeller 6f41d4ec4d DefaultLifecycleProcessor properly counts dependent beans in same phase
Issue: SPR-16901
2018-08-09 17:56:50 +02:00
Juergen Hoeller 42dbc39032 Polishing
(cherry picked from commit 8e571decc1)
2018-08-09 12:15:23 +02:00
Rossen Stoyanchev 1d45e326b7 Fix link from Spring MVC to OXM chapter 2018-08-09 10:29:10 +03:00
Juergen Hoeller 7737175140 Polishing 2018-08-09 03:02:52 +02:00
Juergen Hoeller e00fd52dc6 Polishing 2018-08-09 02:30:10 +02:00
Juergen Hoeller a159dd5993 AbstractAspectJAdvisorFactory uses AnnotationUtils.getValue 2018-08-09 02:07:00 +02:00
Juergen Hoeller d8d04d82c1 Polishing 2018-08-09 01:41:45 +02:00
Juergen Hoeller f3184a0878 Polishing 2018-08-09 00:49:54 +02:00
Juergen Hoeller 688ef9ad46 Find annotations on implemented generic superclass methods as well
Includes Java 8 getDeclaredAnnotation shortcut for lookup on Class.

Issue: SPR-17146

(cherry picked from commit 4521a79b2d)
2018-08-09 00:49:46 +02:00
Juergen Hoeller 9580bbd59f Expose checkbox field marker as 'hidden' to RequestDataValueProcessor
Issue: SPR-17147

(cherry picked from commit fa72186e28)
2018-08-09 00:49:39 +02:00
Juergen Hoeller a9305dbe8b ConcurrentModel ignores null value for put (also used by putAll)
Issue: SPR-17141

(cherry picked from commit b8b6367f9b)
2018-08-09 00:49:33 +02:00
Kazuhiro Sera a80f4caf37 Fix typos detected by github.com/client9/misspell
(cherry picked from commit be211ceead)
2018-08-09 00:49:27 +02:00
Rossen Stoyanchev eaafcee077 Proper use of setComplete in ContextPathCompositeHandler
Issue: SPR-17144
2018-08-08 16:41:50 +03:00
Juergen Hoeller a45ef35b38 Pruning of outdated JDK 6/7 references (plus related polishing)
(cherry picked from commit b325c74216)
2018-08-07 21:08:26 +02:00
Juergen Hoeller b87ee4ca32 ConcurrentModel.addAttribute(String, Object) ignores null value
Issue: SPR-17141

(cherry picked from commit 34ddb88851)
2018-08-07 21:08:18 +02:00
Juergen Hoeller 737ece71ca Polishing 2018-08-07 02:48:04 +02:00
Juergen Hoeller a938f528e2 Polishing 2018-08-07 02:41:18 +02:00
Juergen Hoeller 2b593b0b06 Upgrade to Log4J 2.11.1 2018-08-07 02:12:12 +02:00
Juergen Hoeller 4042c1d578 Polishing 2018-08-07 02:12:00 +02:00
Juergen Hoeller 34052945de Avoid unnecessary annotation introspection on framework methods
Issue: SPR-16933
2018-08-07 02:11:54 +02:00
Juergen Hoeller c814f5821a DisposableBean javadoc refers to singletons as well as scoped beans
Issue: SPR-17131

(cherry picked from commit f155d21c95)
2018-08-07 02:11:42 +02:00
Rossen Stoyanchev 6562e3047f takeUntilByteCount actually uses takeUntil
Issue: SPR-17188
2018-08-02 21:20:20 +03:00
Rossen Stoyanchev 0d0a0a2d08 Polish 2018-08-02 21:20:08 +03:00
Juergen Hoeller 08b5921fff Polishing 2018-08-02 17:45:46 +02:00
Juergen Hoeller f9307897b6 Polishing
(cherry picked from commit 2474c48749)
2018-08-02 17:18:08 +02:00
Juergen Hoeller f4c0421a7d Polishing
(cherry picked from commit dc36bb34c7)
2018-08-02 14:55:28 +02:00
Juergen Hoeller ecf6c381be SchedulerAccessor catches cluster race conditions on job rescheduling
Issue: SPR-17114

(cherry picked from commit fa97aab8be)
2018-08-02 14:55:22 +02:00
Juergen Hoeller 55e8aea2a3 Polishing 2018-08-01 12:35:01 +02:00
Juergen Hoeller 77e75fdf87 Avoid synthesizable annotation creation for @Bean/@Scope on scanning
Includes consistent (non-)use of AnnotationUtils/AnnotatedElementUtils.

Issue: SPR-16933
2018-08-01 12:18:10 +02:00
Juergen Hoeller 8c1290084d Polishing 2018-07-31 23:40:36 +02:00
Rossen Stoyanchev 4133355b72 Typo in URI Encoding section
Issue: SPR-17104
2018-07-31 23:28:08 +03:00
Rossen Stoyanchev 7476c5d5db Revert ""Order of messages" in STOMP section of reference docs"
This reverts commit dc066b0530 which
wasn't meant to be added to 5.0.x where the feature does not exist.
2018-07-31 23:15:49 +03:00
Juergen Hoeller fd75600c26 Polishing 2018-07-31 21:37:40 +02:00
Juergen Hoeller a4be54d760 Avoid synthesizable check for common annotation types
This revision immediately returns false from isSynthesizable for java.lang.annotation types.

Issue: SPR-16933
2018-07-31 21:37:34 +02:00
Juergen Hoeller f791b827ec Correct 404 status code and refined resolution failure log message 2018-07-30 23:33:53 +02:00
Juergen Hoeller a65c7ef780 Polishing 2018-07-30 23:13:22 +02:00
Juergen Hoeller 2a32c6cf57 Nullability refinements in spring-webmvc
Includes revision of web.servlet.tags.form for non-null conventions.

Issue: SPR-15540

(cherry picked from commit f74a631ea1)
2018-07-30 22:33:11 +02:00
Juergen Hoeller 91fa2ed0d4 Initialize pre-filled HashMaps with large enough capacity
Empty Maps are preferably initialized without capacity (not initializing them at all or lazily initializing with default capacity when needed).

Issue: SPR-17105

(cherry picked from commit 4a147d26fc)
2018-07-30 22:33:04 +02:00
Juergen Hoeller 006db06d11 Polishing 2018-07-27 18:48:09 +02:00
Juergen Hoeller 6839570187 Polishing
(cherry picked from commit 1fd6248d84)
2018-07-27 18:20:29 +02:00
Rossen Stoyanchev 5f96d7c46c Add notes on future deprecation of the RestTemplate
Issue: SPR-16993
2018-07-27 08:43:26 -04:00
Juergen Hoeller cca8968a44 Polishing 2018-07-26 23:40:32 +02:00
Juergen Hoeller b6a049a088 Polishing
(cherry picked from commit 7c9ba80f85)
2018-07-26 23:27:28 +02:00
Rossen Stoyanchev 2d83051ce1 bindToApplicatonContext uses WebSessionManager bean
Issue: SPR-17094
2018-07-26 16:05:33 -04:00
Rossen Stoyanchev f9ff6d4192 Polish 2018-07-26 15:54:21 -04:00
Juergen Hoeller 514c28b7c0 Revise BeanFactory vs ApplicationContext section in reference docs
Issue: SPR-17095

(cherry picked from commit 8277ea5794)
2018-07-26 18:50:21 +02:00
Juergen Hoeller 5da58393c1 Polishing 2018-07-26 15:55:15 +02:00
Juergen Hoeller 79936d98de Properly identify event-related ClassCastExceptions on JDK 11
Issue: SPR-17093

(cherry picked from commit e458777925)
2018-07-26 15:07:10 +02:00
Spring Buildmaster 7dff7bb7a4 Next Development Version 2018-07-26 07:49:44 +00:00
Juergen Hoeller d7cf2c869c MethodBeforeAdviceInterceptor implements BeforeAdvice marker interface
Includes related polishing in the advice interceptor implementations.

Issue: SPR-17088

(cherry picked from commit 4e03d3fdcb)
2018-07-25 20:16:48 +02:00
Juergen Hoeller c89fb745f7 ListBasedXMLEventReader uses defensive modifiable copy of given List
(cherry picked from commit 9ab63b8494)
2018-07-25 19:06:55 +02:00
Juergen Hoeller e214ee5c85 Backport of WebMvcConfigurationSupport javadoc revision 2018-07-25 15:39:39 +02:00
Juergen Hoeller 93ef169c5c Polishing 2018-07-25 14:40:31 +02:00
Brian Clozel 407bd96cf3 ResponseEntityResultHandler overwrites headers
Prior to this commit, controller handlers (regular and exception
handlers as well) would not overwrite existing HTTP response headers on
the exchange. This would lead to situations where Content-Type values
set during the initial handling phase would not be overwritten when
handling an error later on.

This commit aligns the implementation of that result handler on the
Spring MVC one in that regard.

Issue: SPR-17082
(Cherry-picked from 195f3f07e7)
2018-07-24 22:23:52 +02:00
Juergen Hoeller 0b5c099de2 Polishing 2018-07-24 22:10:07 +02:00
Juergen Hoeller 4f9a18f5aa Order setter for DefaultSimpUserRegistry
Issue: SPR-17023
2018-07-24 18:56:52 +02:00
Rossen Stoyanchev 9b3d80c5e4 Update STOMP section on working with subscriptions
1. Revise @SubscribeMapping to address common points of confusion.
2. Add ExecutorSubsribableChannel.
3. Split Events and Interception in two.

Issue: SPR-16950
2018-07-24 12:25:41 -04:00
Rossen Stoyanchev dc066b0530 "Order of messages" in STOMP section of reference docs
Issue: SPR-13989
2018-07-24 12:23:39 -04:00
Juergen Hoeller 0c44b5224f Polishing
(cherry picked from commit dd4468a)
2018-07-24 16:34:56 +02:00
Juergen Hoeller 207e8c2409 BeanFactoryAdvisorRetrievalHelper avoids synchronization for name cache
Issue: SPR-16570

(cherry picked from commit 7f1a8d7)
2018-07-24 16:34:50 +02:00
Juergen Hoeller 2329588856 Upgrade to Mockito 2.19.1 2018-07-24 15:00:47 +02:00
Juergen Hoeller f677d684e7 Polishing 2018-07-24 15:00:35 +02:00
Juergen Hoeller 3878db2e8c Provide predetermined capacity for cache operation collections
Issue: SPR-17079

(cherry picked from commit 20c34cb)
2018-07-24 14:59:05 +02:00
Rossen Stoyanchev 24a113fb27 Ensure headers work with ResponseEntity + reactive body
Issue: SPR-17076
2018-07-24 00:26:01 -04:00
Juergen Hoeller e21db2619b AspectJExpressionPointcut leniently ignores non-composable interfaces
Issue: SPR-17003

(cherry picked from commit bccff73)
2018-07-22 22:35:32 +02:00
Juergen Hoeller f5dd4d2c02 Polishing 2018-07-22 19:33:40 +02:00
Juergen Hoeller 192113de60 Correctly determine and propagate validation hints to DataBinder
Issue: SPR-17073

(cherry picked from commit 3c65c17)
2018-07-21 12:34:55 +02:00
Brian Clozel f89511e7fe Switch order of multipart Content-Type directives
Since SPR-15205, the `FormHttpMessageConverter` is adding a `charset`
directive to the `Content-Type` request header in order to help servers
understand which charset is being used to encode headers of each part.

As reported in SPR-17030 and others, some servers are not parsing
properly such header values and assume that `boundary` is the last
directive in the `Content-Type` header.

This commit reorders the charset information right before the boundary
declaration to get around those issues.

Issue: SPR-17030
(Cherry-picked from 390bb871d8)
2018-07-20 18:16:53 +02:00
Juergen Hoeller c3f6403f61 Polishing 2018-07-20 16:45:17 +02:00
Rossen Stoyanchev 5007d01c17 Fix for encoding issue with MvcUriComponentsBuilder
Provide method for stronger encoding of expanded URI variables when
building links from views.

Issue: SPR-17027
2018-07-19 19:07:22 -04:00
Rossen Stoyanchev f1c55a3b4a UriComponentsBuilder method to configure URI variables
See Javadoc on UriComponentsBuilder#uriVariables for details.

This helps to prepare for SPR-17027 where the MvcUriComponentsBuilder
already does a partial expand but was forced to build UriComonents
and then create a new UriComponentsBuilder from it to continue. This
change makes it possible to stay with the same builder instance.

Issue: SPR-17027
2018-07-19 19:07:22 -04:00
Rossen Stoyanchev 34a0cdfc33 Minor fixes: UriComponentsBuilder, UriComponents, docs
After the latest changes, two small fixes in the clone method to copy
the encode flag, and in the encodeUriTemplate method to account for
possible null query params.

Improvements in the URI encoding section.

Issue: SPR-17039, SPR-17027
2018-07-19 19:07:22 -04:00
Juergen Hoeller 1cd0135195 Restore original DefaultAdvisorChainFactory MethodMatcher invocation
Includes test for @Async pointcut against AOP proxy without target.
2018-07-20 00:33:27 +02:00
Juergen Hoeller 0c5c3103c6 ReflectiveMethodExecutor skips interface search (plus related polishing) 2018-07-19 16:51:13 +02:00
Juergen Hoeller c66f9d8880 Javadoc update: ConfigurationClassPostProcessor is priority-ordered
Issue: SPR-17062

(cherry picked from commit 0b60447)
2018-07-19 13:24:48 +02:00
Juergen Hoeller 4d3a899a53 OrderUtils caches order values (for AnnotationAwareOrderComparator)
Issue: SPR-17064

(cherry picked from commit d0bbbf4)
2018-07-19 13:24:43 +02:00
Juergen Hoeller 11fc086309 Prefer ArrayList/ArrayDeque over LinkedList for multi-element holders
LinkedList remains in place where a List is likely to remain empty or single-element (in order to avoid unused capacity).

Issue: SPR-17037

(cherry picked from commit 9c08a48)
2018-07-19 00:08:13 +02:00
Juergen Hoeller ed54895e53 Consistent exposure of nested parameter type in binding exceptions 2018-07-18 19:56:06 +02:00
Juergen Hoeller b72594d799 Find annotations on implemented generic interface methods as well
Issue: SPR-16060

(cherry picked from commit 23d4862)
2018-07-18 19:56:00 +02:00
Juergen Hoeller 4341838a21 Polishing 2018-07-18 14:53:19 +02:00
Brian Clozel 58f58e404e Avoid null signals when resolving handler arguments
Prior to this commit, resolving an argument for a WebFlux controller
that's missing from the request and not required by the handler would
throw a NullPointerException in some cases.

This involves the conversion of the parameter (a `String` parameter type
might not trigger this behavior) and sending a `null` within a reactive
stream, which is illegal per the RS spec.

We now rely on a `Mono.justOrEmpty()` to handle those specific cases.

Issue: SPR-17050
(Cherry-picked from a7f97a1669)
2018-07-18 14:48:06 +02:00
Juergen Hoeller c0040a5508 Polishing 2018-07-18 14:03:54 +02:00
Juergen Hoeller 55563c16b5 StringUtils.parseLocaleString detects variant without country
The parseLocale method also turns an empty locale into null now, compatible with parseLocaleString behavior.

Includes tests for parsing all available locales on the JVM, checking toString/toLanguageTag equality between parsed and original locale.

Issue: SPR-7598
Issue: SPR-16651

(cherry picked from commit cab35aa)
2018-07-18 14:03:30 +02:00
Juergen Hoeller ae1d500bc3 UrlBasedViewResolver exposes redirect prefix as bean name
Issue: SPR-17045

(cherry picked from commit b8d2a16)
2018-07-18 13:59:32 +02:00
Juergen Hoeller 9134588a82 Never return null from AnnotationMetadata.getMetaAnnotationTypes
Issue: SPR-17046

(cherry picked from commit cacd14c)
2018-07-18 13:59:11 +02:00
Juergen Hoeller d283424c82 Update ref doc references to Number/Currency/PercentStyleFormatter
Issue: SPR-17022

(cherry picked from commit 39d4550)
2018-07-18 13:58:45 +02:00
Andrew McCallum 6e019f9ed0 Correct method signature in code example
Closes gh-1887
2018-07-18 09:08:29 +02:00
Rossen Stoyanchev d9d41b4398 Polish 2018-07-17 17:41:44 -04:00
Rossen Stoyanchev eac0ddce13 Update URI Encoding section 2018-07-17 15:58:47 -04:00
Rossen Stoyanchev a363a229eb Update URI links section after encoding changes
Issue: SPR-17039
2018-07-16 21:25:27 -04:00
Rossen Stoyanchev 2bf7c18203 Add TEMPLATE_AND_VALUES mode to DefaultUriBuilderFactory
Issue: SPR-17039
2018-07-16 21:25:09 -04:00
Rossen Stoyanchev 9458186e83 Polish DefaultUriBuilderFactory 2018-07-16 21:24:52 -04:00
Rossen Stoyanchev d81ec55a60 Support for encode() in UriComponentsBuilder
The ability to request to encode before `build()`, and more importantly
before expanding, allows stricter encoding to be applied to URI vars
and consequently to neutralize the effect of characters with reserved
meaning in a URI.

Issue: SPR-17039
2018-07-16 21:24:16 -04:00
Stephane Nicoll 4c8d81bcb4 Fix typo
Issue: SPR-17042
2018-07-15 16:18:25 +02:00
Rossen Stoyanchev 6218db9831 Backport of InMemoryWebSession changes
- hooks to check expired sessions in both create and retrieve.
- maxSessions limit on the total number of sessions.
- getSessions method for management purposes
- removeExpiredSessions public API

Issue: SPR-17020, SPR-16713
2018-07-12 16:27:42 -04:00
Rossen Stoyanchev 7ea8ecb6ab Warn when SimpleAsyncTaskExecutor is used
Issue: SPR-16203
2018-07-11 11:21:49 -04:00
Guilherme Alan Ritter 8c1bc63c9d Fix typo
Closes gh-1880
2018-07-10 15:48:40 +02:00
Rossen Stoyanchev f179181b40 Polish Reactive Spring Web section 2018-07-09 15:58:35 -04:00
Juergen Hoeller eb3254d2a9 Polishing 2018-07-06 15:18:47 +02:00
Juergen Hoeller 6cae0650e6 Upgrade to Jackson 2.9.6 2018-07-06 01:42:07 +02:00
Juergen Hoeller 43868d2b72 Polishing 2018-07-06 01:39:34 +02:00
Juergen Hoeller a8b747c21c Polishing 2018-07-04 22:55:38 +02:00
Juergen Hoeller 490b78a3d3 Polishing 2018-07-04 20:58:27 +02:00
Juergen Hoeller 1ab9e2ceda Polishing 2018-07-04 15:46:52 +02:00
Juergen Hoeller a1d35c23aa ConcurrentModel.addAttribute javadoc: null value not supported
Issue: SPR-16831
2018-07-04 15:45:53 +02:00
Juergen Hoeller 99534a31ba MapSqlParameterSource.addValue declares nullable value parameter
Issue: SPR-16843

(cherry picked from commit d9c6318)
2018-07-04 15:45:32 +02:00
Sebastien Deleuze c6dbfe42d3 Upgrade to Kotlin 1.2.51 2018-07-04 11:25:01 +02:00
Juergen Hoeller acf9ea097a Polishing 2018-07-03 17:11:27 +02:00
Juergen Hoeller decbb43757 Upgrade to Apache Johnzon 1.1.8 2018-07-03 16:23:51 +02:00
Juergen Hoeller 0480e75785 Polishing 2018-07-03 16:23:43 +02:00
Juergen Hoeller ac1e2879e5 Consistent throwing of HttpMessageNotReadableException (5.0.x revision)
Includes specific fine-tuning of ProtobufHttpMessageConverter and JAXB2 based message converters, as well as revised javadoc for abstract base classes.

Issue: SPR-16995
2018-07-03 16:23:36 +02:00
Juergen Hoeller ce0323fa8c ConcurrentReferenceHashMap caches EntrySet in volatile field
Includes an efficient implementation of isEmpty(), not relying on a full entry count but rather backing out once a non-empty hash segment has been found.

Issue: SPR-16994
2018-07-03 16:23:28 +02:00
Juergen Hoeller 0052c899bd Same method filtering in ConstructorResolver and getTypeForFactoryMethod
Issue: SPR-16999

(cherry picked from commit f2787cf)
2018-07-03 16:23:20 +02:00
Juergen Hoeller 8c07c6d099 Polishing 2018-07-01 02:35:35 +02:00
Juergen Hoeller 214fa9c2a0 Polishing 2018-06-29 22:43:13 +02:00
Juergen Hoeller ea534b6820 Polishing 2018-06-29 20:07:53 +02:00
Juergen Hoeller 5a111125c1 Up-to-date coverage of task executor and scheduler variants
Includes a clarification of ThreadPoolExecutor configuration options and a note on early AsyncConfigurer initialization.

Issue: SPR-16944
Issue: SPR-16945

(cherry picked from commit d58c09b)
2018-06-29 20:07:44 +02:00
Juergen Hoeller ac48c64b1a Upgrade to Mockito 2.19 and Mockito Kotlin 1.6 2018-06-28 18:13:59 +02:00
Juergen Hoeller 9a20ec9284 Polishing 2018-06-28 18:13:40 +02:00
Juergen Hoeller 03beee7b68 Upgrade to Tomcat 8.5.32, RxJava 2.1.16, Selenium 3.13 2018-06-28 17:33:30 +02:00
Juergen Hoeller 4be6bcae74 Polishing 2018-06-28 17:30:55 +02:00
Juergen Hoeller 6d0f8bf145 Support for new JsonMappingException wording in Jackson 2.9
Issue: SPR-16947
2018-06-28 16:42:35 +02:00
Juergen Hoeller a631af80c1 Polishing
(cherry picked from commit 40efcc9)
2018-06-28 16:42:14 +02:00
Juergen Hoeller 3e64388b20 Conventions lazily retrieves shared ReactiveAdapterRegistry
Issue: SPR-16981

(cherry picked from commit b68e692)
2018-06-28 16:41:51 +02:00
Juergen Hoeller d3b06a15f2 StringUtils.cleanPath retains plain pointer to current directory
Issue: SPR-16908

(cherry picked from commit 7a02e43)
2018-06-28 16:41:44 +02:00
Juergen Hoeller 75f26eec98 Fix FreeMarker escaping regression for messages and separators
Issue: SPR-16951

(cherry picked from commit 08e1c8c)
2018-06-28 16:41:33 +02:00
Juergen Hoeller 4402336c44 MimeTypeUtils lazily initializes SecureRandom for multipart boundary
Issue: SPR-16974

(cherry picked from commit 847202c)
2018-06-28 16:41:18 +02:00
Juergen Hoeller e388ddfdde WebHttpHandlerBuilder retains ApplicationContext in copy constructor
Issue: SPR-16972

(cherry picked from commit 2a15962)
2018-06-28 16:41:13 +02:00
Napster f83a01e573 Undertow WebSocket sessions share ByteBufferPool
Issues: SPR-16957
2018-06-25 17:59:34 -03:00
Brian Clozel d1c9401dc2 WebClient writes Content-Length for Mono bodies
In SPR-16892, the `EncoderHttpMessageWriter` has been improved to write
`"Content-Length"` HTTP response headers if the response body is of type
`Mono` (i.e. the actual content length is easily accessible without
buffering a possibly large response body). That change was relying on
the fact that the server side is using a `ChannelSendOperator` to delay
the writing of the body until the first signal is received.

This strategy is not effective on the client side, since no such channel
operator is used for `WebClient`. This commit improves
`EncoderHttpMessageWriter` and delays, for `Mono` HTTP message bodies
only, the writing of the body so that we can write the
`"Content-Length"` header information once we've got the body resolved.

Issue: SPR-16949
(Cherry-picked from 4a26f93a0d)
2018-06-19 11:52:26 +02:00
Ryan Yin 60838dcd03 Fix broken link to CONTRIBUTING.md
Closes gh-1860
2018-06-19 09:08:13 +02:00
Rossen Stoyanchev 3526766635 Fix documentation issue 2018-06-18 20:35:57 -04:00
Rossen Stoyanchev 425c311d3c Correctly set maxAge and expires in ResponseCookie
Issue: SPR-16940
2018-06-14 13:16:55 -04:00
Rossen Stoyanchev 24acae1195 Polish ExchangeFilterFunction[s] 2018-06-13 17:15:47 -04:00
Rossen Stoyanchev 49f21ac3ac Polish form writer and converter 2018-06-13 17:15:36 -04:00
Rossen Stoyanchev 8339e7ade5 Use reflection for JdkFlowAdapter
To avoid compiler issues on Eclipse.
2018-06-13 09:41:10 -04:00
Spring Buildmaster 4560f096b9 Next Development Version 2018-06-12 15:09:58 +00:00
Rossen Stoyanchev 4ec9f5df5c Minor polishing for URI encoding docs 2018-06-12 10:15:43 -04:00
Juergen Hoeller 224fcc1712 Remove outdated Servlet environment constraints from annotation javadoc
Includes removal of PathVariable's MultiValueMap support claim.

Issue: SPR-16936

(cherry picked from commit 0b64bcd)
2018-06-12 11:35:55 +02:00
Brian Clozel 96eba8b997 Fix ResourceRegion HttpMessageConverter write checks
This commit fixes the write checks for
`ResourceRegionHttpMessageConverter`, which was previously not checking
properly the parameterized type (e.g. in case of a `List<Something>`).

Issue: SPR-16932
(Cherry-picked from 05ff8b722d)
2018-06-11 22:57:36 +02:00
Rossen Stoyanchev be5229949c Add HTTP caching to WebFlux section
Issue: SPR-16395
2018-06-11 16:44:35 -04:00
Rossen Stoyanchev 516937cfc5 Polish Spring MVC docs on HTTP Caching
Issue: SPR-16395
2018-06-11 16:44:25 -04:00
Brian Clozel dac97f1b7d Restrict HTTP methods on Reactive HiddenHttpMethodFilter
This commit restricts the allowed HTTP methods on HiddenHttpMethodFilter
(Reactive variant) to the following: PUT, DELETE, PATCH.

This filter is meant to be used to simulate those methods from HTML
forms sent by browsers, so no other methods are allowed.

Issue: SPR-16836
(Cherry-picked from a5cd01a4c8)
2018-06-11 19:17:00 +02:00
Brian Clozel f2694a8ed9 Restrict HTTP methods on Servlet HiddenHttpMethodFilter
This commit restricts the allowed HTTP methods on HiddenHttpMethodFilter
(Servlet variant) to the following: PUT, DELETE, PATCH.

This filter is meant to be used to simulate those methods from HTML
forms sent by browsers, so no other methods are allowed.

Issue: SPR-16836
(Cherry-picked from f64fa3dea1)
2018-06-11 19:16:44 +02:00
Juergen Hoeller 82f421bff8 Upgrade to Reactor Bismuth SR10 2018-06-11 18:09:01 +02:00
Juergen Hoeller a2765c009e Polishing 2018-06-11 18:08:39 +02:00
Juergen Hoeller 78d3164543 Remove outdated javadoc references to SpEL lambda functions
Issue: SPR-16930

(cherry picked from commit 6df7ba2)
2018-06-11 18:08:20 +02:00
Brian Clozel afcc430481 Remove dependency management noise from POMs
Prior to this commit, the generated POMs for Spring Framework modules
would contain unneeded/harmful information from the Spring Framework
build:

1. The BOM imports applied to each module by the dependency
management plugin, for example for Netty or Reactor Netty.
Spring should not export that opinion to its POMs.

2. The exclusion of "org.slf4:jcl-over-slf4j" from *all* dependencies,
which made the POMs much larger than necessary and suggested to
developers that they should exclude it as well when using all those
listed dependencies. In fact, only Apache Tiles currently brings that
transitively.

This commit removes that information from the POMs.
The dependencyManagement Gradle plugin is disabled for POM generation
and we manually resolve the dependency versions during the generation
phase.
The Gradle build is streamlined to exclude "org.slf4:jcl-over-slf4j"
only when necessary.

Issue: SPR-16893
(Cherry-picked from 417354da8a)
2018-06-11 16:02:11 +02:00
Juergen Hoeller 062a15fbd7 Latest applicable dependency updates (Jetty 9.4.11, Netty 4.1.25, Hibernate ORM 5.1.14, HSQLDB 2.4.1, Derby 10.14.2.0, HtmlUnit 2.31, Selenium 3.12) 2018-06-11 15:02:44 +02:00
Juergen Hoeller c04c8a2472 Polishing 2018-06-11 15:01:18 +02:00
Juergen Hoeller f39adcf865 AbstractMethodMessageHandler processes Error as MessageHandlingException
Issue: SPR-16912
2018-06-11 14:59:44 +02:00
Juergen Hoeller da049f480b ReflectivePropertyAccessor caches sorted methods per class
Issue: SPR-16882
2018-06-11 14:59:08 +02:00
Juergen Hoeller 455d8ac7b9 Correct code example for YamlProcessor.setDocumentMatchers
Issue: SPR-16849

(cherry picked from commit 7ece0e2)
2018-06-11 14:58:42 +02:00
Sebastien Deleuze b80c13b722 Deprecate JSONP and disable it by default in Jackson view
Issue: SPR-16798
2018-06-08 12:31:40 +02:00
Rossen Stoyanchev 7bfd683816 Eliminate the need for Encoder#getContentLength
Issue: SPR-16892
2018-06-04 16:01:48 -04:00
Jason Zhekov fe01e5114d Fix format typo in webmvc.adoc
Closes gh-1849
2018-06-04 20:56:55 +02:00
Stephane Nicoll b5595c3904 Fix faulty BeanPostProcessorChecker logs with @EnableCaching
Issue: SPR-16896
2018-06-04 15:01:57 +02:00
Violeta Georgieva 76678e9c6a Fix code examples for WebFlux functional endpoints
Closes gh-1844
2018-05-31 15:19:28 +02:00
Johnny Lim b3a34f8397 Polish doc
Closes gh-1843
2018-05-31 10:21:36 +02:00
Juergen Hoeller 79adffd214 Upgrade to Hibernate Validator 6.0.10, RxJava 2.1.14, Gson 2.8.5 2018-05-30 11:59:57 +02:00
Juergen Hoeller af0a82931e Polishing
(cherry picked from commit 1b728fb)
2018-05-30 11:59:30 +02:00
Juergen Hoeller bbe5124556 Polishing 2018-05-29 22:16:48 +02:00
Juergen Hoeller 5935b7aefe Doc: @EnableScheduling needs to be declared per application context
Issue: SPR-16852

(cherry picked from commit b39ce80)
2018-05-29 22:00:34 +02:00
Juergen Hoeller a2d7cc7a69 AbstractRequestLoggingFilter.isIncludeHeaders() declared as protected
Issue: SPR-16881

(cherry picked from commit c754232)
2018-05-29 22:00:24 +02:00
Juergen Hoeller 8a56db6e4e SimpleAliasRegistry logs info message for alias overriding
Issue: SPR-16871

(cherry picked from commit 74fcdea)
2018-05-29 22:00:14 +02:00
Juergen Hoeller 50d6d90ed8 Restore lenient null return value for ConditionContext.getBeanFactory()
Includes nullable return value for getClassLoader() with corresponding notes in applicable javadoc.

Issue: SPR-16866

(cherry picked from commit 46a89d9)
2018-05-29 22:00:05 +02:00
Arjen Poutsma a7ffe092ab Fix parent path variables in nested route functions
This commit fix an issue where path variables in a nested parent
RouterFunction were not committed to the request attributes.

Issue: SPR-16868

(cherry picked from commit 8c30b8e)
2018-05-29 15:57:52 +02:00
Sebastien Deleuze 6407cb9baf Fix PropertyResolverExtensions.kt location 2018-05-28 15:53:03 +02:00
Gary Russell 0bc0762577 Fix JMS Doc typo
There is no such class `ReplyQosSettings`.

Closes gh-1836
2018-05-25 16:32:09 +02:00
Rossen Stoyanchev 051ab05d32 Properly initialize URI/Matrix vars w/ urlDecode=false
Issue: SPR-16867
2018-05-24 15:10:55 -04:00
Rossen Stoyanchev 9d36fd0b68 Respect async request timeout of -1 in MockMvc
When falling back on the timeout associated with the async request,
a value of -1 must be treated as: never time out.

Issue: SPR-16869
2018-05-24 12:36:47 -04:00
Rossen Stoyanchev f078e057ce Update docs on WebClient filters 2018-05-24 07:20:24 -04:00
Rossen Stoyanchev 941186a359 Minor update to STOMP chapter
Issue: SPR-16681
2018-05-23 21:50:46 -04:00
Rossen Stoyanchev 27fc4d6053 ChannelInterceptor default methods + deprecate adapter 2018-05-23 21:50:34 -04:00
Rossen Stoyanchev 1943a1f5bd Fix error in WebFlux chapter on static resources
Issue: SPR-16864
2018-05-23 21:25:26 -04:00
Rossen Stoyanchev a158ff4c3d Return SslInfo only if X509Certificate[] present
Issue: SPR-16842
2018-05-23 14:58:23 -04:00
Rossen Stoyanchev a71bd7c03f Immutable Resource[Resolver|Transformer]Chains
Backport of #f121aa5e31, applied to spring-webflux only.

Issue: SPR-16862
2018-05-23 09:53:26 -04:00
Sebastien Deleuze 1fefe2ab0c Upgrade to Dokka 0.9.17 2018-05-22 17:44:28 +02:00
Rossen Stoyanchev 0b36c9437e CodecConfigurer internal refactoring
Improve how HTTP message writers are obtained for general use vs for
multipart requests.
2018-05-21 21:15:17 -04:00
Rossen Stoyanchev 72e7687b80 Polish CodecConfigurer related classes
Functionally equivalent updates to package private classes to improve
the code and make it easier to understand.
2018-05-21 21:15:05 -04:00
Rossen Stoyanchev e87355b29c STOMP client supports setting accept-version
Issue: SPR-16844
2018-05-18 15:13:14 -04:00
Rossen Stoyanchev 1dc8201df1 Polish ReactiveAdapterRegisry 2018-05-18 09:30:10 -04:00
Rossen Stoyanchev e3e975d7f9 Support for SslInfo in ServerHttpRequest#mutate
Issue: SPR-16830
2018-05-17 17:29:33 -04:00
Rossen Stoyanchev b385ff1d9f Polish WebFlux WebSocket docs
Issue: SPR-16820
2018-05-17 10:03:24 -04:00
Arjen Poutsma 3c88029dd3 Improve toString for filtered router function
Issue: SPR-16829

(cherry picked from commit f722f40)
2018-05-17 12:02:57 +02:00
Rossen Stoyanchev c7adf28f61 Expand WebFlux docs with WebSocketHandler examples
Issue: SPR-16820
2018-05-16 21:33:47 -04:00
Rossen Stoyanchev c555fef6f2 Improve TCP connection info logging.
After the recent changes to expose configuring TcpOperations, it no
longer makes sense to automatically log the relayHost/Port since that's
mutually exclusive with a custom TcpOperations.

Instead we delegate to TcpOperations.toString().

Issue: SPR-16801
2018-05-16 14:26:29 -04:00
Rossen Stoyanchev ab0b0b31fd Polish: simplify ControllerMethodResolver initialization 2018-05-16 10:04:08 -04:00
Arjen Poutsma d24546ad18 Improve toString for query param and path extension predicates
Issue: SPR-16829

(cherry picked from commit 7424ca5)
2018-05-16 11:16:11 +02:00
Juergen Hoeller 2818051aff Revised code examples for stored procedure type declarations
Issue: SPR-16811

(cherry picked from commit 765d18e)
2018-05-16 09:09:55 +02:00
Juergen Hoeller a3bcdbe371 SchedulerFactoryBean triggers shutdown after registration failure
Issue: SPR-16816

(cherry picked from commit 0098245)
2018-05-16 09:09:44 +02:00
Juergen Hoeller 3978d5500d Query termination for JPA 2.1 StoredProcedureQuery.execute() method
Issue: SPR-16826

(cherry picked from commit 3c8c996)
2018-05-16 09:09:35 +02:00
Juergen Hoeller 416dee7226 AspectJExpressionPointcut evaluates interface method on proxy as well
Issue: SPR-16803

(cherry picked from commit bba5dca)
2018-05-16 09:09:24 +02:00
Sebastien Deleuze 4d69ec48b1 Add StatusResultMatchers.isEqualTo Kotlin extension
Issue: SPR-16429
2018-05-15 15:42:25 +02:00
Sebastien Deleuze 14a9d291e1 Filter synthetic in ReflectionUtils#USER_DECLARED_METHODS
Issue: SPR-16823
2018-05-15 15:01:31 +02:00
Sebastien Deleuze 5183f71a78 Update Kotlin refdoc with the new tutorial 2018-05-14 10:54:10 +02:00
Rossen Stoyanchev fd36af6fcf Inject UriComponentsBuilder relative to webapp root
Issue: SPR-16813
2018-05-11 09:54:35 -04:00
Rossen Stoyanchev 9179a4fa30 Correct coordinates for Reactor Netty in STOMP chapter
Issue: SPR-16802
2018-05-10 16:47:17 -04:00
nkjackzhang 98335b41f7 Fix a typo in javadoc
Closes gh-1824
2018-05-10 17:32:58 +02:00
Rossen Stoyanchev e9f4dec08c Restore layout of docs zip with index.html at the top
Issue: SPR-16799
2018-05-09 17:29:38 -04:00
Spring Buildmaster 4ec695b4d9 Next Development Version 2018-05-08 08:34:28 +00:00
Juergen Hoeller 2da02ccbd0 Polishing
(cherry picked from commit 70424a7)
2018-05-08 00:25:46 +02:00
Juergen Hoeller f2cc70ecf9 Explicit coverage of root vs cause exception matching in MVC ref docs
Issue: SPR-16743

(cherry picked from commit a200df6)
2018-05-07 23:18:33 +02:00
Rossen Stoyanchev e2115594c0 Document throwExceptionIfNoHandlerFound property
Issue: SPR-16786
2018-05-07 16:12:25 -04:00
Juergen Hoeller 2008e04354 Upgrade to Servlet API 4.0.1 2018-05-07 14:38:16 +02:00
Juergen Hoeller b4f83dbdc3 Polishing 2018-05-07 14:30:50 +02:00
Juergen Hoeller 0795ae5c6a Polishing 2018-05-05 16:55:06 +02:00
Juergen Hoeller 41ab177b6c Fine-tuned assertions and related polishing 2018-05-05 14:59:13 +02:00
Juergen Hoeller 8848ec73ab Refined backport of gh-1817 2018-05-05 13:18:08 +02:00
Juergen Hoeller 9f9481ec7b Upgrade to Tomcat 8.5.31, Undertow 1.4.25, Jetty 9.4.10, Gson 2.8.4
Includes upgrade from Reactor snapshots to Bismuth SR9.
2018-05-05 13:17:44 +02:00
Juergen Hoeller f6275e009b YamlProcessor embraces SnakeYAML 1.18+ duplicate key handling
Includes deprecation of StrictMapAppenderConstructor.

Issue: SPR-16791

(cherry picked from commit 138b0d0)
2018-05-05 13:17:10 +02:00
Juergen Hoeller ed44262a71 ResponseEntityExceptionHandler rethrows unknown exception (for further processing in DispatcherServlet's HandlerExceptionResolver chain)
Issue: SPR-16743

(cherry picked from commit 7b894fe)
2018-05-05 13:17:00 +02:00
Johnny Lim a0d37ac29e Remove inconsistent spaces
(cherry picked from commit fb898e1)
2018-05-05 12:49:26 +02:00
Johnny Lim a39938d251 Polish DatabaseStartupValidator
(cherry picked from commit 8f21cb1)
2018-05-05 12:49:10 +02:00
nkjackzhang edb33331ed Task "docsZip" copies duplicate reference files
Specify task "docsZip" source directory.
Issue: SPR-16789
2018-05-03 16:39:51 -04:00
Arjen Poutsma a63f04df09 Clean up path variables after non match
This commit makes sure the nested path variables are only commited to
the attributes when all predicates match.

Issue: SPR-16692

(cherry picked from commit 51325af)
2018-05-03 12:06:06 +02:00
Juergen Hoeller 5a98516f6c Lenient fallback to plain getBundle call without Control handle
Issue: SPR-16776
2018-05-02 16:54:38 +02:00
Juergen Hoeller 30363c84bd Consistent SpelEvaluationException messages in findAccessorForMethod
Issue: SPR-16762
2018-05-02 16:53:55 +02:00
Juergen Hoeller fa27130b82 Upgrade to RxJava 2.1.13, Hibernate ORM 5.2.17, AspectJ 1.9.1 2018-05-02 16:32:55 +02:00
Juergen Hoeller be4c07fc32 Expose FactoryBean's raw object on retrieval during post-processing
Issue: SPR-16783

(cherry picked from commit 9281f82)
2018-05-02 16:32:18 +02:00
Juergen Hoeller 22f421cc51 Introspect originating bean definition as configuration class candidate
Issue: SPR-16756

(cherry picked from commit c8b6233)
2018-05-02 16:31:57 +02:00
Juergen Hoeller 9dc538a7c6 Nullable HttpMethod parameter only on internal doExecute delegate
Issue: SPR-15540

(cherry picked from commit f8c2d7a)
2018-05-02 16:31:33 +02:00
Juergen Hoeller d74a2730ec SimpleClientHttpResponse catches any Exception on close
Issue: SPR-16773

(cherry picked from commit 21fad8e)
2018-05-02 16:07:22 +02:00
Juergen Hoeller 3e47f4564d Fine-tuned assertions and related polishing in WebFlux builders
(cherry picked from commit 9bff5b4)
2018-05-02 16:04:51 +02:00
Juergen Hoeller a9548f93e4 Support for non-standard HTTP status in reactive ClientHttpResponse
Issue: SPR-16748

(cherry picked from commit a683472)
2018-05-02 16:04:01 +02:00
Juergen Hoeller f2e77c292d Consistent target method resolution for event and caching expressions
Issue: SPR-16779

(cherry picked from commit eaff2c2)
2018-05-02 16:02:46 +02:00
Juergen Hoeller 8b051ab06e AopUtils.getMostSpecificMethod exposes dynamic proxy class methods
Includes efficient canApply check for IntroductionAwareMethodMatcher.

Issue: SPR-16757

(cherry picked from commit aa11721)
2018-05-02 16:01:48 +02:00
Oleksandr Hasheniuk 5a1d7f9c4b Improve performance of StringUtils#trimWhitespace
Issue: SPR-16766

(cherry picked from commit 6545cab)
2018-05-02 16:01:04 +02:00
Sebastien Deleuze b55f69deb1 Support decoding Mono in Jaxb2XmlDecoder
Issue: SPR-16759
2018-05-02 11:57:40 +02:00
Rossen Stoyanchev de1eb343e7 Polish WebSocketIntegrationTests 2018-05-01 14:26:44 -04:00
Rossen Stoyanchev 417bb302c3 ReactorNettyWebSocketSession implements close properly
Issue: SPR-16774
2018-05-01 12:05:20 -04:00
Rossen Stoyanchev b0aa08a671 Consistent handling of URISyntaxException
Issue: SPR-16778
2018-04-30 21:05:08 -04:00
Sebastien Deleuze 9dc79982e2 Upgrade to Kotlin 1.2.41
Fixes KT-23973 critical regression
2018-04-30 10:48:23 +02:00
Stephane Nicoll 43f2334e82 Keep YAML entries that haven an empty array value
Prior to this commit, a YAML entry that define an empty array value was
lost. This commit makes sure to flag it with an empty String, which
corresponds as an empty comma separated list of entries in the
properties format.

Issue: SPR-16769
2018-04-29 11:15:53 +02:00
Nickloas 6c6e44b58e Fix typo
Closes gh-1813
2018-04-28 10:52:03 +02:00
Johnny Lim c6b60f0c00 Polish 2018-04-27 14:09:35 -04:00
sdeleuze 7aba6ca9d6 Fine tune WebFlux server logging verbosity
With this commit, WebFlux server uses warning instead of error log level
for request handling, and also just print the message instead of the
stacktrace which is mostly meaningless in reactive world.

Complementary to this change, Reactor Netty removed additional logging
as part of https://github.com/reactor/reactor-netty/issues/339.

Issue: SPR-16688
2018-04-27 10:36:06 +02:00
nkjackzhang dca77c0666 Fix broken anchor link in WebFlux refdoc 2018-04-27 08:49:51 +02:00
sdeleuze df6e690e33 Reuse PartBodyStreamStorageFactory in SynchronossPartGenerator
Issue: SPR-16727
2018-04-26 11:01:17 +02:00
nkjackzhang a702ef8074 Fix typos in Spring MVC refdoc
1. Consistent with "xml code" examples.
2. "xml()" is a static method and will use default builder config,
   so use createXmlMapper(true) instead.
3. Fix mvc namespace tag typo.
2018-04-26 10:03:27 +02:00
Rossen Stoyanchev f7376bdde3 Better assertion message in MockPart
Issue: SPR-16767
2018-04-25 10:00:18 -04:00
nkjackzhang f9e31b503c Fix typos
Closes gh-1806
2018-04-25 10:07:34 +02:00
hasheniuk 3551dd92fb Fix typo
Closes gh-1804
2018-04-24 10:06:49 +02:00
Rossen Stoyanchev c23297fe76 Add more detail to ISE in ServerEndpointExporter
Issue: SPR-16655
2018-04-23 17:04:16 -04:00
Rossen Stoyanchev a5622d0dd2 Validate contextPath in RedirectView
Issue: SPR-16752
2018-04-23 15:21:33 -04:00
Brian Clozel 72cfe41f30 Disable HTTP Range support for InputStreamResource
Prior to this commit, the `AbstractMessageConverterMethodProcessor`
would fail to convert `InputStreamResource` to `ResourceRegion` as
expected, since the content length cannot be read without consuming the
stream. This is enforced by the `HttpRange` class.

Now the method processor would still try to output HTTP range response
headers to provide range support information. This step is using the
resource content length and reads the input stream, leading to
exceptions such as "IllegalStateException: InputStream has already been
read".

This commit improves the return type detection and excludes early
`InputStreamResource` return types. With those types, HTTP range support
is now completely disabled.

Issue: SPR-16754
(cherry picked from commit e9a8a5065b)
2018-04-23 18:40:15 +02:00
sdeleuze 4ff595e2bc Upgrade Kotlin to 1.2.40 2018-04-23 15:31:31 +02:00
sdeleuze 2c766b9501 Enable KotlinScriptTemplateTests after KT-18833 fix 2018-04-23 15:31:31 +02:00
Dimitrios (Dimi) Liapis 2960a558d7 Fix typo
See gh-1803
2018-04-21 18:21:19 +02:00
Brian Clozel d69a281e5c Upgrade to Netty 4.1.24.Final 2018-04-21 09:31:29 +02:00
Rossen Stoyanchev d3ed7b624d In 5.0.x we don't have Flux/Mono error with Supplier
Issue: SPR-16726
2018-04-19 13:41:01 -04:00
Rossen Stoyanchev 66bd277671 Use StringDecoder to split SSE stream
ServerSentEventHttpMessageReader had logic to split on new lines
and buffer until an empty new line (start of a new event). To account
for random data chunking, it later re-assembled the lines for each
event and split again on new lines. However bufferUntil was still
unreliable a chunk may contain nothing but a newline, which doesn't
necessarily mean an empty newline in the overall SSE stream.

This commit simplifies the above by delegating the splitting of the
stream along newlines to StringDecoder.

Issue: SPR-16744
2018-04-19 11:38:43 -04:00
Rossen Stoyanchev 881343e928 Polish tests to use WebClient retrieve() 2018-04-19 11:38:43 -04:00
Daniel Kift 922fd1e785 Polish WebFlux reference documentation 2018-04-18 11:58:37 +02:00
nkjackzhang ea8317a1f9 Fix a typo in @Nullable Javadoc 2018-04-18 11:55:13 +02:00
Rossen Stoyanchev 053ffe808f Polish (minor) in AbstractMessageReaderArgumentResolver 2018-04-17 17:58:56 -04:00
Rossen Stoyanchev daa2d37ad4 Avoid creating Exception instance if not needed
Issue: SPR-16726
2018-04-17 17:58:46 -04:00
Juergen Hoeller f800df12e3 Correctly delegate to OrderUtils.getPriority for DecoratingProxy
Issue: SPR-16739

(cherry picked from commit 2f4010e)
2018-04-17 23:38:30 +02:00
Juergen Hoeller 26652a6b83 Avoid repeated superclass introspection in findAnnotation(Method,...)
Issue: SPR-16730

(cherry picked from commit d78e27f)
2018-04-17 17:06:31 +02:00
Juergen Hoeller 4cd43dc793 Workaround for generic parameter types on inner class constructors
Issue: SPR-16734
2018-04-17 15:32:03 +02:00
sdeleuze 91c8b62817 Make ResponseSpec.expectBody Kotlin extension usable
Prior to this commit, due to KT-5464 type inference issue there was not
proper way to provide body expectations with WebTestClient. This commit
provides a workaround by updating the existing Kotlin extension to
return a Kotlin compatible API.

Issue: SPR-15692
2018-04-17 14:58:12 +02:00
Juergen Hoeller 9d37c099a8 OperatorMatches flags misguided evaluation attempts as FLAWED_PATTERN
Issue: SPR-16731

(cherry picked from commit d4a55a2)
2018-04-17 13:35:01 +02:00
Juergen Hoeller eb573d8b9e Restore original MethodMapTransactionAttributeSource matching rules
Issue: SPR-16733

(cherry picked from commit c5b524d)
2018-04-17 13:34:38 +02:00
Rossen Stoyanchev b312a62f64 Selector header name is exposed for configuration
Issue: SPR-16732
2018-04-16 23:58:47 -04:00
Rossen Stoyanchev 567733d2a1 Restore handling of 0 bytes read
Issue: SPR-16728
2018-04-16 10:01:51 -04:00
Juergen Hoeller 0f91f4b960 Local XMLUnit dependency declarations with consistent version 2.5.1
Includes upgrade to Undertow 1.4.24.

(cherry picked from commit 0754833)
2018-04-14 21:23:33 +02:00
Juergen Hoeller c1385f52c2 Polishing
(cherry picked from commit de4ff4b)
2018-04-14 21:03:59 +02:00
Sam Brannen c3bc125093 Suppress warning in SpringFailOnTimeoutTests 2018-04-14 16:44:47 +02:00
Juergen Hoeller b5922f75bb AspectJExpressionPointcut consistently resolves superinterface methods
Includes efficient check for same ClassLoader in ClassUtils.isVisible, efficient MethodMatchers check for IntroductionAwareMethodMatcher, and supertype method resolution in MethodMapTransactionAttributeSource.

Issue: SPR-16723

(cherry picked from commit b95e05d)
2018-04-14 15:49:55 +02:00
nkjackzhang bbe850d33a Fix typo in javadoc
Closes gh-1791
2018-04-13 13:16:40 +02:00
Juergen Hoeller 295929cc16 Cache-safety check for sibling loaders resolving the same classes
Issue: SPR-16714
2018-04-12 21:08:25 +02:00
Juergen Hoeller 4763154193 Consistent getTypeForFactoryMethod result for parameterized method
Issue: SPR-16720

(cherry picked from commit 6184c4e)
2018-04-12 21:08:14 +02:00
Juergen Hoeller 8f7e5e7c1a Fine-tuned JCA MessageEndpoint exception logging and propagation
Issue: SPR-16717

(cherry picked from commit 8e1ecec)
2018-04-12 21:07:44 +02:00
Juergen Hoeller cd79966c52 Revised reference example for linkable controller method signature
Issue: SPR-16710

(cherry picked from commit 7ee6130)
2018-04-12 21:07:39 +02:00
Brian Clozel 7631aa6062 Switch to Reactor Bismusth SNAPSHOTs 2018-04-12 17:01:24 +02:00
Sam Brannen 02e09098e4 Expand scope of SpringFailOnTimeoutTests
Issue: SPR-16716
2018-04-12 11:00:45 +02:00
Igor Suhorukov 230c8f93e8 Throw exception from user code in SpringFailOnTimeout even if a timeout occurs
Issue: SPR-16717
2018-04-12 11:00:35 +02:00
Rossen Stoyanchev c4296fa785 Remove write pausing in Undertow response
Using the simple example shown in the ticket but switching from
Mono<String> to Flux<String> (and 5,000,000 onNext calls) shows that
constant pausing causes significant overhead and is not worth the
trouble vs ignoring the onWritePossible in REQUESTED state.

Issue: SPR-16702
2018-04-11 14:37:35 -04:00
Rossen Stoyanchev ab78854f1b Avoid inifinite recursion in UndertowServerHttpResponse
Undertow does not provide a way to check if we can write so with the
current implementation of isWritePossible, deep recursion can occur
when writing slows down. We now use a flag to keep track of write
ChannelListener callbacks.

This commit also addresses a related issue in
AbstractListenerWriteProcessor that went undected since #3c2d186
where after a large (single) buffer that is not written fully, the
completion signal is processed before the all data is written.

Issue: SPR-16702
2018-04-11 14:37:19 -04:00
Juergen Hoeller 96a465a749 Upgrade to Tomcat 8.5.30 2018-04-11 16:27:34 +02:00
Juergen Hoeller 861b9dc938 Proper exception for controller method return types that do not work with MvcUriComponentsBuilder (e.g. final classes)
Includes direct use of ControllerMethodInvocationInterceptor for return type Object, avoiding the attempt to generate an Object subclass.

Issue: SPR-16710

(cherry picked from commit f28a5d0)
2018-04-11 16:27:14 +02:00
sdeleuze eda2720471 Add default ctor to Reactive UrlBasedCorsConfigurationSource
Issue: SPR-16712
2018-04-11 14:41:06 +02:00
Juergen Hoeller 7fe28ce8b7 Upgrade to Netty 4.1.23 and TestNG 6.14.3 2018-04-11 13:29:37 +02:00
Juergen Hoeller de8c4179fb Polishing 2018-04-11 13:29:15 +02:00
Juergen Hoeller 433877e5cb AnnotationUtils.getAnnotation non-null check for synthesizeAnnotation
Issue: SPR-16708

(cherry picked from commit da80502)
2018-04-11 13:28:53 +02:00
Juergen Hoeller ffa4f03fd4 Unwind _TestTypes to top-level public test classes in AOP test suite
(cherry picked from commit cdaa247)
2018-04-11 13:28:39 +02:00
Juergen Hoeller 7068282e1f Remove bogus DataSource test from JpaTransactionManagerTests
(cherry picked from commit ff53d78)
2018-04-11 13:28:33 +02:00
sdeleuze 3879179927 Document why "charset=UTF-8" is specified for JSON
Issue: SPR-14715
2018-04-09 12:01:21 +02:00
KwonJH 007da2a58d Fix Java 9 link in the reference documentation 2018-04-09 11:13:25 +02:00
sdeleuze 1be585562f Improve Kotlin + bean validation documentation
Issue: SPR-16701
2018-04-09 10:18:06 +02:00
Rossen Stoyanchev 7a896d7d80 TestDispatcherServlet unwraps to find mock request
Issue: SPR-16695
2018-04-06 11:04:29 -04:00
sdeleuze be1aaa06e7 Cleanup settings.gradle pluginManagement configuration 2018-04-04 11:11:38 +02:00
sdeleuze 2fa060f0e9 Fix Dokka reference to Spring Framework's Javadoc
This commit specifies a local packageListUrl and defines that dokka task
must be executed after the api task in order to be able to build KDoc
during the release process when the Spring Framework's Javadoc is not
published yet.

Issue: SPR-16687
2018-04-04 11:11:17 +02:00
Stephane Nicoll 4d2d889142 Initiate 5.0.x branch 2018-04-03 23:07:03 +02:00
Spring Buildmaster 4b9bc50fd0 Release version 5.0.5.RELEASE 2018-04-03 20:11:16 +00:00
Stephane Nicoll 3fb8d16ff7 Temporarily remove reference to Spring Framework's Javadoc
Issue: SPR-16687
2018-04-03 21:14:49 +02:00
Juergen Hoeller 40d5e7cc80 Upgrade to AspectJ 1.9 GA
Issue: SPR-16686
2018-04-03 17:43:09 +02:00
Stephane Nicoll 7be4193933 Upgrade to Reactor Bismuth-SR8 2018-04-03 15:45:36 +02:00
Juergen Hoeller aa0face9a1 Upgrade to RxJava 1.3.8 and Rhino 1.7.9 2018-04-03 15:18:25 +02:00
Juergen Hoeller 475c4d4425 Polishing 2018-04-03 12:24:00 +02:00
Juergen Hoeller 9601d4bb5b Revised mime.types file with cpp extension and updated modification docs
Issue: SPR-16678
2018-04-03 12:23:09 +02:00
Juergen Hoeller 5d0700b936 AnnotationUtils.annotatedInterfaceCache available as deprecated field
Issue: SPR-16675
2018-04-03 12:21:03 +02:00
Juergen Hoeller 6102715b8d Consistent treatment of proxy classes and interfaces for introspection
Issue: SPR-16675
Issue: SPR-16677
2018-04-03 02:42:41 +02:00
Rossen Stoyanchev 65fdd0efeb [docs] Updates for exception handling in web sections
Issue: SPR-16394
2018-04-02 00:51:14 -04:00
Rossen Stoyanchev 9dd3cd98ac [docs] Move Filters section under Reactive Spring Web
Issue: SPR-16394
2018-04-02 00:50:56 -04:00
Juergen Hoeller cc379f1cc7 Polishing 2018-04-01 12:57:19 +02:00
Juergen Hoeller 666037ec5c Pointcut checking directly against superclass in case of CGLIB subclass
Issue: SPR-16675
2018-04-01 12:57:02 +02:00
Juergen Hoeller 66a3a82fb3 Avoid reference to HandlerMethod class in ServerErrorException
This breaks the package dependency cycle between web.server/web.method and makes ServerErrorException more generally applicable. Includes deprecation of the plain reason constructor variant, in favor of providing a Method or MethodParameter context (which MatrixVariableMethodArgumentResolver does now).
2018-04-01 00:21:15 +02:00
Juergen Hoeller 97735e4ffc Proper references to JDK 9+ (including JDK 10) in build comments 2018-04-01 00:07:06 +02:00
Juergen Hoeller 28ea718d2d Build setup allows for JDK 10 as source/test target compatibility
Includes upgrade to Groovy 2.4.15 and HtmlUnit 2.30.

Issue: SPR-16390
2018-03-31 23:17:31 +02:00
Juergen Hoeller bc07a54075 Clear AnnotationUtils cache after context refresh (along with others)
Issue: SPR-16675
2018-03-31 23:08:30 +02:00
Juergen Hoeller 8a9321652d Refined javadoc 2018-03-31 23:07:08 +02:00
Rossen Stoyanchev d9e17a62ce Refine SyncInvocableHandlerMethod error handling
Ensure the error is wrapped as ServerErrorException
2018-03-31 12:06:24 -04:00
Juergen Hoeller 912c270f2b Polishing 2018-03-31 17:49:21 +02:00
Rossen Stoyanchev 4454ffd2b1 Replace remaining use of block operator 2018-03-31 11:18:38 -04:00
Juergen Hoeller 129c05bcff Comprehensively cache annotated methods for interfaces and superclasses
Issue: SPR-16675
2018-03-31 15:12:02 +02:00
Stephane Maldini b8d32095a9 workaround multipart integration test using blocking receive inside netty thread 2018-03-30 15:43:11 -07:00
Juergen Hoeller 6393e5ce0c Consistent Ordered.LOWEST_PRECEDENCE declarations for default order 2018-03-31 00:20:44 +02:00
Juergen Hoeller 4da27c2a73 Avoid unnecessary introspection on methods and meta-annotations
Issue: SPR-16667
2018-03-31 00:18:14 +02:00
Rossen Stoyanchev b1048975d2 Minor updates based on PR#1058
The original repo no longer exists:
https://github.com/spring-projects/spring-framework/pull/1058
2018-03-30 13:36:20 -04:00
Kazuki MATSUDA d232fffa63 Use whenComplete since (null) return value not needed 2018-03-30 11:07:46 -04:00
Bian Jiaping 8f525f07e9 Fix typos, formatting and escaping in reference
Note: Some symbol combinations (including <=) serve as textual symbol
replacements in AsciiDoc.

http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#text-replacement
2018-03-30 10:06:33 -04:00
Juergen Hoeller 22a8a668c9 AnnotationTypeFilter assumes no custom annotations on common Java types
Issue: SPR-16667
2018-03-30 15:31:43 +02:00
Juergen Hoeller 78681c6369 JndiRmiServiceExporter still calls PortableRemoteObject when available
Issue: SPR-16670
2018-03-30 15:19:38 +02:00
Juergen Hoeller 0bc01fcd55 Polishing 2018-03-30 13:42:23 +02:00
Juergen Hoeller 7a8d41e5d6 Extended set of common classes and language interfaces in ClassUtils
Issue: SPR-16667
2018-03-30 13:41:22 +02:00
Johnny Lim 8dd0974e2f Rename SingleColumnRowMapperTest to align with the other tests 2018-03-30 12:28:16 +02:00
Sam Brannen e5096be660 Polishing 2018-03-30 12:23:28 +02:00
Sam Brannen f79562f8d1 Introduce tests for generics & @Nested test classes 2018-03-30 12:12:21 +02:00
Sam Brannen a6c45f0cd9 Polishing 2018-03-30 11:45:28 +02:00
Rossen Stoyanchev 240d6f52c9 Replaces rather than prepend contextPath
Issue: SPR-16650
2018-03-29 18:17:29 -04:00
Juergen Hoeller d553ddc5b3 Nullability refinements (based on IntelliJ IDEA 2018.1 introspection)
Issue: SPR-15756
2018-03-29 23:50:17 +02:00
Juergen Hoeller 1cc513d7db Consistent to/cc/bcc array handling and revised hashCode without text
Issue: SPR-16671
2018-03-29 23:44:04 +02:00
Juergen Hoeller 9a722b4558 Pass type name into PreparedStatement.setNull in case of Types.OTHER
Issue: SPR-16669
2018-03-29 23:43:53 +02:00
igor-suhorukov 93abe0e94b All branches in a conditional structure should not have exactly the same implementation 2018-03-29 23:33:50 +02:00
igor-suhorukov ab96bb5428 Remove redundant check 2018-03-29 23:33:38 +02:00
igor-suhorukov c1ff97e2a8 Short-circuit logic should be used in boolean contexts 2018-03-29 23:33:22 +02:00
Rossen Stoyanchev dd96c873e3 Improve docs on forwarded headers
Issue: SPR-16660
2018-03-29 16:11:01 -04:00
Rossen Stoyanchev a546cf0a3b Reject invalid forwarded headers
Issue: SPR-16660
2018-03-29 15:28:34 -04:00
Thor Andreas Rognan 5fb4c8254f Fix inclusion of license in jar 2018-03-29 12:30:28 -04:00
Rossen Stoyanchev 30b63a71bd Switch to Bismuth snapshots 2018-03-29 12:28:05 -04:00
Sam Brannen 9244090ba0 Support DI of individual constructor args in @Nested tests
Prior to this commit it was impossible to have an individual
constructor argument in a @Nested (i.e., inner) test class injected via
@Autowired, @Qualifier, or @Value.

This is due to a bug in javac on JDK versions prior to 9, whereby
annotation lookups performed directly via the
java.lang.reflect.Parameter API fail for inner class constructors.

Specifically, the parameter annotations array in the compiled byte code
for the user's test class excludes an entry for the implicit enclosing
instance parameter for an inner class constructor.

This commit introduces a workaround in ParameterAutowireUtils for this
off-by-one error by transparently looking up annotations on the
preceding Parameter object (i.e., index - 1). In addition, this commit
relies on the change recently introduced in MethodParameter in order to
compensate for the same JDK bug (see SPR-16652).

Issue: SPR-16653
2018-03-29 17:47:45 +02:00
Sam Brannen 17703e5dde Polishing 2018-03-29 17:45:55 +02:00
Sam Brannen 7c28152c13 Introduce ClassUtils.isInnerClass() utility method 2018-03-29 17:45:25 +02:00
Juergen Hoeller b165475eb6 Polishing 2018-03-29 16:05:52 +02:00
Juergen Hoeller 08dad4e3ac Consistent references to primitive types (in alphabetical order) 2018-03-29 16:05:00 +02:00
Juergen Hoeller 695bf2961f Consistent trace logging in PathResourceResolver
Issue: SPR-16616
2018-03-29 16:04:33 +02:00
Juergen Hoeller 53d01392d7 Workaround for inner class constructor parameter annotation bug in javac
Issue: SPR-16652
2018-03-29 15:45:02 +02:00
Juergen Hoeller 3ac46da22f Correct description for doWithLocalFields
Issue: SPR-16658
2018-03-29 15:42:30 +02:00
nkjackzhang 82cb5dbf2b NamedParameterUtils.parseSqlStatement should parse :{x} style parameter correctly
In my opinion, we should parse ":{x}" style parameter as "x" is parameter using "NamedParameterUtils.parseSqlStatement",
so the condition "j - i > 2" is the correct condition, not "j - i > 3", because if "i" is the index of
":" in ":{x}", and "j" is the index of "}" in ":{x}",  "j - i == 3" is true.
Also add a test case for SPR-16663.
2018-03-29 15:00:25 +02:00
Stephane Nicoll f4813f5b4c Merge pull request #1759 from igor-suhorukov
* pr/1759:
  Nested "enum"s should not be declared static
2018-03-29 09:13:18 +02:00
igor-suhorukov 8d2f64fe2d Nested "enum"s should not be declared static
Closes gh-1759
2018-03-29 09:12:03 +02:00
Rossen Stoyanchev f9e6ea5482 MvcResult returns asyncResult after asyncDispatch
Issue: SPR-16648
2018-03-28 22:15:16 -04:00
igor-suhorukov e6020ed377 avoid unnecessary autoboxing 2018-03-28 23:48:12 +02:00
Rossen Stoyanchev b8d72516e1 Update link to WebSocket spec issue 2018-03-28 15:54:57 -04:00
Sam Brannen 4b9e3a9211 Introduce failing test for SPR-16652
This commit introduces tests for looking up annotations on parameters
in constructors for nested and inner classes via Spring's
MethodParameter abstraction.

The test for an inner class is currently disabled since it fails on
JDK 8. See JIRA issue for details.

Issue: SPR-16652
2018-03-28 17:42:55 +02:00
Juergen Hoeller d95bbb6b1b Test for hasError keeping body available in case of unknown status code
Issue: SPR-16604
2018-03-28 12:16:03 +02:00
Juergen Hoeller b2d87abcbb Polishing 2018-03-28 12:06:38 +02:00
Stephane Nicoll d1a0b8d53f Clarify the format supported by @PropertySource
Issue: SPR-16563
2018-03-28 11:03:53 +02:00
Rossen Stoyanchev 5861e9685b Always specify charset for form data requests
Issue: SPR-16613
2018-03-27 19:56:09 -04:00
Rossen Stoyanchev e00384a6fd MimeTypeUtils trims parameter names / values
Issue: SPR-16630
2018-03-27 19:56:09 -04:00
igor-suhorukov 4aae6a6dda Use Map.forEach instead of manual Map.Entry iteration wherever possible SPR-16646 2018-03-28 01:09:03 +02:00
Rossen Stoyanchev 224d52e032 Refine RequestedContentTypeResolver contract
Consistently return "*/*" if no media types were requested rather than
an empty list. Existing code has to check for both in any case to see
if nothing was requested.

Issue: SPR-16624
2018-03-27 16:54:25 -04:00
Rossen Stoyanchev f3994467c4 Refine ContentNegotiationStrategy contract
Consistently return "*/*" if no media types were requested rather than
an empty list. Existing code has to check for both in any case to see
if nothing was requested.

Issue: SPR-16624
2018-03-27 16:54:19 -04:00
Juergen Hoeller 9a27bc9b3e Upgrade to Jackson 2.9.5 and Hibernate Validator 6.0.9 2018-03-27 17:33:34 +02:00
Juergen Hoeller c072c6deb5 Refined javadoc for SimpleEvaluationContext and its builder features
Issue: SPR-16588
2018-03-27 17:07:03 +02:00
Juergen Hoeller 98ad23bef8 Consistent logging of encoded path evaluation failure
Issue: SPR-16616
2018-03-27 17:04:59 +02:00
Sam Brannen 75f70b269e Introduce @Nested tests with constructor injection
This commit introduces @Nested tests to verify support for constructor
injection when using the SpringExtension.

One of the tests is disabled on Java 8 due to a bug in javac that was
first fixed in JDK 9.

See https://github.com/junit-team/junit5/issues/1345 for details.
2018-03-27 16:45:26 +02:00
Sam Brannen b6e9d1c9ad Publish SpEL content in Reference Manual 2018-03-27 12:48:37 +02:00
Juergen Hoeller 13356a7ee2 Consistent encoded path evaluation in reactive ResourceWebHandler and co
Issue: SPR-16616
2018-03-27 01:00:42 +02:00
Juergen Hoeller e3d0ef6015 Use Map.forEach instead of manual Map.Entry iteration wherever possible
Issue: SPR-16646
2018-03-27 00:38:32 +02:00
Juergen Hoeller 10cb2ccaef Avoid triggering lazy resolution in MultipartResolver.cleanupMultipart
Issue: SPR-16640
2018-03-27 00:25:05 +02:00
Juergen Hoeller 24aae2e104 Defensive containsSingleton cache guard within getObjectFromFactoryBean
Issue: SPR-16625
2018-03-27 00:24:03 +02:00
Juergen Hoeller f59ea610df Simplified separator check within isInvalidEncodedPath
Issue: SPR-16616
2018-03-27 00:23:36 +02:00
Juergen Hoeller c60cefa331 SimpleEvaluationContext.Builder withRootObject/withTypedRootObject
Issue: SPR-16588
2018-03-27 00:22:54 +02:00
Rossen Stoyanchev 19875d8e3f Document WebFlux concurrency model
Issue: SPR-16538
2018-03-26 09:59:38 -04:00
Juergen Hoeller c441d60d1d Upgrade to Kotlin 1.2.31 and RxJava 2.1.12
Includes H2 1.4.197 and Selenium HtmlUnit Driver 2.29.3 as well.
2018-03-24 16:48:53 +01:00
Juergen Hoeller 8d5587fe4f Consistent thread-safe iteration in DefaultSingletonBeanRegistry
Issue: SPR-16620
2018-03-24 16:30:51 +01:00
Juergen Hoeller 9128226da4 SimpleEvaluationContext.Builder withMethodResolvers/withInstanceMethods
Includes DataBindingMethodResolver as ReflectiveMethodResolver subclass.

Issue: SPR-16588
2018-03-24 16:30:37 +01:00
Rossen Stoyanchev a989ea0867 Polish Synchronoss message reader
Issue: SPR-16639
2018-03-24 08:59:16 -04:00
Rossen Stoyanchev 729d0d2796 Property handling of Void.class in WebClient retrieve()
Issue: SPR-16636
2018-03-23 22:21:06 -04:00
Rossen Stoyanchev ab2410c754 MimeTypeUtils uses SecureRandom
The prevailing current wisdom is to use the default constructor for
secure and let it pick the best algorithm for the OS.

On Java 8 (Oracle), Linux this results in "NativePRNG" which uses
/dev/random (potentially blocking) for the initial seed, and
/dev/urandom (non-blocking) for subsequent calls to nextInt.

Issue: SPR-16635
2018-03-23 21:45:41 -04:00
Rossen Stoyanchev f6ea7407e6 Improve docs on client-side multipart requests
Issue: SPR-16635
2018-03-23 21:44:27 -04:00
Rossen Stoyanchev d007c25585 Improve docs on RestTemplate
In preparation for adding multipart content.

Issue: SPR-16635
2018-03-23 21:44:18 -04:00
Rossen Stoyanchev 0af847c01c ServerSentEventHttpMessageReader internal refactoring
Eliminate use of .block() which Reactor now flags as illegal on
schedulers where that's not expected.
2018-03-23 19:01:11 -04:00
Juergen Hoeller b2f900e518 Upgrade to Hibernate ORM 5.2.16 and 5.1.13 2018-03-23 17:36:55 +01:00
Juergen Hoeller f00afe3247 Use (Concurrent)Map.computeIfAbsent for lazy nested collection creation 2018-03-23 17:36:23 +01:00
Juergen Hoeller 8d8e218b52 Consistent FactoryBean cache visibility in concurrent creation scenarios
Issue: SPR-16625
Issue: SPR-16627
2018-03-23 17:34:33 +01:00
Juergen Hoeller 937cd48fcb Contextual BeanCreationException in case of depending on a missing bean
Issue: SPR-16628
2018-03-23 17:32:08 +01:00
Juergen Hoeller 38dcd179d5 Guidance of which PropertyAccessors to use with SimpleEvaluationContext
Issue: SPR-16588
2018-03-23 17:29:21 +01:00
Rossen Stoyanchev 94924566d5 Minor typo in docs 2018-03-23 11:12:54 -04:00
Rossen Stoyanchev 3b4c7a40c0 Improve docs on @Controller methods in STOMP section
Issue: SPR-16631
2018-03-23 10:54:53 -04:00
Arjen Poutsma c56317928f Add formData() and multipartData() to ServerRequest
Issue: SPR-16551
2018-03-23 10:00:30 +01:00
Rossen Stoyanchev 1b83f129a2 ReactorNettyTcpClient uses elastic pool
Issue: SPR-16626
2018-03-22 20:22:07 -04:00
Juergen Hoeller a8688880b1 Upgrade to RxJava 2.1.11 and 1.3.7 as well as Jetty 9.4.9 2018-03-22 18:10:29 +01:00
Juergen Hoeller 51c57d77d9 SimpleEvaluationContext with dedicated factory methods for common cases
Aligned with DataBindingPropertyAccessor and shown in ref doc examples.

Issue: SPR-16588
2018-03-22 18:09:27 +01:00
Rossen Stoyanchev 025ee83403 Update CONTRIBUTING.md 2018-03-22 10:57:19 -04:00
sn42 f18d8c31e2 Correct link caption. 2018-03-22 13:21:57 +01:00
Christoph Dreis d3a0a8e007 Use Collection.removeIf() where possible (#1747)
Use Collection.removeIf() where possible

Issue: SPR-16622
2018-03-22 11:36:11 +01:00
Rossen Stoyanchev e0de9126ed Re-use EvaluationContext in DefaultSubscriptionRegistry
Rather than create a new EvaluationContext instance per evaluation, we
now create a statically shared instance, without the root object in it,
and re-use it for all evalutations.
2018-03-21 23:29:58 -04:00
Rossen Stoyanchev 19293b9847 SimpleEvaluationContext builder
Issue: SPR-16588
2018-03-21 22:36:08 -04:00
Juergen Hoeller b5511645b8 DataBindingPropertyAccessor with factory methods (forReadOnlyAccess etc)
Includes configurable write support at ReflectivePropertyAccessor level.

Issue: SPR-16588
2018-03-22 00:03:06 +01:00
Rossen Stoyanchev 94c525cdc8 Polish @RequestPart support 2018-03-21 18:26:13 -04:00
Juergen Hoeller c1405ef140 Polishing 2018-03-21 16:12:42 +01:00
Juergen Hoeller ba5ef6456f WebFluxResponseStatusExceptionHandler for @ResponseStatus introspection
The web.server package is quite low-level and should not depend on web.bind in order to avoid a dependency cycle. Extracting the introspection of the ResponseStatus annotation into a WebFlux-level subclass resolves the cycle.

Issue: SPR-16567
2018-03-21 16:12:32 +01:00
Juergen Hoeller 639d2c6fe7 Polishing 2018-03-21 12:39:15 +01:00
Juergen Hoeller 1fd5935afa SimplePropertyAccessor with configurable write support
Issue: SPR-16588
2018-03-21 12:06:40 +01:00
Juergen Hoeller 91b803a231 Consistent encoded path evaluation in ResourceHttpRequestHandler and co
Issue: SPR-16616
2018-03-21 12:02:13 +01:00
Rossen Stoyanchev f9df8c738a Avoid inifinite recursion in UndertowServerHttpRequest
Undertow does not provide a way to check if data is available to read
but instead we have to try to read and see if any data is returned.
This makes it impossible to implement checkOnDataAvailable without
trying to read and that can lead to infinite recursion like this:

...
UndertowServerHttpRequest$RequestBodyPublisher.checkOnDataAvailable(UndertowServerHttpRequest.java:156)
AbstractListenerReadPublisher.changeToDemandState(AbstractListenerReadPublisher.java:177)
AbstractListenerReadPublisher.access$900(AbstractListenerReadPublisher.java:47)
AbstractListenerReadPublisher$State$4.onDataAvailable(AbstractListenerReadPublisher.java:319)
AbstractListenerReadPublisher.onDataAvailable(AbstractListenerReadPublisher.java:85)
UndertowServerHttpRequest$RequestBodyPublisher.checkOnDataAvailable(UndertowServerHttpRequest.java:156)

This commit prevent the call to checkOnDataAvailable() when switching
states from READING->DEMAND which implies we exited the readAndPublish
loop because there was no more data to read.

Issue: SPR-16545
2018-03-20 17:21:33 -04:00
Rossen Stoyanchev 88a17a4b10 Reactor2TcpClient constructor with address supplier
Issue: SPR-12452
2018-03-20 12:21:45 -04:00
Rossen Stoyanchev 0e28bee0f1 Clean duplicate separators in resource URLs
Most Servlet containers do this anyway, but not all, and not
consistently for forward and backslashes.

Issue: SPR-16616
2018-03-19 17:16:03 -04:00
Juergen Hoeller fdd756ce8a Upgrade to Log4J 2.11 2018-03-19 20:39:54 +01:00
Juergen Hoeller 442ddb0845 Correct documentation of default HttpMessageConverters in RestTemplate
Issue: SPR-7885
2018-03-19 20:38:14 +01:00
Rossen Stoyanchev 2ff35daf9b Add test case based on SPR-16615 2018-03-19 13:32:10 -04:00
Rossen Stoyanchev 26bb3a0893 Improve docs on enabling Servlet 3 multipart 2018-03-19 11:20:08 -04:00
Rossen Stoyanchev 8651b8d4c1 Show use of RequestEntity rather than HttpEntity
Issue: SPR-16608
2018-03-19 08:57:01 -04:00
Juergen Hoeller 99399084a6 Consistent Future check (even if typically encountering RunnableFuture)
Issue: SPR-16607
2018-03-19 12:42:49 +01:00
Juergen Hoeller 578c04ea17 Consistent table declarations (including fix for disarranged FTL macros)
Issue: SPR-16612
2018-03-19 12:41:22 +01:00
Juergen Hoeller 702b27e1e4 Polishing 2018-03-19 12:05:04 +01:00
Juergen Hoeller 2c7efbb9d0 Deprecate TableMetaDataContext.getSimulationQueryForGetGeneratedKey 2018-03-19 12:04:51 +01:00
Juergen Hoeller b7c423813d CallMetaDataContext handles 'procedureColumnResult' as return parameter
Issue: SPR-16611
2018-03-19 12:04:15 +01:00
Juergen Hoeller 3c1adf7f6a ThreadPoolTaskExecutor/Scheduler cancels remaining Futures on shutdown
Issue: SPR-16607
2018-03-19 01:45:22 +01:00
Wang Jingyu 9d63f805b3 Fix AsciiDoc typos in AOP documentation (#1743)
* Fix AsciiDoc typos in AOP documentation

* Polish formatting
2018-03-17 17:17:41 +01:00
Rossen Stoyanchev 30583a62cf Fix Class isAssignableFrom checks for Resource conversion
Issue: SPR-16606
2018-03-16 16:18:05 -04:00
Rossen Stoyanchev 842c29103f MultipartBodyBuilder supports PublisherEntity as input
Issue: SPR-16601
2018-03-16 16:18:05 -04:00
Rossen Stoyanchev 313c6cef32 Polish 2018-03-16 16:18:05 -04:00
Juergen Hoeller 4fef1fe820 Polishing 2018-03-16 18:49:12 +01:00
Juergen Hoeller 914b2470dc Scope annotation in class hierarchies vs XML bean definition inheritance
Issue: SPR-16602
2018-03-16 18:49:00 +01:00
Arjen Poutsma b31d55dfce Deprecated ClientRequest.method in favor of ClientRequest.create
The former method clashed with the ClientRequest.method() getter.
2018-03-16 17:27:29 +01:00
Arjen Poutsma 04c2a2990d Provide simple way to create ClientResponse
This commit introduces ClientResponse.Builder, an easier way to create a
ClientResponse from an existing response, or from scratch.

Issue: SPR-16553
2018-03-16 17:27:29 +01:00
Juergen Hoeller f8588e364a AcceptHeaderLocaleResolver keeps language match among supported locales
Issue: SPR-16599
2018-03-16 14:17:50 +01:00
Rossen Stoyanchev 7de2650a70 Drop @WebServlet annotation
Issue: SPR-16591
2018-03-16 00:14:54 -04:00
Rossen Stoyanchev 72bbb2619d Commit actions are (properly) deferred
Issue: SPR-16597
2018-03-15 23:17:57 -04:00
Rossen Stoyanchev 541ee13934 Add bufferContent option to MockRestServiceServer
Issue: SPR-14694
2018-03-15 22:13:44 -04:00
Rossen Stoyanchev f7e75a5b82 Polish MockRestServiceServer client tests 2018-03-15 22:13:43 -04:00
Rossen Stoyanchev 8d51d6769b [docs] Polish reactive types section 2018-03-15 22:13:43 -04:00
Juergen Hoeller 2096676b3f Upgrade to Apache Johnzon 1.1.7 and JRuby 9.1.16 2018-03-15 15:43:45 +01:00
Juergen Hoeller d4a8f76bf9 Consistent volatile access to running flag in Lifecycle implementations
Issue: SPR-16488
2018-03-15 15:17:55 +01:00
Rossen Stoyanchev b8d94f8a20 Improve WebFlux support for response status exceptions
Support @ResponseStatus annotated exceptions.
Supported root cause exceptions with response status information.

Issue: SPR-16567
2018-03-14 20:07:00 -04:00
Rossen Stoyanchev cb8c6e3251 Add SimpleEvaluationContext
Issue: SPR-16588
2018-03-14 15:53:19 -04:00
Juergen Hoeller 58011f71e9 Consistent assertions for template method result vs servlet registration 2018-03-14 18:55:50 +01:00
Juergen Hoeller c4e9ce8d0e Clarified repeatable PropertySource annotation vs use as meta-annotation
Issue: SPR-16592
2018-03-14 18:53:50 +01:00
Juergen Hoeller 3988dd9ebb Polishing 2018-03-14 17:24:58 +01:00
Juergen Hoeller 356ef45e99 ConcurrentReferenceHashMap properly handles getOrDefault for null values
Issue: SPR-16584
2018-03-14 17:17:04 +01:00
Stephane Nicoll cc12afdea2 Add support for deferred import selector group
This commit allows several DeferredImportSelector instances to be
grouped and managed in a centralized fashion. This typically allows
different instances to provide a consistent ordered set of imports to
apply.

Issue: SPR-16589
2018-03-13 16:52:26 -04:00
Sam Brannen 5f4d5f17f7 Polishing 2018-03-13 16:48:52 +01:00
Sam Brannen 2c2ce55f47 Support target type in JsonPath assertions for MockMvc results
This commit picks up where SPR-14498 left off by adding support for an
explicit target type when using JsonPath to perform an assertion against
the response content using a Hamcrest Matcher.

Specifically, there is a new overloaded value(Matcher<T>, Class<T>)
method in JsonPathResultMatchers for use with Hamcrest matchers where
the target type (i.e., Class<T>) can be specified.

Issue: SPR-16587
2018-03-13 15:55:39 +01:00
Bronwyn Perry-Huston d64f2eb038 Add JSON matcher to assert on request body
Support asserting JSON regardless of order and formatting.
Based on same JsonExpectationHelper used in ContentResultMatchers.

Issue: SPR-13919
2018-03-13 12:27:05 +01:00
Andy Clement 1db7e02de3 Modify SpEL code gen to take account of null safe refs
With this change the code generation for method and property
references is modified to include branching logic in the
case of null safe dereferencing (?.). This is complicated
by the possible usage of primitives on the left hand side
of the dereference. To cope with this case primitives are
promoted to boxed types when this situation occurs enabling
null to be passed as a possible result.

Issue: SPR-16489
2018-03-12 15:58:59 -07:00
Juergen Hoeller 41730220f4 InterceptingClientHttpRequest adapts to StreamingHttpOutputMessage
Issue: SPR-16582
2018-03-12 22:31:48 +01:00
Juergen Hoeller 499128dae7 URIEditor uses straight ClassPathResource.getURI() access
Issue: SPR-16581
2018-03-12 22:26:18 +01:00
sdeleuze 36a222acd5 Take into account the MimeType's charset in Jackson encoder
Notice that per specification, only Unicode is supported
(UTF8, UTF16_BE, UTF16_LE, UTF32_BE, UTF32_LE).

Issue: SPR-16539
2018-03-12 21:54:53 +01:00
Juergen Hoeller 99bb97388e Upgrade to Tomcat 8.5.29 and Selenium 3.11 2018-03-12 20:42:11 +01:00
Juergen Hoeller 04a8f81710 Polishing 2018-03-12 20:42:03 +01:00
Juergen Hoeller 967a2ef2d2 Validate Class attributes as well as Class array attributes
Issue: SPR-16564
2018-03-12 20:41:44 +01:00
Juergen Hoeller 50e980c02f Validate declared annotations before deciding between reflection and ASM
Issue: SPR-16564
2018-03-12 13:40:26 +01:00
Juergen Hoeller 1b1a69a144 SimpleAliasRegistry fully synchronizes registerAlias and removeAlias
Issue: SPR-16577
2018-03-12 13:27:48 +01:00
Sam Brannen 42b4f6e1ff Clean up warnings and dead code in spring-core module 2018-03-11 14:13:30 +01:00
Sam Brannen 2575c26020 Clean up warnings and dead code in spring-webflux module 2018-03-11 13:44:27 +01:00
Stephane Nicoll fb7c4a3066 Polish 2018-03-11 10:26:41 +01:00
Sam Brannen 1fa1f2b58a Delete unused import 2018-03-10 16:56:33 +01:00
Rossen Stoyanchev e228ded589 Include form and multipart data in WebFlux.fn chapter
Issue: SPR-16547
2018-03-09 21:16:19 -05:00
Rossen Stoyanchev a3d8c60aba Restructure functional endpoints chapter
This commit restructures the existing content to separate out Overview
content into its own section, and also introduces more formal structure
where reference type content can be expanded over time.

Issue: SPR-16547
2018-03-09 21:16:19 -05:00
Rossen Stoyanchev 3653a37e27 Polish tests 2018-03-09 21:16:18 -05:00
Sam Brannen 107f8bb5fd Polishing 2018-03-09 18:19:30 +01:00
Sam Brannen 00fea23e6b Introduce test for WebTestClient with RegEx-based JsonPath 2018-03-09 14:51:37 +01:00
Juergen Hoeller 2a3f90dc7b Upgrade to Hibernate ORM 5.2.15 and Hibernate Validator 6.0.8 2018-03-09 09:40:12 +01:00
Juergen Hoeller df8061494c TransactionTemplate equality for same transaction manager only
Issue: SPR-16572
2018-03-09 09:39:45 +01:00
Juergen Hoeller cf74b1b8be Consistent result synchronization in WebAsyncManager
Issue: SPR-16571
2018-03-09 09:03:15 +01:00
igor-suhorukov 58a5138f26 simplify lambda expression 2018-03-08 23:44:32 +01:00
igor-suhorukov 2f9d0a7de8 simplify boolean NOT operation 2018-03-08 23:44:15 +01:00
igor-suhorukov d89f9af22d parentheses should be removed from a single lambda input parameter when its type is inferred 2018-03-08 21:55:45 +01:00
igor-suhorukov 0c45c4c6a3 lamdbas containing only one statement should not nest this statement in a block 2018-03-08 21:49:04 +01:00
igor-suhorukov 6163f2d32f use more modern java API for empty collections 2018-03-08 21:41:57 +01:00
igor-suhorukov 32b689a994 use StringBuilder for complex string concatenation 2018-03-08 21:25:47 +01:00
igor-suhorukov 407ecf7334 to get rid of "magic" time constants 2018-03-08 20:37:48 +01:00
Brian Clozel ed7684d2b2 Don't implicitly check preconditions on PUT requests
Prior to this commit, the `HttpEntityMethodProcessor` would check HTTP
conditions on non-safe requests (i.e. not GET/HEAD). This would prevent
Controllers from returning `ResponseEntity` containing response headers
with updated values of `"Last-Modified"` or `ETag` once the resource has
been updated.

This commit avoids those checks for non GET/HEAD requests - this code
can still be leveraged from Controllers themselves using
`ServletWebRequest::checkNotModified` methods.

Issue: SPR-15780
2018-03-08 19:43:01 +01:00
Juergen Hoeller 50253f670e Quick access to volatile field (full synchronization only for lazy init)
Issue: SPR-16570
2018-03-08 18:13:00 +01:00
Juergen Hoeller 139dc1d373 Polishing (collapsed if checks, consistent downcasts, refined javadoc) 2018-03-08 18:11:57 +01:00
igor-suhorukov 0f7485b01d Polish: reorder the modifiers to comply with the Java Language Specification. 2018-03-08 17:57:47 +01:00
Juergen Hoeller a02aafe5fe Regular getBeanInfo call for interfaces (enabling Introspector's cache)
Issue: SPR-16568
2018-03-08 12:29:09 +01:00
Rossen Stoyanchev eb96ff2943 Doc improvements related to HTTP streaming
Issue: SPR-16494
2018-03-07 17:07:09 -05:00
Rossen Stoyanchev 568c93457a Improve ResponseBodyEmitter error handling
After send error, ignore calls to complete or completeWithError by the
application in the same thread (e.g. try-catch block), to avoid a
competing with an error callback from servlet container during which
the same action is taken.

Issue: SPR-16548
2018-03-07 15:25:31 -05:00
Rossen Stoyanchev e20652009d Improve docs on SseEmitter onComplete/onError
Issue: SPR-16548
2018-03-07 14:59:18 -05:00
Sam Brannen b14301bfba Allow TestContextManager to be compiled in Eclipse again 2018-03-07 17:44:24 +01:00
Violeta Georgieva 030bc224e3 Invert the check for ServletInputStream.isReady()
When checking whether there is still request body the first method
that should be checked is ServletInputStream.isReady() and then
ServletInputStream.isFinished(). ServletInputStream.isReady() is the active
method whereas the ServletInputStream.isFinished() is not.
It is important to call ServletInputStream.isReady() because if it returns
false it will schedule a dispatch and if the request body is already read it will
send onAllDataRead event.

Issue: SPR-16521
2018-03-07 11:23:10 -05:00
Juergen Hoeller 20287e0cb0 Polishing 2018-03-07 17:09:09 +01:00
Juergen Hoeller 934a995acb Strong recommendation for OpenPDF 1.0.5 instead of iText 2.1.7
Issue: SPR-16107

(cherry picked from commit b70d400)
2018-03-07 17:08:45 +01:00
Sam Brannen 0f5a3e2647 Polish formatting in Groovy scripts 2018-03-07 16:09:04 +01:00
Sam Brannen df0b39e8ac Add missing packages to Groovy scripts 2018-03-07 16:09:03 +01:00
Juergen Hoeller f57fcdee3c Polishing 2018-03-07 15:49:58 +01:00
Patrick0308 6f4d25a6e6 Polish "Use Java 8 forEach method on Map" 2018-03-07 15:39:58 +01:00
Sam Brannen 2454b31b30 Polish MockRestRequestMatchers[Tests] 2018-03-07 14:20:57 +01:00
Sam Brannen f932796201 Polishing 2018-03-07 13:22:36 +01:00
Sam Brannen fef0c7b151 Throw AssertionError instead of IAE in MockRestRequestMatchers 2018-03-07 13:22:21 +01:00
Yannik Hampe 4094879daf Make MockRestRequestMatchers independent of JUnit (#1720)
MockRestRequestMatchers was using org.junit.Assert.assertNotNull
and thus could not be used in projects that use e.g. TestNG instead
of JUnit 4.
2018-03-07 13:07:32 +01:00
Rossen Stoyanchev 27815847b1 content-length support in EncoderHttpMessageWriter
EncoderHttpMessageWriter checks explicitly for Mono publishers and sets
the content length, if it is known for the given data item.

Issue: SPR-16542
2018-03-06 19:04:02 -05:00
Rossen Stoyanchev 7a8e0ff3c3 Update ServerWebExchangeTests 2018-03-06 18:12:37 -05:00
Juergen Hoeller eb9c43dcbc Reliably expose nested cause exception message for PersistenceException
Issue: SPR-16559
2018-03-06 23:06:14 +01:00
Juergen Hoeller 90d768bb7f Overloaded convenience setters: setCacheControl(CacheControl), setExpires(ZonedDateTime)
Issue: SPR-16562
2018-03-06 23:06:04 +01:00
Juergen Hoeller 82515a3f01 Consistent incrementer arrangement for PostgreSQL, DB2 and SAP HANA
Includes related polishing in core.metadata and datasource.embedded and a revision of the corresponding database definitions in sql-error-codes.

Issue: SPR-16558
2018-03-06 13:36:15 +01:00
Juergen Hoeller 4a4f2c2f08 Drop version check in isGetGeneratedKeysSimulated (for PostgreSQL 10)
Issue: SPR-16556
2018-03-06 13:31:26 +01:00
Rossen Stoyanchev e48def2d35 Set readyToWrite flag after cached signals emitted
Issue: SPR-16555
2018-03-05 23:23:39 -05:00
Brian Clozel 6d26e61ac7 Guard against invalid paths in ResourceUrlProvider
This commit makes sure that no `StringIndexOutOfBoundsException` is
thrown when `getForRequestUrl` is called with a URL that's shorter than
the expected context path.

Issue: SPR-16526
2018-03-05 15:26:56 +01:00
Juergen Hoeller 4f8c4546f1 Upgrade to SnakeYAML 1.20 and Selenium 3.10 2018-03-05 15:25:01 +01:00
Juergen Hoeller a0cc80063d Concurrency and exception message refinements for test transactions 2018-03-05 13:00:35 +01:00
Juergen Hoeller ff818d56a4 Correct description for class-level @Transactional with AspectJ
Includes proper quoting of AspectJ expressions in Asciidoc.

Issue: SPR-16552
Issue: SPR-16549
2018-03-05 12:22:17 +01:00
Juergen Hoeller c543368aad Polishing 2018-03-03 17:33:48 +01:00
igor-suhorukov 06fef1e5a4 Polish: assertion arguments should be passed in the correct order 2018-03-03 16:14:45 +01:00
Stephane Nicoll 38ebb6c982 Restore includes and isCompatibleWith
See gh-1713
2018-03-03 12:41:58 +01:00
Stephane Nicoll d89d95ef1c Merge pull request #1715 from igor-suhorukov:master
* pr/1715:
  Polish
2018-03-03 12:12:45 +01:00
igor-suhorukov 129530f792 Polish
Closes gh-1715
2018-03-03 12:12:15 +01:00
Rossen Stoyanchev cef98e1125 FilePart uses correct flags when opening files
Issue: SPR-16546
2018-03-02 10:42:50 -05:00
Juergen Hoeller cec7204fca Polishing 2018-03-02 13:53:17 +01:00
Juergen Hoeller 2e164787db Upgrade to Groovy 2.4.14 and Undertow 1.4.23 2018-03-02 13:52:42 +01:00
igor-suhorukov ed936cbd89 Polish: Overriding methods should do more than simply call the same method in the super class 2018-03-02 00:06:27 +01:00
Juergen Hoeller cd4f0935c5 Revised deprecation markers 2018-03-01 23:43:06 +01:00
Juergen Hoeller cf1d162e1c Upgrade to Kotlin 1.2.30 2018-03-01 23:41:59 +01:00
Rossen Stoyanchev 9352e3d047 Add ClientRequest attribute for URI template
Issue: SPR-16537
2018-03-01 17:06:24 -05:00
Rossen Stoyanchev 36cfdf68b1 Correct log level
Issue: SPR-16528
2018-03-01 15:52:59 -05:00
Juergen Hoeller fa670dd07d Indexer enforces target descriptor only after non-null target check
Issue: SPR-16544
2018-03-01 13:31:56 +01:00
Juergen Hoeller bfddbbe731 Polishing 2018-03-01 01:39:06 +01:00
Juergen Hoeller 478162741d WebApplicationContextFacesELResolver.isReadOnly returns true for WAC
Issue: SPR-16543
2018-03-01 01:32:11 +01:00
Juergen Hoeller 6f7ad0304c Polishing 2018-03-01 00:29:38 +01:00
igor-suhorukov 83300c4b27 Polish: follow naming convention 2018-03-01 00:22:29 +01:00
igor-suhorukov 8080f56db8 Polish: "@Override" should be used on overriding and implementing methods 2018-03-01 00:15:18 +01:00
Juergen Hoeller a19d4deb24 Polishing 2018-02-28 16:41:59 +01:00
Juergen Hoeller 33cd160861 Upgrade to Reactor Bismuth SR7, Hibernate ORM 5.2.14, Common Annotations 1.3.2 2018-02-28 14:01:04 +01:00
Juergen Hoeller 9962df6527 Polishing 2018-02-28 00:09:15 +01:00
Juergen Hoeller 95aad9cdc2 Interrupt listener invoker threads on shutdown (after initial wait step)
Issue: SPR-16536
2018-02-28 00:06:46 +01:00
igor-suhorukov d1ccecd021 Polish: to get rid unnecessary array creation 2018-02-27 23:37:54 +01:00
Rossen Stoyanchev bf0308b0cf Merge pull request #1706 from mariusz-jasinski/SPR-16519 2018-02-27 15:39:30 -05:00
Rossen Stoyanchev 356ef5199e Polish
Issue: SPR-16519
2018-02-27 15:38:34 -05:00
Mariusz Jasinski 184ed6da57 Overloaded acknowledge method with StompHeaders
Issue: SPR-16519
2018-02-27 15:38:10 -05:00
igor-suhorukov 7bce04c06c Polish: combine catches block with same body 2018-02-27 12:51:28 +01:00
Rossen Stoyanchev f835f7b500 Switch to Bismuth snapshots 2018-02-26 20:41:00 -05:00
Rossen Stoyanchev e12fcca1e3 Fix failing test 2018-02-26 20:35:17 -05:00
Rossen Stoyanchev e0e90ed006 SSE writer respects charset in MediaType
Issue: SPR-16516
2018-02-26 16:42:00 -05:00
Juergen Hoeller 6663d0ff07 Support for ResolvableType.getType().getTypeName() on Java 8
Issue: SPR-16535
2018-02-26 17:19:12 +01:00
Juergen Hoeller c2d5ca9811 Proper nullable return declaration for AbstractValueAdaptingCache.lookup
Issue: SPR-15540
2018-02-26 13:05:12 +01:00
Juergen Hoeller 7d89de06e3 Enforce GMT timezone for testBindInstantFromJavaUtilDate
Issue: SPR-16534
2018-02-26 13:02:17 +01:00
Juergen Hoeller 15c97b753e Revised URI building in http.server (consistently use raw attributes)
Issue: SPR-16434
2018-02-26 13:00:38 +01:00
sdeleuze c6f5acf15d Upgrade Dokka to 0.9.16 2018-02-26 11:07:02 +01:00
Juergen Hoeller 2a379e099c Polishing 2018-02-25 21:24:38 +01:00
Juergen Hoeller 8a56cd0e8b Revised URI building in http.server (avoid package cycle with web.util)
Issue: SPR-16434
2018-02-25 21:24:10 +01:00
igor-suhorukov b202205d77 Polish: String.valueOf() should not be appended to a String 2018-02-25 21:10:19 +01:00
igor-suhorukov 49fd724d8f Polish: String function use should be optimized for single characters 2018-02-25 20:48:47 +01:00
Rossen Stoyanchev 9c55dd5961 Additional shortcut with charset in WebSocketMessage 2018-02-25 14:41:13 -05:00
Alexander Sparkowsky d3eff49c59 Fix typos in webmvc documentation 2018-02-25 19:40:25 +01:00
Juergen Hoeller 3732032ee4 Customizable PreparedStatementCreator in NamedParameterJdbcTemplate
Issue: SPR-16050
2018-02-25 18:23:00 +01:00
Juergen Hoeller 0ef9568c06 Upgrade to OkHttp 3.10 (as well as RxJava 2.1.10 and Caffeine 2.6.2) 2018-02-25 15:38:56 +01:00
Juergen Hoeller 9e55422334 Polishing 2018-02-25 15:38:32 +01:00
Juergen Hoeller 01d9475bcc Turn registered controller classes into controller instances on the fly
Issue: SPR-16520
2018-02-25 14:29:44 +01:00
Juergen Hoeller 85984f3b72 Mark Castor tests as deprecated
Issue: SPR-16219
2018-02-25 14:29:28 +01:00
igor-suhorukov c782075a13 Polish: Array designators "[]" should be on the type, not the variable 2018-02-25 13:14:20 +01:00
Juergen Hoeller 7f58d9ede0 Efficiently merge bean name result with parent result (possibly empty) 2018-02-25 00:27:06 +01:00
Juergen Hoeller 3531c104b0 Prefer Collections.addAll call with array over Set.addAll(Arrays.asList) 2018-02-25 00:21:39 +01:00
igor-suhorukov 67a91cf6f9 Polish: redundant pairs of parentheses should be removed 2018-02-25 00:01:43 +01:00
Juergen Hoeller eeecbaef2c Gson/JsonbHttpMessageConverter keeps output stream open (for SseEmitter)
Issue: SPR-16529
2018-02-23 10:49:38 +01:00
Juergen Hoeller 578c078082 Polishing 2018-02-22 15:14:20 +01:00
Juergen Hoeller 0f740527c1 Deprecated StringUtils.mergeStringArrays 2018-02-22 15:13:57 +01:00
Juergen Hoeller 1278459ad5 ReactorHttpHandlerAdapter logs bad request at warn level only
Issue: SPR-16524
2018-02-22 15:12:51 +01:00
Juergen Hoeller 3d6483873f Upgrade to Netty 4.1.22 2018-02-22 15:11:45 +01:00
Juergen Hoeller 0939492966 Upgrade to Apache Johnzon 1.1.6 2018-02-22 11:32:14 +01:00
Juergen Hoeller a5cbf5fe24 Consistent use of Collection.toArray with zero-sized array argument
Includes consistent use of ClassUtils.toClassArray (as non-null variant)

Issue: SPR-16523
2018-02-22 11:29:46 +01:00
Jinsoo Park 1ab3f88e82 Fix typo
MockMVc -> MockMvc
2018-02-21 14:22:40 -05:00
Rossen Stoyanchev bb8cddda23 Assert instances (vs classes) in MockMvc/WebTestClient
Issue: SPR-16520
2018-02-21 14:01:53 -05:00
Rossen Stoyanchev 3bfa56dff2 Polish 2018-02-21 10:29:46 -05:00
Rossen Stoyanchev 6959e66b25 JsonEOFException is wrapped as DecodingError
Jackson2Tokenizer now also wraps JsonProcessingException's on
endOfInput(), as it also does in tokenize(DataBuffer). This ensures
treating those errors as 400 vs 500.

Issue: SPR-16521
2018-02-21 10:12:33 -05:00
Rossen Stoyanchev a6d527e57a Call onAllDataRead when read() returns -1
When read returns -1, we know we've reached the end of input. Instead
of waiting for the onAllDataRead container callback, this commit
proactively calls onAllDataRead.

Issue: SPR-16521
2018-02-21 09:44:24 -05:00
Spring Buildmaster 1aaefbdd03 Next Development Version 2018-02-19 11:12:59 +00:00
Juergen Hoeller f316f6a46a Remove unnecessary assertions from annotation resolution code paths
Issue: SPR-16514
2018-02-19 10:29:09 +01:00
Juergen Hoeller 3ba858213f Upgrade to RxJava 1.3.6 2018-02-18 23:43:32 +01:00
Juergen Hoeller 0de36d2883 Consistent HttpMethod identity comparisons 2018-02-18 22:01:22 +01:00
Stephane Nicoll d1e9161ca6 Merge pull request #1691 from theHacker:patch-1
* pr/1691:
  Polish Javadoc
2018-02-18 08:57:51 +01:00
Alexander Münch 37f19a4b43 Polish Javadoc
WebSocketMessageBrokerStats's Javadoc now states the correct default
logging period.

Closes gh-1691
2018-02-18 08:57:08 +01:00
Juergen Hoeller 1ea233ac56 Upgrade to Reactor Bismuth SR6 2018-02-17 23:23:24 +01:00
Juergen Hoeller d7cab23e6d Consistent use of StringUtils.toStringArray
(cherry picked from commit 6d11b40)
2018-02-16 20:49:17 +01:00
Rossen Stoyanchev c198138d4e Polish URI encoding section 2018-02-16 14:35:15 -05:00
Rossen Stoyanchev 2b4250ec44 [doc] WebFlux has coverage of URI links
Issue: SPR-16423
2018-02-16 12:58:01 -05:00
Rossen Stoyanchev 9c679fccdf Fix intdentation 2018-02-16 12:34:25 -05:00
Rossen Stoyanchev ac495d7380 Polish ForwardedHeaderFilter and related code
Issue: SPR-16506
2018-02-16 12:17:23 -05:00
Juergen Hoeller c9d08bff41 DefaultListableBeanFactory only calls getPriority for non-null instance
Issue: SPR-16508
2018-02-16 17:27:42 +01:00
Rossen Stoyanchev 6920a1f958 ForwardedHeaderFilter handles query+fragment correctly
Issue: SPR-16506
2018-02-16 11:10:50 -05:00
Rossen Stoyanchev dcf5c646be Use correct X509 certificate attribute name
Issue: SPR-16507
2018-02-16 09:45:17 -05:00
Sam Brannen 1513e7be63 Polishing 2018-02-16 14:25:13 +01:00
Juergen Hoeller 8d3264f680 Prefer List.sort(Comparator) over Collections.sort(List, Comparator) 2018-02-16 10:23:18 +01:00
Juergen Hoeller b35274f5a7 WebSocket callbacks need to remain inner classes (retaining generics) 2018-02-16 10:22:05 +01:00
igor-suhorukov d5b0df8c3f Polish codacy warning: fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. 2018-02-16 09:38:19 +01:00
igor-suhorukov 2be4985b8f Polish: anonymous inner classes containing only one method should become lambdas,
use getOrDefault instead of ternary operator
2018-02-16 09:38:19 +01:00
Rossen Stoyanchev aa4bcedad3 Up-to-date and expanded coverage on preparing URIs
Issue: SPR-16422
2018-02-15 23:25:52 -05:00
Rossen Stoyanchev 9801afb85d Fix compile error
Update places that call UriUtils to catch the right exception that is
now raised as a result of using Charet.forName.
2018-02-15 15:59:21 -05:00
Rossen Stoyanchev 4db0d999af Polish UriBuilderFactory and implementation
Issue: SPR-16422
2018-02-15 15:44:44 -05:00
Rossen Stoyanchev 3d20db1e49 Polish UriUtils, UriComponents
Issue: SPR-16422
2018-02-15 15:44:37 -05:00
Rossen Stoyanchev 394c30efd0 Update to Bismuth snapshots 2018-02-15 11:08:05 -05:00
Juergen Hoeller cd8a1bdb8b AcceptHeaderLocaleContextResolver leniently handles invalid header value
Also falls back to language-only match among its supported locales now.

Issue: SPR-16500
Issue: SPR-16457
2018-02-15 13:14:49 +01:00
sdeleuze 067ad4c57a Update Kotlin reference documentation 2018-02-15 11:46:30 +01:00
Andy Wilkinson 52dfc4ebc4 Align spring-webflux's Webjars Locator dependency with spring-webmvc 2018-02-15 00:58:17 +01:00
Rossen Stoyanchev 3367df8637 Suggest use of OkHttp MockWebServer
Issue: SPR-16482
2018-02-14 17:32:24 -05:00
Juergen Hoeller 7baf33fea0 Avoid multiple warnings related to jackson-module-kotlin
Issue: SPR-16497
2018-02-14 21:19:57 +01:00
Rossen Stoyanchev 1aeae5d40d Fix compiler error 2018-02-14 12:23:52 -05:00
Rossen Stoyanchev 0ead0503eb AbstractJackson2Encoder uses private fields
Make the protected fields in AbstractJackson2Encoder private plus
minor refactoring to the way streaming separators are applied.

The current (5.0.3) behavior is to always use '\n', but in 5.0.4 the
newly supported "application/stream+x-jackson-smile" needs to be
excluded from that. For now, separator determination remains private
in the abstract base class, but current behavior remains which is to
apply '\n' by default.

Issue: SPR-15424
2018-02-14 12:15:01 -05:00
Juergen Hoeller 6d7573262e FormTag skips rendering of hidden fields in case of empty Map
Issue: SPR-16498
2018-02-14 17:41:45 +01:00
Juergen Hoeller de7ff556d9 Polishing 2018-02-14 17:41:08 +01:00
Sam Brannen 24adc7d3c6 Delete unused imports 2018-02-14 16:55:57 +01:00
Juergen Hoeller 95f7180298 Explicit documentation notes on transacted sessions vs AUTO_ACKNOWLEDGE
Issue: SPR-16487
2018-02-14 15:32:23 +01:00
Juergen Hoeller 3b810f3544 Consistent Class array vs vararg declarations (and related polishing) 2018-02-14 14:44:00 +01:00
Juergen Hoeller 46cbdff5c3 Consistent ControllerAdvice applicability against user-declared class
Issue: SPR-16496
2018-02-14 14:41:16 +01:00
Juergen Hoeller 766e6028d7 Defensively handle DatabaseMetaData.getConnection() returning null
Issue: SPR-16495
2018-02-14 14:40:52 +01:00
igor-suhorukov 7826567df6 Polish: lamdbas containing only one statement should not nest this statement in a block 2018-02-14 01:22:01 +01:00
Juergen Hoeller 99662bc702 Polishing 2018-02-13 23:32:10 +01:00
igor-suhorukov 45e520ed86 Polish: remove unused private fields, remove empty operator 2018-02-13 23:00:18 +01:00
Rossen Stoyanchev 1908080d5c Test for disconnected client detection
Issue: SPR-16494
2018-02-13 14:58:10 -05:00
Rossen Stoyanchev 8c37ad7ac5 Startup/shutdown log messages for AbstractHttpServer
Issue: SPR-16494
2018-02-13 14:58:10 -05:00
Juergen Hoeller 37609e4ede Object/FieldError exposes source object through unwrap/contains methods
Issue: SPR-16372
2018-02-13 17:58:31 +01:00
Stephane Nicoll 6bbc5b0f26 Merge pull request #1681 from olivergierke-patch-1
* pr/1681:
  Add explicit anchor to discussion about constructor VS. setter injection
2018-02-13 17:31:36 +01:00
Oliver Gierke 30316b16e5 Add explicit anchor to discussion about constructor VS. setter injection
This commit adds an Asciidoc anchor to the section on different injection
styles to be able to link to the discussion as official recommendation.

Closes gh-1681
2018-02-13 17:29:56 +01:00
Juergen Hoeller 0c78c9c6f7 Refined javadoc and exception messages 2018-02-13 15:25:42 +01:00
Juergen Hoeller d3cee45f30 Polishing 2018-02-13 13:15:29 +01:00
Sam Brannen c11a963b1e Remove dependency on apiguardian-api in spring-test
The apiguardian-api dependency is once again a mandatory transitive
dependency of JUnit 5 since JUnit Jupiter 5.0.3.
2018-02-13 13:04:48 +01:00
Sam Brannen 02fb5a4121 Use effectively final local variable in lambda expression 2018-02-13 12:56:36 +01:00
Juergen Hoeller c9aede3727 Upgrade to Tomcat 8.5.28 (and Selenium HtmlUnit Driver 2.29.2) 2018-02-13 12:44:34 +01:00
Vladimir Sitnikov 659f13be1c Avoid creating message arguments to Assert.isABC calls
See https://github.com/spring-projects/spring-framework/commit/67f184293b94c076b0474231f739a74f42d5ffa8
2018-02-13 12:31:49 +01:00
Juergen Hoeller b449928691 Avoid unused arguments for internal delegates 2018-02-13 11:40:28 +01:00
Rossen Stoyanchev 0585fb3999 Polish 2018-02-12 22:04:53 -05:00
Rossen Stoyanchev 4ee09c89b5 Fix regression in MappingJackson2MessageConverter
As of 4.3.13 MappingJackson2MessageConverter uses the MethodParameter
hint to obtain generic type information but it needs to be careful, and
nest one level, if the target parameter type has a Message wrapper.

Issue: SPR-16486
2018-02-12 21:30:26 -05:00
Juergen Hoeller 3c631f8ea0 SubProtocolWebSocketHandler closes sessions outside of lifecycle monitor
Issue: SPR-16488
2018-02-13 00:04:55 +01:00
Juergen Hoeller a5a069c5b1 Upgrade to JavaMail 1.6.1 2018-02-13 00:02:43 +01:00
Rossen Stoyanchev 73095955bf Refine logging in ExchangeFunctions
Notably do not log error signal since we are letting that propagate.

Also improve logging messages vs relying on the log operator.

Issue: SPR-16484
2018-02-12 15:56:04 -05:00
Juergen Hoeller b089ded5b0 Polishing 2018-02-12 15:55:18 +01:00
Juergen Hoeller d5cabca2f7 Internal adaptation to Deque semantics 2018-02-12 15:55:09 +01:00
Stephane Nicoll e7076ad35c Merge pull request #1676 from fabriziocucci:patch-1
* pr/1676:
  Fix indentation in doc
2018-02-12 08:12:55 +01:00
Fabrizio Cucci 13f942fab7 Fix indentation in doc
Closes gh-1676
2018-02-12 08:11:34 +01:00
Kazuki Shimizu 8c623c8a42 Supports ConversionService on SingleColumnRowMapper
Issue: SPR-16483
2018-02-11 22:36:50 +01:00
igor-suhorukov 711b0f50f2 Polish: replace the synchronized class "Stack" by an unsynchronized one such as "Deque". 2018-02-11 21:15:46 +01:00
Juergen Hoeller 3cbb2b7616 Upgrade to Hibernate ORM 5.1.12 (for integration tests) 2018-02-10 21:57:59 +01:00
Juergen Hoeller d00e1c5e4f Polishing 2018-02-10 21:35:46 +01:00
Juergen Hoeller b5bd977d9a Revised assertion refactoring in AbstractExpressionTests 2018-02-10 18:17:40 +01:00
Juergen Hoeller 91965500cb Upgrade to TestNG 6.14.2 and Selenium 3.9.1 2018-02-10 17:48:58 +01:00
Juergen Hoeller 55ee250659 Object/FieldError stores source object as transient (not serialized)
Issue: SPR-16372
2018-02-10 17:41:30 +01:00
igor-suhorukov 0ee505b73e Polish: assertion arguments should be passed in the correct order,
use assertNull instead of assertEquals(null, value),
declare delta as double value in assertEquals
2018-02-10 17:17:28 +01:00
Juergen Hoeller 39201adca4 Consistent handling of InterruptedException
Issue: SPR-16479
2018-02-10 13:03:33 +01:00
igor-suhorukov 6ea0af3540 Polish: Lambdas should be replaced with method references 2018-02-10 12:09:46 +01:00
igor-suhorukov d3a1d44864 Polish: Maps with keys that are enum values should be replaced with EnumMap 2018-02-10 12:09:33 +01:00
igor-suhorukov 9a6fbf59c5 Polish: follow name convention - make immutable fields final 2018-02-10 12:09:19 +01:00
Juergen Hoeller 9bb7fcd997 Object/FieldError provides access to source object (exception/violation)
Issue: SPR-16372
2018-02-09 18:42:56 +01:00
Juergen Hoeller e873b18f43 ResolvableType.forClassWithGenerics retains original TypeVariables
Issue: SPR-16456
2018-02-09 15:29:00 +01:00
Juergen Hoeller a639535f33 Upgrade to Netty 4.1.21 2018-02-09 13:33:16 +01:00
Juergen Hoeller c8b860c4b8 Streamlined BeanFactory access within DefaultLifecycleProcessor 2018-02-09 13:31:31 +01:00
Juergen Hoeller fc93f99f53 Relaxed procedure existence check on Oracle (for non-exposed synonyms)
Issue: SPR-16478
2018-02-09 13:30:31 +01:00
Stephane Nicoll 8222698eb2 Merge pull request #1569 from lonre:patch-1
* pr/1569:
  Fix typo
2018-02-09 10:18:33 +01:00
Lonre Wang b8c6734580 Fix typo
Closes gh-1569
2018-02-09 10:18:16 +01:00
Stephane Nicoll 991eb4858e Update copyright header 2018-02-09 10:16:58 +01:00
Stephane Nicoll 0d757bf3f7 Merge pull request #1671 from igor-suhorukov:master
* pr/1671:
  Change this "try" to a try-with-resources
2018-02-09 10:13:22 +01:00
igor-suhorukov c0b4b5787f Change this "try" to a try-with-resources
Closes gh-1671
2018-02-09 10:12:55 +01:00
Stephane Nicoll 909cacec42 Merge pull request #1670 from igor-suhorukov
* pr/1670:
  Collection.isEmpty() should be used to test for emptiness
2018-02-09 10:12:06 +01:00
igor-suhorukov e381514b07 Collection.isEmpty() should be used to test for emptiness
Closes gh-1670
2018-02-09 10:11:44 +01:00
Stephane Nicoll 7da40abba5 Merge pull request #1669 from igor-suhorukov
* pr/1669:
  Polish
2018-02-09 10:11:16 +01:00
igor-suhorukov 4c888d0f32 Polish
Closes gh-1669
2018-02-09 10:10:05 +01:00
Arjen Poutsma fb61af1882 Allow "release on close" for DataBuffer.asInputStream
This commit introduces DataBuffer.asInputStream(boolean), that can
release the underlying buffer when the stream is closed.

Furthermore, this commit adds additional javadoc.

Issue: SPR-16444
2018-02-08 10:11:53 +01:00
Juergen Hoeller 4318710b9b Upgrade to Hibernate 5.2.13 2018-02-07 14:14:22 +01:00
Juergen Hoeller 285b01fc79 Test with all-negated profile condition
Issue: SPR-16465
2018-02-07 14:14:11 +01:00
Juergen Hoeller ac7a699356 NamedParameterUtils.isParameterSeparator checks for non-ASCII characters
Issue: SPR-16472
2018-02-07 14:10:39 +01:00
Johnny Lim 5c0ddf3c69 Polishing 2018-02-07 10:59:10 +01:00
Rossen Stoyanchev 1b98d09855 Fix copy+paste error 2018-02-06 15:43:05 -05:00
Rossen Stoyanchev 9551b3a9bb Eliminate sub-sections in Spring MVC test chapter
The very short, summary mini-sections confuse the client-side code that
highlights the TOC item. This commit removes the sub-sections.
2018-02-06 12:16:31 -05:00
Rossen Stoyanchev efdfe9ad8d Minor Javadoc update 2018-02-06 11:23:53 -05:00
Rossen Stoyanchev 1653a32a04 Stabilize Flux.interval emissions in integration tests
After this commit the use of interval in tests is combined with
take(n).onBackpressureBuffer(n) to ensure emissions don't fail if the
fixed rate is exceeded (e.g. on slow CI server).

Tests that verify N number of items followed by verifyOnComplete()
should set the number of emissions to N.

Tests that verify N number of items followed by thenCancel() should
set the number of buffered to an arbitrary number greater than N.
2018-02-06 11:01:19 -05:00
Juergen Hoeller 41a4bdea55 Upgrade to Kotlin 1.2.21 2018-02-05 22:51:59 +01:00
Juergen Hoeller 5c813a366b Consistent use of @throws instead of @exception 2018-02-05 22:51:51 +01:00
Juergen Hoeller 0ac117ff27 Explicit notes on isolation level handling in participating transactions
Issue: SPR-16463
2018-02-05 22:51:43 +01:00
Juergen Hoeller 817a836960 Consistent object type exposure for JSON rendering (workaround for Gson)
Issue: SPR-16461
2018-02-05 22:51:33 +01:00
sdeleuze 31b25b5808 Make WebFlux Jackson refdoc section relevant for Smile
Issue: SPR-16151
2018-02-05 18:00:41 +01:00
sdeleuze 196f3f8cc1 Improve WebFlux exception logging
This commit updates HttpWebHandlerAdapter and
ResponseStatusExceptionHandler in order to specify the method/uri in the
logged message.

It also logs a WARN message for bad request (400) HTTP responses in
order to get some logs when an exception is thrown due to client error
(unable to deserialize request body for example).

Issue: SPR-16447
2018-02-05 16:08:22 +01:00
Stephane Nicoll fdde9de005 Merge pull request #1606 from kamilszymanski:arraycopy
* pr/1606:
  Replace manual array copy with native method call
2018-02-04 11:41:10 +01:00
Kamil Szymanski 61117245a6 Replace manual array copy with native method call
Closes gh-1606
2018-02-04 11:39:43 +01:00
Rossen Stoyanchev f20eacdb9b Polish 2018-02-02 15:06:59 -05:00
Rob Winch 0cd427bdd3 MockHttpServletRequestBuilder decodes pathInfo
Previously MockHttpServletRequestBuilder calculated the pathInfo from the
provided URL without decoding the value. This meant that the pathInfo
incorrectly included URL encoded values.

Now MockHttpServletRequestBuilder properly decodes the pathInfo.

Fixes: SPR-16453
2018-02-02 15:00:47 -05:00
Arjen Poutsma 609f173ebc StringDecoder shouldn't chop off strings randomly
Issue: SPR-16337
2018-02-02 15:59:21 +01:00
Juergen Hoeller cfe7ff1c81 MimeType.compareTo uses case-insensitive Charset (analogous to equals)
Issue: SPR-16458
2018-02-02 13:44:07 +01:00
Juergen Hoeller 4dc964544f AcceptHeaderLocaleResolver falls back to language-only match among its supported locales
Issue: SPR-16457
2018-02-02 12:41:59 +01:00
Juergen Hoeller c5a33d62dd TypeVariablesVariableResolver compares variables by full equality again
Issue: SPR-16456
2018-02-02 12:41:43 +01:00
Juergen Hoeller 30f6e447d5 TypeVariablesVariableResolver compares variables by name
Issue: SPR-16456
2018-02-02 11:34:36 +01:00
Juergen Hoeller b3e21ec737 MockHttpServletRequest leniently handles invalid Accept-Language header
Issue: SPR-16454
2018-02-02 11:34:22 +01:00
Juergen Hoeller 7f96827ade Polishing 2018-02-02 11:34:03 +01:00
Juergen Hoeller 4a1cc9ced7 Constructor-provided field values get recorded for failed binding result
Also, TypeMismatchExceptions get registered via BindingErrorProcessor.

Issue: SPR-16449
2018-02-02 11:33:56 +01:00
Juergen Hoeller 9c069f6cb1 Avoid String concatenation for not-null assertion in BeanProperty/DirectFieldBindingResult
Issue: SPR-16455
2018-02-02 11:33:39 +01:00
Juergen Hoeller b6ecfcf9ec CachingConnectionFactory makes its Session caching inactive during reset
Issue: SPR-16450
2018-02-02 11:33:10 +01:00
Stephane Nicoll 10caaefd0b Merge pull request #1657 from izeye:polish-20180201
* pr/1657:
  Polish SqlParameter.sqlTypesToAnonymousParameterList()
2018-02-01 09:15:37 +01:00
Johnny Lim df3241e072 Polish SqlParameter.sqlTypesToAnonymousParameterList()
Closes gh-1657
2018-02-01 09:14:56 +01:00
Stephane Nicoll f0dd31a639 Merge pull request #1656 from adamlehenbauer:master
* pr/1656:
  Fix typos
2018-02-01 08:44:57 +01:00
adamlehenbauer 8de80ffe9e Fix typos
Closes gh-1656
2018-02-01 08:43:49 +01:00
Rossen Stoyanchev 0ded239453 [doc] Update Spring MVC exception handling content
Issue: SPR-16394
2018-01-31 23:03:10 -05:00
Rossen Stoyanchev d9a93f44ae [doc] Update links to composed annotations 2018-01-31 20:39:34 -05:00
sdeleuze b6c78452b2 Update and improve script templating documentation
Issue: SPR-16447
2018-01-31 17:57:41 +01:00
Rossen Stoyanchev b77032c36e [doc] Explain custom/composed @RequestMapping annotations
Issue: SPR-16442
2018-01-31 11:03:37 -05:00
sdeleuze b2681e1f4a Add ViewResolverRegistry#scriptTemplate in WebFlux
Issue: SPR-16431
2018-01-31 10:38:08 +01:00
Juergen Hoeller c7f60d1799 SchedulerFactoryBean always ignores local factory settings in case of an external SchedulerFactory instance (expecting it to be fully initialized)
This commit includes various javadoc fixes and related refinements.

Issue: SPR-16439
2018-01-30 22:35:42 +01:00
Rossen Stoyanchev 6d909b013e Do not commit response on access to content
MockHttpServletResponse no longer calls flushBuffer on calls to
getContentAsByteArray and getContentAsString. The flushing doesn't
actually do anything useful but does commit the response leading to
unexpected side effects.

Issue: SPR-16430
2018-01-30 16:19:08 -05:00
Juergen Hoeller cd57335e46 SchedulerFactoryBean ignores local factory settings in case of external SchedulerFactory instance (unless it extends from StdSchedulerFactory)
Issue: SPR-16439
2018-01-30 21:31:04 +01:00
sdeleuze d02e4fb545 Add Vary:Access-Control-Request-Method/Headers CORS headers
This commit adds these 2 Vary headers in addition to the existing
Origin one to avoid caching of Access-Control-Request-Method and
Access-Control-Request-Headers headers which can be an issue
when allowed methods or headers are unbounded and only the
requested method or headers are returned in the response.

Issue: SPR-16413
2018-01-30 17:00:32 +01:00
Juergen Hoeller 857a5b03b7 SchedulerFactoryBean accepts external Quartz SchedulerFactory instance
Issue: SPR-16439
2018-01-30 16:55:09 +01:00
Rossen Stoyanchev f4de8615aa Fix encoding issue in ServerHttpRequest.mutate()
Issue: SPR-16434
2018-01-30 10:23:02 -05:00
Juergen Hoeller 637e09f995 Polishing 2018-01-30 16:00:30 +01:00
Juergen Hoeller ef2e16912d Formatting support for java.time.Year and java.time.Month
Issue: SPR-16437
2018-01-30 15:54:47 +01:00
Juergen Hoeller 89d2bd954a Properly analyze Java 9 class cast messages for lambda event listeners
Issue: SPR-16435
2018-01-30 15:53:58 +01:00
Rossen Stoyanchev 4f28c28287 Update Javadoc on uriTemplateHandler property
Issue: SPR-16419
2018-01-29 21:53:22 -05:00
Rossen Stoyanchev 5ff724968d [docs] View Technologies section in WebFlux
Issue: SPR-16393
2018-01-29 21:28:48 -05:00
Rossen Stoyanchev 49eec6248d [docs] Reorder View Technologies
From:
  Thymeleaf
  Groovy Markup
  FreeMarker
  JSP & JSTL
  Script Views
  XML
  Tiles
  XSLT
  PDF, Excel
  RSS, Atom
  Jackson

To:
  Thymeleaf
  FreeMarker
  Groovy Markup
  Script views
  JSP & JSTL
  Tiles
  RSS, Atom
  PDF, Excel
  Jackson
  XML
  XSLT

Also move View Technologies after MVC Config to align order with
WebFlux config.

Issue: SPR-16393
2018-01-29 16:43:51 -05:00
Rossen Stoyanchev e76973c5f0 [docs] Update view-related content
1. The View Technologies chapter in Spring MVC
2. The View Resolution and View Resolver config in WebFlux

Issue: SPR-16393
2018-01-29 16:43:51 -05:00
Juergen Hoeller 8d42888476 Upgrade to RxJava 1.3.5 and WebJars Locator 0.35
Includes Rhino 1.7.8 and JRuby 9.1.15 as well.
2018-01-29 21:31:27 +01:00
Juergen Hoeller 7772b914c6 Deep BeanCurrentlyInCreationException check in getTypeForFactoryBean
Issue: SPR-16427
2018-01-29 21:13:59 +01:00
sdeleuze 32f6ccece8 Add WebFlux support for Smile streaming
The commit brings following changes:
 - Move getDecodableMimeTypes() to AbstractJackson2Decoder
 - Move getEncodableMimeTypes() to AbstractJackson2Encoder
 - Add support for application/stream+x-jackson-smile
 - Avoid streaming line separator when Smile encoder is used
 - Use double null token in Jackson2Tokenizer to identify documents

Issue: SPR-16151
2018-01-29 18:56:25 +01:00
Juergen Hoeller e1fa65a37c Notes about HibernateJpaVendorAdapter settings vs native Hibernate rules
Issue: SPR-16428
2018-01-29 18:40:18 +01:00
Juergen Hoeller 4e194c3fbe Deprecate outdated HibernateTemplate operations in favor of lambdas
Issue: SPR-16426
2018-01-29 18:40:08 +01:00
Rossen Stoyanchev c718ddf7b0 Update CONTRIBUTING.md 2018-01-29 09:26:23 -05:00
Rossen Stoyanchev 0762131d88 Update CONTRIBUTING.md 2018-01-29 09:25:46 -05:00
Rossen Stoyanchev 00b95b10a8 Docs: result handling and view resolution
Issue: SPR-16393
2018-01-26 22:14:14 -05:00
Rossen Stoyanchev fbde97f302 Default order 0 for ServerResponseResultHandler
Issue: SPR-16420
2018-01-26 17:06:01 -05:00
Sam Brannen b612f53e27 Rename doesExist() to exists() for header assertions 2018-01-26 17:24:54 +01:00
Juergen Hoeller 0e734d83d5 @EnableAspectJAutoProxy: per application context, requires aspectjweaver
Issue: SPR-14753
Issue: SPR-15801
2018-01-26 10:38:43 +01:00
Juergen Hoeller 37ab8a700b Doc: no "useCodeAsDefaultMessage" for setValidationMessageSource
Issue: SPR-15986
2018-01-26 10:35:37 +01:00
Juergen Hoeller e49198d49f Polishing 2018-01-25 22:12:29 +01:00
Juergen Hoeller 13c735442c @Scheduled supports java.time.Duration format for its delay attributes
Issue: SPR-15455
2018-01-25 19:11:18 +01:00
Juergen Hoeller ef3f93e84a Language tag parsing support in StringUtils and StringToLocaleConverter
Issue: SPR-16188
2018-01-25 19:10:31 +01:00
Juergen Hoeller c6b0d85a7c Consistent available() support in DelegatingServletInputStream
Issue: SPR-16416
2018-01-25 19:06:20 +01:00
Ketan Padegaonkar a0c9fdba12 Fix DelegatingServletInputStream#available
Ensure that the method returns the correct number of bytes that can be
read without blocking

Issue: #SPR-16416
2018-01-25 18:02:59 +01:00
Sam Brannen 165ca12e6d Add doesExist() to HeaderAssertions for WebTestClient 2018-01-25 15:50:19 +01:00
Sam Brannen 431494096a Polishing 2018-01-25 15:49:06 +01:00
Juergen Hoeller cf100d4d03 AbstractClientSockJsSession.close propagates IOException from disconnect
Issue: SPR-16415
2018-01-25 12:24:46 +01:00
Juergen Hoeller 8e2be91353 Fine-tuned logging of WebSocket close exceptions
Issue: SPR-16409
2018-01-25 12:24:40 +01:00
Juergen Hoeller 9ef0465c34 Upgrade to Jackson 2.9.4 and RxJava 2.1.9 2018-01-25 12:24:17 +01:00
Rossen Stoyanchev b948e7cf75 Polish 2018-01-24 19:58:14 -05:00
Rossen Stoyanchev 84cc7ffdf6 Fix test failure 2018-01-24 19:55:46 -05:00
Rossen Stoyanchev 5d25ca29a6 Merge pull request #1649 from neonailol/header-does-exist-matcher 2018-01-24 17:39:15 -05:00
Rossen Stoyanchev 49f1aa78eb Polish 2018-01-24 17:37:49 -05:00
Neonailol 81ca1f7c2b Add doesExist assertion method to HeaderResultMatchers 2018-01-24 17:28:46 -05:00
Rossen Stoyanchev cf812ba831 Reference docs: improve async request content 2018-01-24 17:28:20 -05:00
Juergen Hoeller 0e6f8df0a8 ServletServerHttpRequest.getURI() ignores malformed query string
The resolved URI instance is also being cached now. This should not make a difference in a real Servlet environment but does affect tests which assumed they could modify an HttpServletRequest path behind a pre-created ServletServerHttpRequest instance. Our WebSocket test base class has been revised accordingly, re-creating the ServletServerHttpRequest in such a case.

Issue: SPR-16414
2018-01-24 22:13:40 +01:00
Stephane Nicoll 6db1b692b8 Merge pull request #1650 from izeye:polish-20180124
* pr/1650:
  Polish "Remove an unnecessary intermediate variable"
  Remove an unnecessary intermediate variable
2018-01-24 09:19:15 +01:00
Stephane Nicoll 42a2081e8c Polish "Remove an unnecessary intermediate variable"
Closes gh-1650
2018-01-24 09:18:46 +01:00
Johnny Lim 826db88509 Remove an unnecessary intermediate variable
See gh-1650
2018-01-24 09:18:24 +01:00
sdeleuze 1af052433c Document @Bean nullable parameters optional bean injection
Issue: SPR-16053
2018-01-23 18:05:05 +01:00
Rossen Stoyanchev 97894a1c22 Improve logging dependencies for tests 2018-01-23 10:42:41 -05:00
Spring Buildmaster 14fa2b18ce Next Development Version 2018-01-23 09:42:34 +00:00
Rossen Stoyanchev 4b861aeae6 Reference docs: update async request content
Issue: SPR-16203
2018-01-22 22:42:59 -05:00
Rossen Stoyanchev aee8a9c97b Upgrade to Bismuth-SR5
Issue: SPR-16385
2018-01-22 19:57:38 -05:00
Juergen Hoeller 91e6274b7d Upgrade to Apache HttpClient 4.5.5 and Tomcat 8.5.27 2018-01-22 22:11:00 +01:00
Juergen Hoeller 61579ffe7b Polishing 2018-01-22 21:34:44 +01:00
Arjen Poutsma b47491695e Support array of scalar values in Jackson2Tokenizer
Issue: SPR-16407
2018-01-22 17:08:08 +01:00
Juergen Hoeller 9d0e62ef68 Javadoc format and related polishing 2018-01-22 11:43:21 +01:00
Juergen Hoeller 3dd6c19c6d Upgrade to Netty 4.1.20 2018-01-22 11:43:06 +01:00
Arjen Poutsma 0befc60c8f Renamed DataBufferUtils/DataBufferFactory.compose to join
Issue: SPR-16365
2018-01-22 10:51:07 +01:00
sdeleuze 3f3141cdda Add additional test for SPR-16210
Issue: SPR-16210
2018-01-22 10:29:21 +01:00
Arjen Poutsma 646fcc5c2f Support Custom Headers for Multipart Async Data
This commit makes sure there is no custom Content-Disposition header
before setting one automatically.

This commit also adds a headers(Consumer<HttpHeaders>) method, so that
one can user the nicer methods of HttpHeaders, as opposed to basic
strings.

Issue: SPR-16376
2018-01-20 15:18:20 +01:00
Juergen Hoeller b2ce98e881 Upgrade to CGLIB 3.2.6
Issue: SPR-16267
2018-01-20 14:29:56 +01:00
Juergen Hoeller 395c9bd723 Consistently call HttpURLConnection.setFixedLengthStreamingMode(long)
Issue: SPR-16404
2018-01-20 14:29:40 +01:00
andrm 142f1ab42f Removed unnecessary cast to int
Since Java7 HttpURLConnection offers setFixedLengthStreamingMode method with long parameter which should be prefered over version with int argument, therefore casting ContentLength to int is no longer needed. Moreover it makes impossible to stream payload larger than Integer.MAX_VALUE
2018-01-20 14:11:15 +01:00
Stephane Nicoll 0ca4cd1cf8 Merge pull request #1647 from izeye:polish-20180120
* pr/1647:
  Polish InterceptorRegistration
2018-01-20 10:15:53 +01:00
Johnny Lim 36d42bcda4 Polish InterceptorRegistration
Closes gh-1647
2018-01-20 10:15:12 +01:00
Rossen Stoyanchev 283811b16b Ensure filename is written
Now that SPR-16307 makes it possible to write a part with a Publisher
we need to ensure we get the filename correctly when writing with
Publisher<Resource>.

Issue: SPR-16376
2018-01-19 22:12:53 -05:00
Rossen Stoyanchev aea6bb6357 Update STOMP docs on using dot as separator
Issue: SPR-16275
2018-01-19 21:51:31 -05:00
Rossen Stoyanchev 0fb31c5e36 Refine "." separator support for STOMP messaging
After this commit DefaultUserDestinationResolves no longer looks at
whether AntPathMatcher is configured with "." as separator and rather
expects to be explicitly told whether to keep the leading slash in
translated destinations which actually depends on what the message
broker supports (e.g. RabbitMQ "/", Artemis ".") or how it is
configured (simple broker could be either way).

There is also a minor improvement in SimpMessagingTemplate to ensure
user destinations are correctly formed based on what the
DefaultUserDestinationResolver expects. When using "." as separtor it
allows sending messages to "queue.q1" rather than "/queue.q1".

Issue: SPR-16275
2018-01-19 21:02:43 -05:00
Rossen Stoyanchev 17f9b61249 Polish MessageBrokerConfigurationTests 2018-01-19 21:02:43 -05:00
Rossen Stoyanchev afd248da8a MultipartHttpMessageWriter consumes source once only
The previous fix #09f1f7 did not actually address the issue but only
moved it further down, so instead of the subscribe(), it was consuming
it inside the MultipartHttpMessageWriter#write method which returned
this.body.then(), and then again for the actual request body writing.

In this commit MultipartHttpMessageWriter#write returns Mono.empty()
since we don't actually want to write the part content from there, but
only want to access it as soon as it is availabele, for writing to
the request body.

Issue: SPR-16402
2018-01-19 20:55:22 -05:00
Juergen Hoeller 572c668726 Polishing 2018-01-19 21:30:37 +01:00
Arjen Poutsma 5520e730f1 DataBufferUtils.read should not take input stream/channel as parameter
Fixed by creating `Callable`-based variants, as explained in the JIRA
issue.

Issue: SPR-16403
2018-01-19 17:38:14 +01:00
Rossen Stoyanchev 09f1f727a7 Remove explicit subscribe in MultipartHttpMessageWriter
Issue: SPR-16402
2018-01-19 10:41:08 -05:00
Juergen Hoeller 40127bd9ad Polishing 2018-01-19 12:30:10 +01:00
Juergen Hoeller 4c7414833b ResolvableType returns clone for cached state with original local source
Issue: SPR-16210
2018-01-19 12:30:03 +01:00
Rossen Stoyanchev 357fb48d13 Update docs on stomp.js library
Issue: SPR-15624
2018-01-18 13:09:40 -05:00
Rossen Stoyanchev 513461d4f1 Update STOMP overview
Issue: SPR-15624
2018-01-18 13:04:43 -05:00
Arjen Poutsma c53c8bfc5a Set 304 status on ServerResponse when ETag/LastModified match
This commit checks the Etag/LastModified headers on the incoming
request, and sets a 304 Not Modified status with no body when they
match, by delegating to ServerWebExchange.checkNotModified.

Issue: SPR-16348
2018-01-18 11:34:38 +01:00
Arjen Poutsma c211e3998b Polishing 2018-01-18 11:34:38 +01:00
Arjen Poutsma 61d330f805 Javadoc 2018-01-18 11:34:38 +01:00
Juergen Hoeller ea5f8f5a7c Consistently handle NoClassDefFoundError in BeanUtils and related places
Issue: SPR-16369
2018-01-17 20:24:57 +01:00
Rossen Stoyanchev 0c289283ff Separate from expectations from response creation
This commit separates the creation of a response so that it is executed
after the synchronized block inside which requests need to be matched
and validated (for order and count).

This allows a ResponseCreator to be slow or block if it has to.

Issue: SPR-16319
2018-01-17 13:01:40 -05:00
Rossen Stoyanchev 7ab4d0ca08 Polish MockRestServiceServer code 2018-01-17 13:01:40 -05:00
Juergen Hoeller 214576673a Proper NoClassDefFoundError check against BeanUtils.instantiateClass
Issue: SPR-16369
2018-01-17 18:29:05 +01:00
Juergen Hoeller 32b4279929 Upgrade to Kotlin 1.2.20 (and Undertow 1.4.22) 2018-01-17 18:28:26 +01:00
Stephane Nicoll 817254f2eb Merge pull request #1646 from JanStureNielsen:patch-2
* pr/1646:
  Fix doc typo
2018-01-17 18:07:04 +01:00
Jan Nielsen fed81c6f83 Fix doc typo
Closes gh-1646
2018-01-17 18:06:17 +01:00
Stephane Nicoll dfe4e01f51 Merge pull request #1645 from JanStureNielsen:patch-1
* pr/1645:
  Fix doc typo
2018-01-17 18:06:04 +01:00
Jan Nielsen df9761cb3f Fix doc typo
Closes gh-1645
2018-01-17 18:05:39 +01:00
Rossen Stoyanchev 12baafd4f0 WebFlux docs: security + consistent order for WebFlux config 2018-01-16 23:23:26 -05:00
Rossen Stoyanchev 1148b61dfa WebMVC Docs: remove old code-by-convention content
We cover this more succinctly from other places, e.g. in Model Methods
by referring to the Javadoc of Contentions, or pointing to the
RequestToViewNameTranslator.
2018-01-16 23:23:09 -05:00
Rossen Stoyanchev bb7152d6e7 WebFlux docs: matrix variables
Issue: SPR-16040
2018-01-16 22:53:40 -05:00
Rossen Stoyanchev 61fc321554 WebFlux docs: Request|ResponseBody + Http|ResponseEntity
Issue: SPR-16040
2018-01-16 22:10:04 -05:00
Rossen Stoyanchev 4f2e54fc2d Document multipart data support for WebFlux
Issue: SPR-16040
2018-01-16 16:53:19 -05:00
Rossen Stoyanchev b97fa4a5ee Update docs on multipart requests + table of parameters
Issue: SPR-16040
2018-01-16 11:33:27 -05:00
Juergen Hoeller 65a167f7fd JmsListenerAnnotationBeanPostProcessor properly deals with nested proxies
Issue: SPR-16196
2018-01-16 14:39:31 +01:00
Juergen Hoeller 0270808b3c Upgrade to EclipseLink 2.7.1 2018-01-16 14:39:14 +01:00
Timo Meinen 823a16ce17 Log SQL parameters in EclipseLink when using showSql
As of EclipseLink 2.4.0 - Juno this is not sufficient to log
SQL parameter binding. Additionally,
eclipselink.logging.parameters must be enabled.

Issue: SPR-16383
2018-01-16 14:20:49 +01:00
Sam Brannen 7b4ec72378 Upgrade to JUnit Jupiter 5.0.3
Issue: SPR-16384
2018-01-16 13:17:32 +01:00
Rossen Stoyanchev 437c33ba42 WebFlux @ModelAttribute coverage in reference
Issue: SPR-16040
2018-01-15 17:47:27 -05:00
sdeleuze 43d3abdfd5 Fix SockJs CorsConfiguration for forbidden origins
After this commit, AbstractSockJsService uses the configured allowed
origins when generating the CorsConfiguration instead of "*".

As a consequence, forbidden origin requests still result in a 403
response but now with no CORS headers in order to improve consistency
between the status code and the headers.

Issue: SPR-16304
2018-01-15 18:07:24 +01:00
Stephane Nicoll 3ae776b1fa Fix BOM link
Issue: SPR-16317
2018-01-15 17:12:19 +01:00
Rossen Stoyanchev 61352fe85b Fix compile error 2018-01-15 10:28:12 -05:00
Rossen Stoyanchev 6375cc55a3 Merge pull request #1642 from EnvOut/master 2018-01-15 10:01:54 -05:00
Rossen Stoyanchev dd09c08cdf Replace use of AbstractWebSocketMessageBrokerConfigurer 2018-01-15 10:01:14 -05:00
Sergey d6591a6329 Default methods in WebSocketMessageBrokerConfigurer
+ deprecate AbstractWebSocketMessageBrokerConfigurer
2018-01-15 09:54:55 -05:00
Stephane Nicoll 42dfa40151 Make sure endpoint settings override default factory settings
Issue: SPR-16338
2018-01-15 15:42:50 +01:00
Stephane Nicoll 89b81b0080 Merge pull request #1636 from izeye:exception-message
* pr/1636:
  Fix an exception message in ScheduledAnnotationBeanPostProcessor
2018-01-15 15:19:16 +01:00
Johnny Lim d31767eab8 Fix an exception message in ScheduledAnnotationBeanPostProcessor
Closes gh-1636
2018-01-15 15:19:02 +01:00
Juergen Hoeller b160f93495 CacheProxyFactoryBean exposes all relevant CacheInterceptor callbacks
Issue: SPR-16295
2018-01-14 23:48:21 +01:00
Juergen Hoeller 44fd2d96cc Restore original separator set (but keep new isParameterSeparator impl)
Issue: SPR-16340
2018-01-14 17:57:32 +01:00
Juergen Hoeller 9623cdec48 Functional response builders allow for non-standard HTTP status codes
Issue: SPR-16366
2018-01-14 17:45:58 +01:00
Philippe Marschall 91e39d558f Use ArrayList instead of LinkedList for known size
Spring JDBC unlike other modules uses LinkedList instead of ArrayList
in several places. There is a large body of evidence suggesting that on
contemporary hardware ArrayList is both faster and has less overhead
than even in degenerate cases of empty lists [3] or unknown size.

There are two places in Spring JDBC where the size of the list is known
in advance and an ArrayList of the correct final size can be created

 [1] https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8011200
 [2] http://cliffc.org/blog/2017/11/05/modern-hardware-performance-cache-lines/
 [3] https://bugs.openjdk.java.net/browse/JDK-8011200

Issue: SPR-16378
2018-01-14 17:45:32 +01:00
Sam Brannen c88f11f958 Avoid deprecation warnings on JDK 9 in spring-test 2018-01-13 16:45:04 +01:00
Rossen Stoyanchev 1dbcd66091 More sections in WebFlux docs @Controller argument
Issue: SPR-16040
2018-01-12 16:48:06 -05:00
Juergen Hoeller 4c9ed0d87e Polishing 2018-01-12 18:24:00 +01:00
Juergen Hoeller 06e6386dc9 CollectionUtils.lastElement for common Set/List extraction
Issue: SPR-16374
2018-01-12 18:23:52 +01:00
Juergen Hoeller 13a8f90e08 ScheduledAnnotationBeanPostProcessor properly deals with nested proxies
Issue: SPR-16196
2018-01-12 16:48:17 +01:00
Juergen Hoeller a15975d94d Log non-loadable TestExecutionListener classes at debug level only
Issue: SPR-16369
2018-01-12 16:47:46 +01:00
Juergen Hoeller 93f645800b Test for non-equality after URI normalization
Issue: SPR-16364
2018-01-12 16:46:06 +01:00
Juergen Hoeller 347c2daa2c Test for multiple interfaces at BridgeMethodResolver level
Issue: SPR-16288
2018-01-12 16:45:38 +01:00
Arjen Poutsma e39bf87b07 Add reference docs for DataBufferUtils.compose
Issue: SPR-16365
2018-01-12 11:38:50 +01:00
Arjen Poutsma 67e7c784e8 Use DataBufferUtils.compose and remove writeAggregator
Use DataBufferUtils.compose instead of writeAggregator to combine
multiple data buffers into one, as the write aggregator would not work
when the initial data buffer did not have enough capacity to contain
all subsequent buffers.

Removed writeAggregator, as it is no longer needed.

Issue: SPR-16365
2018-01-12 10:36:09 +01:00
Arjen Poutsma 384a399fd2 Add DataBufferUtils.compose
Added a utility method that composes data buffers into a single buffer.
Depending on the `DataBuffer` implementation, the returned buffer may be
a single buffer containing all data of the provided buffers, or it may
be a true composite that contains references to the buffers.

Issue: SPR-16365
2018-01-12 10:36:09 +01:00
Rossen Stoyanchev c60313de3f Refine UriTemplate match pattern
The match/matches methods of UriTemplate use a regex with (.*) in place
of URI variables, which work fine except in the end where such a
pattern can match greedily more than one segment.

This commit updates the regex to use ([^/]*) instead since URI
variables are only meant to be used within a single path segment.

Issue: SPR-16169
2018-01-11 16:36:35 -05:00
Rossen Stoyanchev 84b8ceca0f Update Javadoc for AbstractHandlerMapping properties
Clarify what PathPatternParser is used for which is CORS checks in the
very least. Some sub-classes will also use it for request mapping but
not all (e.g. RouterFunctionMapping). Hence the need to be more
explicit.
2018-01-11 12:41:04 -05:00
Rossen Stoyanchev 72e3c43375 Refine @EnableWebFlux docs for functional endpoints
@EnableWebFlux bootstraps both annotated controllers and functional
endpoints, so we need to be more explicit about which parts of the
configuration apply to which.

Issue: SPR-16360
2018-01-11 12:25:42 -05:00
Juergen Hoeller 8f6d3feaa0 Tests for non-required MultipartFile parameters
Issue: SPR-16329
2018-01-11 10:22:59 +01:00
Juergen Hoeller 121f9e3734 BridgeMethodResolver properly resolves all declared interfaces
Issue: SPR-16288
2018-01-11 10:18:27 +01:00
Rossen Stoyanchev ea73ec5c41 ResourceUrlProvider handles sanitizes double slashes
Issue: SPR-16296
2018-01-10 17:48:43 -05:00
Rossen Stoyanchev cdf2ab9737 Expand docs on WebFlux.fn + @EnableWebFlux
Issue: SPR-16360
2018-01-10 16:28:34 -05:00
sdeleuze 19a1477228 Fix Kotlin bean w/ default + secondary ctors handling
This commit polishes SPR-16022 fix in order to handle correctly
the case when primary and default constructors are the same when
a secondary constructor is defined.

Issue: SPR-16289
2018-01-10 18:29:33 +01:00
Arjen Poutsma 5adaa1030c Javadoc 2018-01-10 17:54:51 +01:00
Arjen Poutsma f7bf6460aa Reverted signature change on fromMultipartData
Reverted back from `MultiValueMap<String, Object>` to
`MultiValueMap<String, ?>`
2018-01-10 17:54:51 +01:00
Rossen Stoyanchev b36af8a11f Uncomment test after Reactor Netty fix
Issue: SPR-16246
2018-01-10 10:47:36 -05:00
Arjen Poutsma 8a129ef3da Use write aggregator from DataBufferUtils
This commit uses the newly introduced write aggregator from
DataBufferUtils throughout WebFlux.

Issue: SPR-16351
2018-01-10 11:15:47 +01:00
Arjen Poutsma 69ccba30e9 Introduce write aggregator to DataBufferUtils
As a consequence of dropping CompositeByteBuf (see prior commit),
DataBuffers fluxes that are aggregated with Flux.reduce(BiFunction) are
now required to be released, as the composite no longer holds a
reference to subsequent data buffers.

For this purpose, DataBufferUtils now has a writeAggregator that can be
used with Flux.reduce, and that released the subsequent buffers
properly.

Issue: SPR-16351
2018-01-10 11:14:02 +01:00
Arjen Poutsma e6893da971 Remove use of CompositeByteBuf in NettyDataBuffer
Prior to this commit, NettyDataBuffer had a optimization in
write(ByteBuf...), where it used a CompositeByteBuf to hold the original
and the parameter buffer.
Unfortunately, this procedure has nasty consequences when splicing
buffers (see https://stackoverflow.com/a/48111196/839733).

As of this commit, NettyDataBuffer stopped using CompositeByteBuf, and
 simply does ByteBuf.write().

Issue: SPR-16351
2018-01-10 11:05:41 +01:00
Rossen Stoyanchev 5ed0cf9027 Fix init issues in AbstractReactiveWebInitializer
Issue: SPR-16290
2018-01-09 17:32:40 -05:00
Rossen Stoyanchev 537f79f680 Merge pull request #1609 from jeff/SPR-16245 2018-01-09 16:40:46 -05:00
Rossen Stoyanchev 018469286d Polish 2018-01-09 16:39:40 -05:00
Jeff Nelson 30e40210a8 Extract protected method in AbstractRequestLoggingFilter
Issue: SPR-16245
2018-01-09 16:38:21 -05:00
Juergen Hoeller c8bdb3c602 Polishing 2018-01-09 22:20:22 +01:00
Juergen Hoeller e43439c6c3 SqlParameterSource interface exposes parameter names
Includes default implementations of getSqlType and getTypeName.

Issue: SPR-16361
2018-01-09 22:19:46 +01:00
Juergen Hoeller b2322e58d9 Support for PostgreSQL array syntax
Includes efficient separator determination.

Issue: SPR-16340
2018-01-09 22:19:05 +01:00
Masahiro Ide d9af4d6599 ResourceBundleMessageSource uses ConcurrentHashMaps instead of synchronization
Issue: https://jira.spring.io/browse/SPR-16235
2018-01-09 22:12:03 +01:00
Stephane Nicoll f72318a0ae Merge pull request #1640 from making:patch-2
* pr/1640:
  Fix source code in doc
2018-01-09 19:17:24 +01:00
Toshiaki Maki 50b46c9e35 Fix source code in doc
Closes gh-1640
2018-01-09 19:17:09 +01:00
sdeleuze 9c7de232b8 Polishing
Optimize same origin check when the request is an instance of
ServletServerHttpRequest and when there is no forwarded headers.

This commit also optimizes the getPort methods and ForwardedHeaderFilter
forwarded headers checks.

Issue: SPR-16262
2018-01-09 14:33:54 +01:00
sdeleuze c326e44488 Refine forwarded protocol support
This commit refines forwarded protocol support in order to support
proxies that only set "X-Forwarded-Proto" header and not
"X-Forwarded-Port" by performing a reset of the port in such case.

"Forwarded" header support has been updated accordingly since it
also supports similar use case, as described in SPR-15504.

Issue: SPR-16262
2018-01-09 14:33:54 +01:00
Rossen Stoyanchev 30c0616384 Improve error message
Issue: SPR-16214
2018-01-08 21:30:41 -05:00
Rossen Stoyanchev 74b5c371ba Merge pull request #1634 from lin/patch-1 2018-01-08 17:36:24 -05:00
Rossen Stoyanchev 846636f2b9 Polish 2018-01-08 17:35:30 -05:00
Aleksey Voronenkov cb8ad46564 Overloaded methods in InterceptorRegistration
Issue: SPR-16324
2018-01-08 17:31:06 -05:00
Juergen Hoeller 45828cb934 Check BeanInfoFactory for interface introspection as well
Issue: SPR-16322
2018-01-08 18:05:02 +01:00
Rossen Stoyanchev 446e7ed25c Links from @RequestMapping to reference docs
Issue: SPR-16266
2018-01-08 09:29:52 -05:00
Juergen Hoeller 73cad470e5 Upgrade to HtmlUnit 2.29 and Selenium 3.8.1 2018-01-08 13:41:36 +01:00
Juergen Hoeller 4adc820714 Warning instead of error for non-present type filter class
Issue: SPR-16356
2018-01-08 13:41:23 +01:00
Stephane Nicoll 0d151b0212 Fix SpEL syntax
Issue: SPR-16315
2018-01-08 08:46:20 +01:00
Juergen Hoeller 72590dbb21 CachingConnectionFactory does not cache producer for temporary queue/topic
Issue: SPR-16353
2018-01-08 00:26:29 +01:00
Juergen Hoeller 7a55d932f9 Build against OpenPDF 1.0.5 instead of outdated iText 2.1.7
Issue: SPR-16352
2018-01-08 00:26:10 +01:00
Skelotron b9e03cb06b SPR-16316 — fix transaction timeout value overflow 2018-01-07 23:48:24 +01:00
Juergen Hoeller 4a57e26d76 Polishing 2018-01-07 23:33:35 +01:00
Juergen Hoeller b6191f6057 Direct reference to JPA 2.1 SynchronizationType enum
Issue: SPR-13481
2018-01-07 23:30:05 +01:00
Juergen Hoeller d187cbce73 LoadTimeWeaver detection differentiates between WebSphere and Liberty
Issue SPR-16248
2018-01-07 23:29:16 +01:00
Juergen Hoeller 6a1fe0b1d0 FunctionReference's method field is volatile
Issue: SPR-16255
2018-01-07 23:23:45 +01:00
Juergen Hoeller 0a06bce3a6 Relaxed BeanFactory assertion in resolveInterceptorNames
Issue: SPR-16347
2018-01-07 23:23:25 +01:00
Juergen Hoeller 977550f956 Properly handle null bean instance in getLifecycleBeans
Issue: SPR-16343
2018-01-07 23:23:08 +01:00
Juergen Hoeller 18d90ec140 Properly handle null FactoryBean instance
Issue: SPR-16250
2018-01-07 23:22:56 +01:00
Juergen Hoeller d3e0f4dd91 Consider enum subclasses as simple value types as well
Issue: SPR-16278
2018-01-07 23:20:09 +01:00
Juergen Hoeller 9beb97880f Support for static field access on non-public enums
Issue: SPR-16284
2018-01-07 23:19:47 +01:00
Juergen Hoeller 7ad69bfc20 Avoid extra existence check in SimpleMetadataReaderFactory
Issue: SPR-16281
2018-01-07 23:18:52 +01:00
Juergen Hoeller 1a154c3e4c Consistently throw FileNotFoundException even for NIO access
Issue: SPR-16334
2018-01-07 23:18:28 +01:00
Rossen Stoyanchev 37f0e8c6e5 Access to ApplicationContext via ServerWebExchange
Issue: SPR-16298
2018-01-05 15:46:45 -05:00
Rossen Stoyanchev 93a522f336 Fix regression in BodyInserters with multipart data
The issue was introduced very recently with commit #7035ee but never
released.

Issue: SPR-16350
2018-01-05 13:59:14 -05:00
Rossen Stoyanchev 542de82c5f Document Jackson encoder/decoder behavior
Issue: SPR-16260
2018-01-04 22:02:27 -05:00
Rossen Stoyanchev 7bf9b767fd Improve HTTP message reading/writing docs
Cross-reference sections on HttpMessageReader/Writer and
HttpMessageConverter and improve the content.

Issue: SPR-16260
2018-01-04 21:15:04 -05:00
Rossen Stoyanchev 0f1f95e090 Add hasJsonPath/doesNotHaveJsonPath assertion options
Issue: SPR-16339
2018-01-03 20:27:09 -05:00
Juergen Hoeller a49123a72b Upgrade to RxJava 2.1.8 (and Protobuf 3.5.1) 2017-12-31 18:51:22 +01:00
Juergen Hoeller dd4f915234 Upgrade to JCache 1.1 (and Caffeine 2.6.1)
Issue: SPR-13574
2017-12-28 14:08:21 +01:00
sdeleuze d2616b7996 Fix RestOperations extensions parameters nullability
Issue: SPR-16328
2017-12-27 17:54:38 +01:00
sdeleuze deac8e556e Improve Kotlin extensions doc about type erasure
Since type erasure can be fixed only when using
ParameterizedTypeReference based Java methods, RestOperations and
WebFlux API documentation should be updated to specify which extensions
are subject to type erasure, and which are not.

Issue: SPR-16273
2017-12-27 17:49:18 +01:00
Stephane Nicoll 8fc16fc937 Merge pull request #1627 from nkjackzhang:patch-1
* pr/1627:
  Polish Javadoc
2017-12-23 14:20:28 +01:00
nkjackzhang ec6eed6c63 Polish Javadoc
Closes gh-1627
2017-12-23 14:19:56 +01:00
Rossen Stoyanchev 3aee3182ac Restore milestone repo for AspectJ 2017-12-22 15:13:48 -05:00
Rossen Stoyanchev f389f66270 Upgrade to Reactor Bismuth snapshots
This allows us to confirm 0.7.3 fixes and run tests against the latest
ahead of an upgrade to Reactor Netty 0.8 snapshots.

The fix for #231 and #240 are confirmed but unfortunately test case for
2017-12-22 12:50:18 -05:00
Arjen Poutsma 6c3a64578c Move ResolvableType from HttpEntity to PublisherEntity
This commit moves the ResolvableType field from HttpEntity to
PublisherEntity, a new entity type defined in MultipartBodyBuilder.
With this change, the scope of the ResolvableType is limited to
multipart-related code, instead of becoming part of the complete
HttpEntity hierarchy.

Issue: SPR-16307
2017-12-22 13:44:01 +01:00
Brian Clozel 6e587d5c57 Add new WebTestClient header assertions
This commit adds new header assertions for `WebTestClient`.

`doesNotExist` tests that a given header is not present:

    .expectHeader().doesNotExist("Cache-Control");

`contentTypeCompatibleWith` tests for MediaType compatibility:

    .expectHeader().contentTypeCompatibleWith("text/*");

Issue: SPR-16285
2017-12-21 20:34:24 +01:00
Arjen Poutsma 7035ee7ebb Support Publishers for multipart data in BodyInserters
This commit uses the changes in the previous commit to support
Publishers as parts for multipart data.

Issue: SPR-16307
2017-12-21 17:41:01 +01:00
Arjen Poutsma f23612c3a3 Add ResolvableType to HttpEntity for multipart Publishers
This commit adds a ResolvableType field to HttpEntity, in order to
support Publishers as multipart data. Without the type, the
MultipartHttpMessageWriter does not know which delegate writer to use to
write the part.

Issue: SPR-16307
2017-12-21 17:40:27 +01:00
Juergen Hoeller 9d27e86951 Upgrade to Hibernate Validator 6.0.7 2017-12-21 17:00:06 +01:00
Juergen Hoeller 4577a19190 Upgrade to Commons Pool 2.5 (and Jackson Kotlin Module 2.9.3) 2017-12-21 13:52:00 +01:00
sdeleuze 0075f13126 Improve CORS list properties combination logic
This commit allows CorsConfiguration#combine()
to differentiate permit default values set by
CorsConfiguration#applyPermitDefaultValues()
from values configured explicitly by the user.

Those permit default values will be overridden
by any user-provided ones while user-provided values
will be combined in an additive way, including
when "*" is specified.

Documentation has been improved accordingly.

Issue: SPR-15772
2017-12-20 22:38:01 +01:00
Juergen Hoeller 425a999d5e Upgrade to Gradle 4.4.1 (and Netty 4.1.19)
Issue: SPR-16237
2017-12-20 18:10:15 +01:00
Rossen Stoyanchev a8cf275aed MockServerHttpRequest builder supports query params
Issue: SPR-16280
2017-12-19 15:38:12 -05:00
Rossen Stoyanchev 6df1a7874a MockHttpServletResponse uses correct language header
Issue: SPR-16311
2017-12-19 13:56:16 -05:00
sdeleuze 99cbfd32c3 Set default view content-type with WebFlux fn
With this commit, the default content-type defined by the
view (usually "text/html;charset=UTF-8" defined in AbstractView)
is used if any, when none is defined in the response headers.

Issue: SPR-16247
2017-12-19 11:11:40 +01:00
sdeleuze e3e4f37222 Upgrade to Kotlin 1.2.10 2017-12-19 11:03:50 +01:00
Juergen Hoeller 3a51b5a9d2 Upgrade to Hibernate Validator 6.0.6 2017-12-15 15:58:12 +01:00
Arjen Poutsma b8201f48fd Typo in example code in spring reactive reference document
Issue: SPR-16300
2017-12-15 12:03:14 +01:00
Rossen Stoyanchev f4d8c7cc2b Improve decodeToMono support
This commit ensures uniform support for decodeToMono across the various
byte and String related decoders.

Issue: SPR-16253
2017-12-14 16:59:34 -05:00
Arjen Poutsma 8e253a316d Support top-level scalar values in Jackson2Tokenizer
Issue: SPR-16166
2017-12-14 16:44:40 +01:00
sdeleuze 51aa16f85f Remove -Xskip-runtime-version-check Kotlin compiler arg
This compiler argument is not needed anymore since KT-16780
has been fixed.
2017-12-14 15:08:00 +01:00
sdeleuze 8c2e5dcb4a Update Kotlin reference documentation
This commit removes the mention that Spring Boot 2.0 includes
Jackson Kotlin module since it is not the case as of M7, and
add a note about using bean validation annotations with Kotlin.
2017-12-14 14:22:59 +01:00
Juergen Hoeller 05988193b7 Upgrade to Jackson 2.9.3 and Netty 4.1.18 2017-12-13 17:55:50 +01:00
sdeleuze 6a7b197af7 Improve Jackson codecs documentation 2017-12-13 12:07:43 +01:00
sdeleuze 73a81f98d4 Allow interceptors to add existing header values
Additional commit to provide support of requests
that have a body.

Issue: SPR-15066
2017-12-13 10:08:24 +01:00
Rossen Stoyanchev 583201b02c MappingJackson2MessageConverter uses generic type
Issue: SPR-16252
2017-12-12 22:32:33 -05:00
Rossen Stoyanchev f05175586e Refine behavior on error after response committed
If the response is set and we can't change the status through
ServerHttpResponse any more, allow the error signal to propagate and
let the individual server adapters handle it. Ultimately that should
result in closing the connection.

On Servlet containers, we check one last time if the response is
committed (we may not have filled the buffer). If not then save
the exception as a request attribute, dispatch, and re-throw it on the
container thread.

On Undertow access the connection and close it.

On Netty just let the error through to Reactor Netty.

Issue: SPR-16051
2017-12-12 14:51:24 -05:00
Juergen Hoeller 9d421841d5 Merge pull request #1622 from dreis2211/SPR-16293
Improve performance of some string operations

Issue: SPR-16293
2017-12-12 18:36:07 +01:00
Christoph Dreis 260ebeca3a Improve performance of some string operations
Issue: SPR-16293
2017-12-12 17:14:24 +01:00
Rossen Stoyanchev f736b665bd Fix compile issue from previous commit 2017-12-11 16:37:11 -05:00
Rémi Alvergnat 76dcde9e31 Fix Stomp Broker Relay ignoring destination prefixes in some cases
Issue: SPR-16265
2017-12-11 13:25:29 -08:00
sdeleuze 554662ebab Allow interceptors to add existing header values
Provide a fully mutable HttpHeaders to ClientHttpRequestInterceptors
of a RestTemplate when headers are set using HttpEntity. This avoids
UnsupportedOperationException if both HttpEntity and
ClientHttpRequestInterceptor add values for the same HTTP header.

Issue: SPR-15066
2017-12-11 15:01:20 +01:00
sdeleuze ac00d8a215 Use JCenter first to resolve plugins
This is a workaround for Kotlin/dokka#146.
2017-12-11 12:07:17 +01:00
sdeleuze 769ea1b106 Fix Kdoc regression to show only Kotlin API
As of Gradle Kotlin plugin 1.1.60,
project.sourceSets.main.kotlin.srcDirs contains
Java source directories in addition to Kotlin
ones. This commit filter out Java sources to
retain only Kotlin ones.

Issue: SPR-16268
2017-12-11 11:28:39 +01:00
Stephane Nicoll 206a5e02dd Merge pull request #1615 from gro-gg:patch-1
* pr/1615:
  Fix exception message
2017-12-09 15:46:55 -08:00
Philipp Grogg 591429e538 Fix exception message
initialDelayString is parsed into long, not integer.

Closes gh-1615
2017-12-09 15:46:28 -08:00
Juergen Hoeller d198626618 Upgrade to Gradle 4.4 (and Apache HttpClient 4.5.4)
Issue: SPR-16237
2017-12-07 07:28:07 +01:00
Sam Brannen 767ea9db83 Fix minor logic error in SocketUtils 2017-12-06 17:00:29 -08:00
Tony Mitchell 9f36d170be Support identical minPort and maxPort in SocketUtils (#1612)
This commit fixes a bug where an IllegalStateException was
thrown if the minPort and maxPort values supplied to
SocketUtils.findAvailableTcpPort(int, int) were identical.
2017-12-06 16:38:46 -08:00
Sam Brannen f9689dfe48 Polishing 2017-12-06 15:54:02 -08:00
Juergen Hoeller bf8831157d Merge pull request #1614 from dreis2211/SPR-16264
Reduce access on user in SimpleBrokerMessageHandler.handleMessageInternal
2017-12-06 00:40:38 +01:00
Christoph Dreis f4e9fb52a8 Reduce access on user in SimpleBrokerMessageHandler.handleMessageInternal
Issue: SPR-16264
2017-12-05 11:18:02 +01:00
ugultopu 04ab93ceb4 Add missing verb on the note about relays 2017-12-04 11:20:39 -05:00
Juergen Hoeller 0ef117ff11 Upgrade to Tomcat 8.5.24 and Jetty 9.4.8 2017-12-03 16:03:02 +01:00
Rossen Stoyanchev fda08852ba Take content-type from ResponseEntity unconditionally
From #9a894a we began using the content-type from the ResponseEntity
but cross-checking it still against the requested content type.

Arguably there isn't any purpose in cross-checking. The only possible
outcomes are: a) it's compatible or b) it's not, which would result in
406 (NOT_ACCEPTABLE). As we've been given explicitly the media type to
use, it makes little sense to send 406, ignoring the wish to use that
content type.

Issue: SPR-16251
2017-12-02 00:43:43 -05:00
Rossen Stoyanchev 203370a810 Handle absolute URI in Reactor request.uri()
The request URI returned from HttpServerRequest.uri() typically
contains contains an absolute path but could also contain an
absolute URI. This commit adds handling for the latter, effectively
taking only the absolute path portion.

Issue: SPR-16243
2017-12-01 23:34:35 -05:00
Rossen Stoyanchev b9a1168580 Consistently return null if certificates not available
Issue: SPR-16244
2017-12-01 21:38:40 -05:00
Rossen Stoyanchev e99b0038a0 Polish 2017-12-01 21:18:13 -05:00
Rossen Stoyanchev 91d3e4402f Add test case for SPR-16246 2017-12-01 15:40:35 -05:00
Rossen Stoyanchev 44c95a4736 Adjust logging to catch sporadic PERF build failure 2017-12-01 10:11:51 -05:00
sdeleuze 7368f58518 Upgrade to Kotlin 1.2
apiVersion and languageVersion options are set to 1.1
on production code in order to avoid incompatibilities
with Kotlin 1.1 based projects or libraries.

Issue: SPR-16239
2017-11-30 14:50:16 +01:00
Rossen Stoyanchev 63c2c08e01 Update advice on file extensions in URLs
Issue: SPR-16240
2017-11-29 15:09:13 -05:00
Rossen Stoyanchev dd0d270ba2 Improve error handling when response is committed
ResponseStatusExceptionHandler lets the error through if it can't
change the status while HttpWebHandlerAdapter logs a more helpful
message (including status code) but without a full stack trace.

Issue: SPR-16231
2017-11-29 12:39:06 -05:00
Juergen Hoeller 873cb4e58b Remove unnecessary deprecation suppression 2017-11-29 15:44:08 +01:00
Juergen Hoeller b55a2631ba NamedParameterJdbcTemplate provides accessor for classic JdbcTemplate
Issue: SPR-16241
2017-11-29 15:38:21 +01:00
Rossen Stoyanchev 6f73b8b200 Add WebTestClient to Web Servlet section 2017-11-29 08:45:07 -05:00
Sam Brannen 2b68212c20 Fix grammar 2017-11-29 14:44:21 +01:00
Rossen Stoyanchev 3650ecc3bb Polish 2017-11-28 22:16:07 -05:00
Rossen Stoyanchev bec63fbb33 Update CORS chapters
- Add "Processing" section (also replaces Advanced Customizations)
- Add information on out-of-the-box behavior
- Add more deails on @CrossOririn default configuratio
- Add cross-references between Spring MVC and WebFlux
- Polish
2017-11-28 16:29:30 -05:00
Rossen Stoyanchev 375a63a041 Update README.md 2017-11-28 09:28:34 -05:00
Sam Brannen 773cd3241b Polishing 2017-11-28 14:11:21 +01:00
Juergen Hoeller f2e8171bfb Latest dependency updates (RxJava 2.1.7, TestNG 6.13.1, Selenium HtmlUnit Driver 2.28.2) 2017-11-28 12:10:26 +01:00
Rossen Stoyanchev dc3d834026 Refinements related to a committed response
1. setComplete checks the isCommitted flag to avoid an unnecessary
debug message. This method is meant to be safe to call many times.

2. setStatusCode lowers log message to TRACE, since the return value
communicates the outcome it's arguably much less critical.

3. Add comment and test case for ResponseStatusExceptionHandler.
A ResponseStatusException is clearly meant to be handled by this
handler so don't let it pass through even if the respones is
committed.

Issue: SPR-16231
2017-11-27 16:31:49 -05:00
Spring Buildmaster e30f1fbe89 Next Development Version 2017-11-27 10:52:28 +00:00
1991 changed files with 48818 additions and 28611 deletions
+11 -3
View File
@@ -8,6 +8,7 @@ First off, thank you for taking the time to contribute! :+1: :tada:
* [How to Contribute](#how-to-contribute)
* [Discuss](#discuss)
* [Create a Ticket](#create-a-ticket)
* [Ticket Lifecycle](#ticket-lifecycle)
* [Submit a Pull Request](#submit-a-pull-request)
* [Build from Source](#build-from-source)
* [Source Code Style](#source-code-style)
@@ -35,8 +36,15 @@ it helps us to make a decision.
#### Create a Ticket
Reporting an issue or making a feature request is a great way to contribute. Your feedback
and the conversations that result from it provide a continuous flow of ideas. However,
before you do that, please take the time to [research first](#Discuss).
and the conversations that result from it provide a continuous flow of ideas.
Before you create a ticket, please take the time to [research first](#discuss).
If creating a ticket after a discussion on StackOverflow, please provide a self-sufficient description in the ticket, independent of the details on StackOverview. We understand this is extra work but the issue tracker is an important place of record for design discussions and decisions that can often be referenced long after the fix version, for example to revisit decisions, to understand the origin of a feature, and so on.
When ready create a ticket in the [JIRA issue tracker](https://jira.spring.io/browse/SPR).
#### Ticket Lifecycle
When an issue is first created, it may not be assigned and will not have a fix version.
Within a day or two, the issue is assigned to a specific committer and the target
@@ -56,7 +64,7 @@ You can contribute a source code change by submitting a pull request.
[Contributor License Agreement](https://cla.pivotal.io/sign/spring). You will also be reminded
automatically when you submit a pull request.
1. For all but the most trivial of contributions, please [create a ticket](#Create-a-Ticket).
1. For all but the most trivial of contributions, please [create a ticket](#create-a-ticket).
The purpose of the ticket is to understand and discuss the underlying issue or feature.
We use the JIRA issue tracker as the preferred place of record for conversations and
conclusions. In that sense discussions directly under a PR are more implementation detail
+3 -2
View File
@@ -22,8 +22,9 @@ wiki page.
## Documentation
The Spring Frameworks maintains
[reference documentation](http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/),
The Spring Frameworks maintains reference documentation
([published](http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and
[source](src/docs/asciidoc)),
Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
[API reference](http://docs.spring.io/spring-framework/docs/current/javadoc-api/).
There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
+94 -73
View File
@@ -14,26 +14,52 @@ buildscript {
plugins {
id "com.gradle.build-scan" version "1.8"
id "io.spring.dependency-management" version "1.0.3.RELEASE" apply false
id "org.jetbrains.kotlin.jvm" version "1.1.61" apply false
id "org.jetbrains.dokka" version "0.9.15"
id "org.jetbrains.kotlin.jvm" version "1.2.71" apply false
id "org.jetbrains.dokka" version "0.9.17"
id "org.asciidoctor.convert" version "1.5.6"
}
buildScan {
licenseAgreementUrl = 'https://gradle.com/terms-of-service'
licenseAgree = 'yes'
licenseAgreementUrl = "https://gradle.com/terms-of-service"
licenseAgree = "yes"
}
ext {
linkHomepage = 'https://projects.spring.io/spring-framework'
linkCi = 'https://build.spring.io/browse/SPR'
linkIssue = 'https://jira.spring.io/browse/SPR'
linkScmUrl = 'https://github.com/spring-projects/spring-framework'
linkScmConnection = 'scm:git:git://github.com/spring-projects/spring-framework.git'
linkScmDevConnection = 'scm:git:ssh://git@github.com:spring-projects/spring-framework.git'
linkHomepage = "https://projects.spring.io/spring-framework"
linkCi = "https://build.spring.io/browse/SPR"
linkIssue = "https://jira.spring.io/browse/SPR"
linkScmUrl = "https://github.com/spring-projects/spring-framework"
linkScmConnection = "scm:git:git://github.com/spring-projects/spring-framework.git"
linkScmDevConnection = "scm:git:ssh://git@github.com:spring-projects/spring-framework.git"
moduleProjects = subprojects.findAll {
!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
!it.name.equals("spring-build-src") && !it.name.equals("spring-framework-bom")
}
aspectjVersion = "1.8.13"
freemarkerVersion = "2.3.28"
groovyVersion = "2.4.15"
hsqldbVersion = "2.4.1"
jackson2Version = "2.9.7"
jettyVersion = "9.4.14.v20181114"
junitJupiterVersion = "5.0.3"
junitPlatformVersion = "1.0.3"
junitVintageVersion = "4.12.3"
kotlinVersion = "1.2.71"
log4jVersion = "2.11.1"
nettyVersion = "4.1.31.Final"
reactorVersion = "Bismuth-SR14"
rxjavaVersion = "1.3.8"
rxjavaAdapterVersion = "1.2.1"
rxjava2Version = "2.1.17"
slf4jVersion = "1.7.25" // spring-jcl + consistent 3rd party deps
tiles3Version = "3.0.8"
tomcatVersion = "8.5.35"
undertowVersion = "1.4.26.Final"
gradleScriptDir = "${rootProject.projectDir}/gradle"
withoutJclOverSlf4J = {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
}
@@ -41,48 +67,33 @@ configure(allprojects) { project ->
group = "org.springframework"
version = qualifyVersionIfNecessary(version)
ext.aspectjVersion = "1.8.13"
ext.freemarkerVersion = "2.3.27-incubating"
ext.groovyVersion = "2.4.13"
ext.hsqldbVersion = "2.4.0"
ext.jackson2Version = "2.9.2"
ext.jettyVersion = "9.4.7.v20170914"
ext.junitJupiterVersion = "5.0.2"
ext.junitPlatformVersion = "1.0.2"
ext.junitVintageVersion = "4.12.2"
ext.kotlinVersion = "1.1.61"
ext.log4jVersion = "2.10.0"
ext.nettyVersion = "4.1.17.Final"
ext.reactorVersion = "Bismuth-SR4"
ext.rxjavaVersion = "1.3.4"
ext.rxjavaAdapterVersion = "1.2.1"
ext.rxjava2Version = "2.1.6"
ext.slf4jVersion = "1.7.25"
ext.tiles3Version = "3.0.8"
ext.tomcatVersion = "8.5.23"
ext.undertowVersion = "1.4.21.Final"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
apply plugin: "propdeps"
apply plugin: "java"
apply plugin: "kotlin"
apply plugin: "propdeps"
apply plugin: "test-source-set-dependencies"
apply plugin: "io.spring.dependency-management"
apply from: "${gradleScriptDir}/ide.gradle"
apply plugin: "kotlin"
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.freeCompilerArgs = ["-Xskip-runtime-version-check", "-Xjsr305=strict"]
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.freeCompilerArgs = ["-Xskip-runtime-version-check", "-Xjsr305=strict"]
dependencyManagement {
resolutionStrategy {
cacheChangingModulesFor 0, "seconds"
}
applyMavenExclusions = false
generatedPomCustomization {
enabled = false
}
}
configurations.all {
// Check for updates every build
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
resolutionStrategy.cacheChangingModulesFor 0, "seconds"
// Consistent slf4j version (e.g. clashes between slf4j versions)
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == "org.slf4j") {
details.useVersion slf4jVersion
}
}
}
def commonCompilerArgs =
@@ -95,22 +106,38 @@ configure(allprojects) { project ->
"-Xlint:deprecation", "-Xlint:unchecked", "-Werror"]
compileTestJava.options*.compilerArgs = commonCompilerArgs +
["-Xlint:-varargs", "-Xlint:-fallthrough","-Xlint:-rawtypes",
["-Xlint:-varargs", "-Xlint:-fallthrough", "-Xlint:-rawtypes",
"-Xlint:-deprecation", "-Xlint:-unchecked"]
compileJava {
sourceCompatibility = 1.8
sourceCompatibility = 1.8 // can be switched to 10 for testing
targetCompatibility = 1.8
options.encoding = 'UTF-8'
options.encoding = "UTF-8"
}
compileTestJava {
sourceCompatibility = 1.8
sourceCompatibility = 1.8 // can be switched to 10 for testing
targetCompatibility = 1.8
options.encoding = 'UTF-8'
options.encoding = "UTF-8"
options.compilerArgs += "-parameters"
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = ["-Xjsr305=strict"]
apiVersion = "1.1"
languageVersion = "1.1"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = ["-Xjsr305=strict"]
}
}
test {
systemProperty("java.awt.headless", "true")
systemProperty("testGroups", project.properties.get("testGroups"))
@@ -125,25 +152,25 @@ configure(allprojects) { project ->
repositories {
maven { url "https://repo.spring.io/libs-release" }
maven { url "https://repo.spring.io/milestone" } // for AspectJ 1.9 beta
}
dependencies {
testCompile("junit:junit:4.12") {
exclude group:'org.hamcrest', module:'hamcrest-core'
exclude group: "org.hamcrest", module: "hamcrest-core"
}
testCompile("org.mockito:mockito-core:2.12.0") {
exclude group:'org.hamcrest', module:'hamcrest-core'
testCompile("org.mockito:mockito-core:2.19.1") {
exclude group: "org.hamcrest", module: "hamcrest-core"
}
testCompile("com.nhaarman:mockito-kotlin:1.5.0") {
exclude module:'kotlin-stdlib'
exclude module:'kotlin-reflect'
exclude module:'mockito-core'
testCompile("com.nhaarman:mockito-kotlin:1.6.0") {
exclude module: "kotlin-stdlib"
exclude module: "kotlin-reflect"
exclude module: "mockito-core"
}
testCompile("org.hamcrest:hamcrest-all:1.3")
testCompile("org.xmlunit:xmlunit-matchers:2.3.0")
testRuntime("org.apache.logging.log4j:log4j-core:${log4jVersion}")
// JSR-305 only used for non-required meta-annotations
testRuntime("org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}")
testRuntime("org.apache.logging.log4j:log4j-jul:${log4jVersion}")
// JSR-305 only used for non-required meta-annotations
compileOnly("com.google.code.findbugs:jsr305:3.0.2")
testCompileOnly("com.google.code.findbugs:jsr305:3.0.2")
}
@@ -178,7 +205,7 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
manifest.attributes["Created-By"] =
"${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})"
from("${rootProject.projectDir}/src/dist") {
from("${rootProject.projectDir}/src/docs/dist") {
include "license.txt"
include "notice.txt"
into "META-INF"
@@ -194,7 +221,7 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
options.header = project.name
options.use = true
options.links(project.ext.javadocLinks)
options.addStringOption('Xdoclint:none', '-quiet')
options.addStringOption("Xdoclint:none", "-quiet")
// Suppress warnings due to cross-module @see and @link references.
// Note that global 'api' task does display all warnings.
@@ -204,7 +231,7 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
task sourcesJar(type: Jar, dependsOn: classes) {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
classifier = 'sources'
classifier = "sources"
from sourceSets.main.allSource
// Don't include or exclude anything explicitly by default. See SPR-12085.
}
@@ -224,7 +251,6 @@ configure(rootProject) {
description = "Spring Framework"
apply plugin: "groovy"
apply plugin: "io.spring.dependency-management"
apply from: "${gradleScriptDir}/jdiff.gradle"
apply from: "${gradleScriptDir}/docs.gradle"
@@ -232,13 +258,9 @@ configure(rootProject) {
imports {
mavenBom "io.projectreactor:reactor-bom:${reactorVersion}"
}
resolutionStrategy {
cacheChangingModulesFor 0, 'seconds'
}
applyMavenExclusions = false
}
// don't publish the default jar for the root project
// Don't publish the default jar for the root project
configurations.archives.artifacts.clear()
dependencies { // for integration tests
@@ -257,7 +279,7 @@ configure(rootProject) {
testCompile("javax.servlet:javax.servlet-api:3.1.0")
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
testCompile("org.hibernate:hibernate-core:5.1.10.Final")
testCompile("org.hibernate:hibernate-core:5.1.16.Final")
}
artifacts {
@@ -268,7 +290,7 @@ configure(rootProject) {
task wrapper(type: Wrapper) {
description = "Generates gradlew[.bat] scripts"
gradleVersion = '4.3.1'
gradleVersion = "4.4.1"
doLast() {
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
@@ -281,7 +303,6 @@ configure(rootProject) {
"set GRADLE_OPTS=$gradleBatOpts %GRADLE_OPTS%\nset DEFAULT_JVM_OPTS=")
}
}
}
/*
@@ -295,7 +316,7 @@ def qualifyVersionIfNecessary(version) {
if (rootProject.hasProperty("BRANCH_NAME")) {
def qualifier = rootProject.getProperty("BRANCH_NAME")
if (qualifier.startsWith("SPR-")) {
return version.replace('BUILD', qualifier)
return version.replace("BUILD", qualifier)
}
}
return version
+1 -1
View File
@@ -1 +1 @@
version=5.0.2.BUILD-SNAPSHOT
version=5.0.11.RELEASE
+11 -7
View File
@@ -27,6 +27,7 @@ task api(type: Javadoc) {
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
options.author = true
options.header = rootProject.description
options.use = true
options.overview = "src/docs/api/overview.html"
options.stylesheetFile = file("src/docs/api/stylesheet.css")
options.splitIndex = true
@@ -49,12 +50,9 @@ task api(type: Javadoc) {
}
}
// Need https://github.com/Kotlin/dokka/issues/184 to be fixed to avoid "Can't find node by signature" log spam
dokka {
dependsOn {
subprojects.collect {
it.tasks.getByName("jar")
}
tasks.getByName("api")
}
doFirst {
classpath = subprojects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
@@ -66,10 +64,12 @@ dokka {
outputDirectory = "$buildDir/docs/kdoc"
sourceDirs = files(subprojects.collect { project ->
project.sourceSets.main.kotlin.srcDirs
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
kotlinDirs -= project.sourceSets.main.java.srcDirs
})
externalDocumentationLink {
url = new URL("http://docs.spring.io/spring-framework/docs/${version}/javadoc-api/")
url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/")
packageListUrl = new File(buildDir, "api/package-list").toURI().toURL()
}
externalDocumentationLink {
url = new URL("http://projectreactor.io/docs/core/release/api/")
@@ -124,10 +124,14 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
into "javadoc-api"
}
from (asciidoctor) {
from ("$asciidoctor.outputDir/html5") {
into "spring-framework-reference"
}
from ("$asciidoctor.outputDir/pdf") {
into "spring-framework-reference/pdf"
}
from (dokka) {
into "kdoc-api"
}
+5
View File
@@ -18,6 +18,11 @@ def customizePom(pom, gradleProject) {
"$dep.scope:$dep.groupId:$dep.artifactId"
}
def managedVersions = dependencyManagement.managedVersions
generatedPom.dependencies.findAll{dep -> !dep.version }.each { dep ->
dep.version = managedVersions["${dep.groupId}:${dep.artifactId}"]
}
// add all items necessary for maven central publication
generatedPom.project {
name = gradleProject.description
Binary file not shown.
+2 -2
View File
@@ -1,5 +1,5 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
+1 -12
View File
@@ -1,14 +1,3 @@
/*
pluginManagement {
repositories {
maven {
url "https://dl.bintray.com/kotlin/kotlin-eap-1.1"
}
gradlePluginPortal()
}
}
*/
include "spring-aop"
include "spring-aspects"
include "spring-beans"
@@ -36,7 +25,7 @@ include "spring-framework-bom"
include "buildSrc"
rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
rootProject.name = 'spring'
rootProject.name = "spring"
rootProject.children.each {project ->
project.buildFileName = "${project.name}.gradle"
}
+2 -2
View File
@@ -2,8 +2,8 @@ description = "Spring AOP"
dependencies {
compile(project(":spring-beans"))
compile(project(':spring-core'))
compile(project(":spring-core"))
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.apache.commons:commons-pool2:2.4.3")
optional("org.apache.commons:commons-pool2:2.5.0")
optional("com.jamonapi:jamon:2.81")
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,10 +50,11 @@ import org.springframework.lang.Nullable;
public interface MethodMatcher {
/**
* Perform static checking whether the given method matches. If this
* returns {@code false} or if the {@link #isRuntime()} method
* returns {@code false}, no runtime check (i.e. no.
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made.
* Perform static checking whether the given method matches.
* <p>If this returns {@code false} or if the {@link #isRuntime()}
* method returns {@code false}, no runtime check (i.e. no
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call)
* will be made.
* @param method the candidate method
* @param targetClass the target class (may be {@code null}, in which case
* the candidate class must be taken to be the method's declaring class)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -224,6 +224,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
/**
* Set the name of the aspect (bean) in which the advice was declared.
*/
public void setAspectName(String name) {
this.aspectName = name;
}
@@ -234,7 +237,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
/**
* Sets the <b>declaration order</b> of this advice within the aspect
* Set the declaration order of this advice within the aspect.
*/
public void setDeclarationOrder(int order) {
this.declarationOrder = order;
@@ -374,7 +377,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* to which argument name. There are multiple strategies for determining
* this binding, which are arranged in a ChainOfResponsibility.
*/
public synchronized final void calculateArgumentBindings() {
public final synchronized void calculateArgumentBindings() {
// The simple case... nothing to bind.
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
return;
@@ -382,10 +385,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
int numUnboundArgs = this.parameterTypes.length;
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
numUnboundArgs--;
}
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
maybeBindJoinPointStaticPart(parameterTypes[0])) {
numUnboundArgs--;
}
@@ -421,7 +421,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
for (int i = 0; i < tokens.length; i++) {
String toMatch = tokens[i];
int firstParenIndex = toMatch.indexOf("(");
int firstParenIndex = toMatch.indexOf('(');
if (firstParenIndex != -1) {
toMatch = toMatch.substring(0, firstParenIndex);
}
@@ -582,7 +582,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
if (toMatch.startsWith("!")) {
toMatch = toMatch.substring(1);
}
int firstParenIndex = toMatch.indexOf("(");
int firstParenIndex = toMatch.indexOf('(');
if (firstParenIndex != -1) {
toMatch = toMatch.substring(0, firstParenIndex);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.aop.aspectj;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
@@ -289,10 +290,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean beanHasIntroductions) {
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
obtainPointcutExpression();
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
// Special handling for this, target, @this, @target, @annotation
// in Spring - we can optimize since we know we have exactly this class,
@@ -305,7 +305,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
else {
// the maybe case
if (beanHasIntroductions) {
if (hasIntroductions) {
return true;
}
// A match test returned maybe - if there are any subtype sensitive variables
@@ -331,8 +331,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
// consistent with return of MethodInvocationProceedingJoinPoint
@@ -367,7 +366,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* <p>See SPR-2979 for the original bug.
*/
if (pmi != null && thisObject != null) { // there is a current invocation
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
}
@@ -427,6 +426,28 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
invocation.setUserAttribute(resolveExpression(), jpm);
}
private ShadowMatch getTargetShadowMatch(Method method, @Nullable Class<?> targetClass) {
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
if (targetClass != null && targetMethod.getDeclaringClass().isInterface()) {
// Try to build the most specific interface possible for inherited methods to be
// considered for sub-interface matches as well, in particular for proxy classes.
// Note: AspectJ is only going to take Method.getDeclaringClass() into account.
Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
if (ifcs.size() > 1) {
try {
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
}
catch (IllegalArgumentException ex) {
// Implemented interfaces probably expose conflicting method signatures...
// Proceed with original target method.
}
}
}
return getShadowMatch(targetMethod, method);
}
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
// Avoid lock contention for known Methods through concurrent access...
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
@@ -434,9 +455,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
synchronized (this.shadowMatchCache) {
// Not found - now check again with full lock...
PointcutExpression fallbackExpression = null;
Method methodToMatch = targetMethod;
shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
Method methodToMatch = targetMethod;
try {
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
@@ -454,12 +475,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
fallbackExpression = null;
}
}
if (shadowMatch == null && targetMethod != originalMethod) {
if (targetMethod != originalMethod && (shadowMatch == null ||
(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
// Fall back to the plain original method in case of no resolvable match or a
// negative match on a proxy class (which doesn't carry any annotations on its
// redeclared methods).
methodToMatch = originalMethod;
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex3) {
catch (ReflectionWorldException ex) {
// Could neither introspect the target class nor the proxy class ->
// let's try the original method's declaring class before we give up...
try {
@@ -468,7 +493,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex4) {
catch (ReflectionWorldException ex2) {
fallbackExpression = null;
}
}
@@ -542,6 +567,19 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return sb.toString();
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<>(32);
}
/**
* Handler for the Spring-specific {@code bean()} pointcut designator
@@ -638,20 +676,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<>(32);
}
private static class DefensiveShadowMatch implements ShadowMatch {
private final ShadowMatch primary;
@@ -57,6 +57,16 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
this.order = order;
}
@Override
public int getOrder() {
if (this.order != null) {
return this.order;
}
else {
return this.advice.getOrder();
}
}
@Override
public boolean isPerInstance() {
return true;
@@ -72,14 +82,13 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
return this.pointcut;
}
@Override
public int getOrder() {
if (this.order != null) {
return this.order;
}
else {
return this.advice.getOrder();
}
/**
* Return the name of the aspect (bean) in which the advice was declared.
* @since 4.3.15
* @see AbstractAspectJAdvice#getAspectName()
*/
public String getAspectName() {
return this.advice.getAspectName();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,12 +36,12 @@ public interface AspectJPrecedenceInformation extends Ordered {
// its advice for aspects with non-singleton instantiation models.
/**
* The name of the aspect (bean) in which the advice was declared.
* Return the name of the aspect (bean) in which the advice was declared.
*/
String getAspectName();
/**
* The declaration order of the advice member within the aspect.
* Return the declaration order of the advice member within the aspect.
*/
int getDeclarationOrder();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import org.aopalliance.aop.Advice;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.IntroductionAdvisor;
import org.springframework.aop.IntroductionInterceptor;
import org.springframework.aop.support.ClassFilters;
import org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
@@ -34,12 +35,12 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor;
*/
public class DeclareParentsAdvisor implements IntroductionAdvisor {
private final Advice advice;
private final Class<?> introducedInterface;
private final ClassFilter typePatternClassFilter;
private final Advice advice;
/**
* Create a new advisor for this DeclareParents field.
@@ -48,8 +49,8 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param defaultImpl the default implementation class
*/
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
this(interfaceType, typePattern, defaultImpl,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
this(interfaceType, typePattern,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
}
/**
@@ -59,8 +60,7 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param delegateRef the delegate implementation object
*/
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
this(interfaceType, typePattern, delegateRef.getClass(),
new DelegatingIntroductionInterceptor(delegateRef));
this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(delegateRef));
}
/**
@@ -68,18 +68,16 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* (cannot use method such as init() to share common code, due the use of final fields)
* @param interfaceType static field defining the introduction
* @param typePattern type pattern the introduction is restricted to
* @param implementationClass implementation class
* @param advice delegation advice
* @param interceptor the delegation advice as {@link IntroductionInterceptor}
*/
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> implementationClass, Advice advice) {
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, IntroductionInterceptor interceptor) {
this.advice = interceptor;
this.introducedInterface = interfaceType;
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
// Excludes methods implemented.
ClassFilter exclusion = clazz -> !(introducedInterface.isAssignableFrom(clazz));
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
ClassFilter exclusion = (clazz -> !introducedInterface.isAssignableFrom(clazz));
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
this.advice = advice;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,17 +33,15 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Implementation of AspectJ ProceedingJoinPoint interface
* wrapping an AOP Alliance MethodInvocation.
* An implementation of the AspectJ {@link ProceedingJoinPoint} interface
* wrapping an AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}.
*
* <p><b>Note</b>: the {@code getThis()} method returns the current Spring AOP proxy.
* <p><b>Note</b>: The {@code getThis()} method returns the current Spring AOP proxy.
* The {@code getTarget()} method returns the current Spring AOP target (which may be
* {@code null} if there is no target), and is a plain POJO without any advice.
* <b>If you want to call the object and have the advice take effect, use
* {@code getThis()}.</b> A common example is casting the object to an
* introduced interface in the implementation of an introduction.
*
* <p>Of course there is no such distinction between target and proxy in AspectJ.
* {@code null} if there is no target instance) as a plain POJO without any advice.
* <b>If you want to call the object and have the advice take effect, use {@code getThis()}.</b>
* A common example is casting the object to an introduced interface in the implementation of
* an introduction. There is no such distinction between target and proxy in AspectJ itself.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -58,7 +56,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
private final ProxyMethodInvocation methodInvocation;
@Nullable
private Object[] defensiveCopyOfArgs;
private Object[] args;
/** Lazily initialized signature object */
@Nullable
@@ -79,6 +77,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
this.methodInvocation = methodInvocation;
}
@Override
public void set$AroundClosure(AroundClosure aroundClosure) {
throw new UnsupportedOperationException();
@@ -120,12 +119,10 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
@Override
public Object[] getArgs() {
if (this.defensiveCopyOfArgs == null) {
Object[] argsSource = this.methodInvocation.getArguments();
this.defensiveCopyOfArgs = new Object[argsSource.length];
System.arraycopy(argsSource, 0, this.defensiveCopyOfArgs, 0, argsSource.length);
if (this.args == null) {
this.args = this.methodInvocation.getArguments().clone();
}
return this.defensiveCopyOfArgs;
return this.args;
}
@Override
@@ -133,7 +130,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
if (this.signature == null) {
this.signature = new MethodSignatureImpl();
}
return signature;
return this.signature;
}
@Override
@@ -175,7 +175,7 @@ class RuntimeTestWalker {
}
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
private abstract static class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
private final Class<?> matchClass;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,6 +45,7 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
this.aspectClass = aspectClass;
}
/**
* Return the specified aspect class (never {@code null}).
*/
@@ -52,7 +53,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
return this.aspectClass;
}
@Override
public final Object getAspectInstance() {
try {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,6 @@ import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Abstract base class for factories that can create Spring AOP Advisors
@@ -60,6 +59,9 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static final String AJC_MAGIC = "ajc$";
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@@ -123,15 +125,13 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...)
* (there <i>should</i> only be one anyway...).
*/
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
Class<?>[] classesToLookFor = new Class<?>[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
@@ -151,14 +151,13 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
/**
* Enum for AspectJ annotation types.
* @see AspectJAnnotation#getAnnotationType()
*/
protected enum AspectJAnnotationType {
AtPointcut,
AtBefore,
AtAfter,
AtAfterReturning,
AtAfterThrowing,
AtAround
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
}
@@ -168,17 +167,17 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
*/
protected static class AspectJAnnotation<A extends Annotation> {
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
private static Map<Class<?>, AspectJAnnotationType> annotationTypes = new HashMap<>();
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap<>(8);
static {
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
annotationTypes.put(After.class,AspectJAnnotationType.AtAfter);
annotationTypes.put(AfterReturning.class,AspectJAnnotationType.AtAfterReturning);
annotationTypes.put(AfterThrowing.class,AspectJAnnotationType.AtAfterThrowing);
annotationTypes.put(Around.class,AspectJAnnotationType.AtAround);
annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore);
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
}
private final A annotation;
@@ -192,39 +191,31 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
this.annotationType = determineAnnotationType(annotation);
// We know these methods exist with the same name on each object,
// but need to invoke them reflectively as there isn't a common interface.
try {
this.pointcutExpression = resolveExpression(annotation);
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
this.argumentNames = (argNames instanceof String ? (String) argNames : "");
}
catch (Exception ex) {
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
}
}
private AspectJAnnotationType determineAnnotationType(A annotation) {
for (Class<?> type : annotationTypes.keySet()) {
if (type.isInstance(annotation)) {
return annotationTypes.get(type);
}
AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
if (type != null) {
return type;
}
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
throw new IllegalStateException("Unknown annotation type: " + annotation);
}
private String resolveExpression(A annotation) throws Exception {
for (String methodName : EXPRESSION_PROPERTIES) {
Method method;
try {
method = annotation.getClass().getDeclaredMethod(methodName);
}
catch (NoSuchMethodException ex) {
method = null;
}
if (method != null) {
String candidate = (String) method.invoke(annotation);
if (StringUtils.hasText(candidate)) {
return candidate;
private String resolveExpression(A annotation) {
for (String attributeName : EXPRESSION_ATTRIBUTES) {
Object val = AnnotationUtils.getValue(annotation, attributeName);
if (val instanceof String) {
String str = (String) val;
if (!str.isEmpty()) {
return str;
}
}
}
@@ -270,11 +261,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
if (annotation == null) {
return null;
}
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
if (strTok.countTokens() > 0) {
String[] names = new String[strTok.countTokens()];
StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
if (nameTokens.countTokens() > 0) {
String[] names = new String[nameTokens.countTokens()];
for (int i = 0; i < names.length; i++) {
names[i] = strTok.nextToken();
names[i] = nameTokens.nextToken();
}
return names;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -170,11 +170,10 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
synchronized (aspectCache) {
// To be safe, check within full lock now...
instance = aspectCache.get(aspectClass);
if (instance != null) {
return instance;
if (instance == null) {
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
aspectCache.put(aspectClass, instance);
}
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
aspectCache.put(aspectClass, instance);
}
}
return instance;
@@ -127,7 +127,7 @@ public class AspectMetadata implements Serializable {
*/
private String findPerClause(Class<?> aspectClass) {
String str = aspectClass.getAnnotation(Aspect.class).value();
str = str.substring(str.indexOf("(") + 1);
str = str.substring(str.indexOf('(') + 1);
str = str.substring(0, str.length() - 1);
return str;
}
@@ -148,7 +148,7 @@ public class AspectMetadata implements Serializable {
}
/**
* Return the aspect class.
* Return the aspect name.
*/
public String getAspectName() {
return this.aspectName;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
package org.springframework.aop.aspectj.annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -87,8 +87,8 @@ public class BeanFactoryAspectJAdvisorsBuilder {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<>();
aspectNames = new LinkedList<>();
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
@@ -138,7 +138,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new LinkedList<>();
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ import org.springframework.lang.Nullable;
class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
private static Advice EMPTY_ADVICE = new Advice() {};
private static final Advice EMPTY_ADVICE = new Advice() {};
private final AspectJExpressionPointcut declaredPointcut;
@@ -116,14 +116,41 @@ class InstantiationModelAwarePointcutAdvisorImpl
/**
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
* depending on the state of the advice.
* The pointcut for Spring AOP to use.
* Actual behaviour of the pointcut will change depending on the state of the advice.
*/
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public boolean isLazy() {
return this.lazy;
}
@Override
public synchronized boolean isAdviceInstantiated() {
return (this.instantiatedAdvice != null);
}
/**
* Lazily instantiate advice if necessary.
*/
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
/**
* This is only of interest for Spring AOP: AspectJ instantiation semantics
* are much richer. In AspectJ terminology, all a return of {@code true}
@@ -141,34 +168,6 @@ class InstantiationModelAwarePointcutAdvisorImpl
return this.aspectInstanceFactory.getAspectMetadata();
}
/**
* Lazily instantiate advice if necessary.
*/
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
@Override
public boolean isLazy() {
return this.lazy;
}
@Override
public synchronized boolean isAdviceInstantiated() {
return (this.instantiatedAdvice != null);
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
return this.aspectInstanceFactory;
}
@@ -221,33 +220,26 @@ class InstantiationModelAwarePointcutAdvisorImpl
}
else {
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
case AtAround:
this.isBeforeAdvice = false;
this.isAfterAdvice = false;
break;
case AtBefore:
this.isBeforeAdvice = true;
this.isAfterAdvice = false;
break;
case AtAfter:
case AtAfterReturning:
case AtAfterThrowing:
this.isBeforeAdvice = false;
this.isAfterAdvice = true;
this.isBeforeAdvice = false;
break;
case AtAround:
case AtPointcut:
this.isAfterAdvice = false;
this.isBeforeAdvice = false;
break;
case AtBefore:
this.isAfterAdvice = false;
this.isBeforeAdvice = true;
}
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
@@ -258,11 +250,18 @@ class InstantiationModelAwarePointcutAdvisorImpl
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
/**
* Pointcut implementation that changes its behaviour when the advice is instantiated.
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might
* be optimized out if it does not at first match statically.
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
* if it does not at first match statically.
*/
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
@@ -273,7 +272,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
@Nullable
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
public PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
this.declaredPointcut = declaredPointcut;
@@ -285,7 +284,8 @@ class InstantiationModelAwarePointcutAdvisorImpl
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
// We're either instantiated and matching on declared pointcut,
// or uninstantiated matching on either pointcut...
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,9 +20,8 @@ import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.aopalliance.aop.Advice;
@@ -122,7 +121,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new LinkedList<>();
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
@@ -148,14 +147,14 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new LinkedList<>();
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
Collections.sort(methods, METHOD_COMPARATOR);
methods.sort(METHOD_COMPARATOR);
return methods;
}
@@ -164,7 +163,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
* for the given introduction field.
* <p>Resulting Advisors will need to be evaluated for targets.
* @param introductionField the field to introspect
* @return {@code null} if not an Advisor
* @return the Advisor instance, or {@code null} if not an Advisor
*/
@Nullable
private Advisor getDeclareParentsAdvisor(Field introductionField) {
@@ -247,6 +246,15 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
@@ -271,15 +279,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
@@ -293,6 +292,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
@@ -306,13 +306,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, @Nullable Object target) {
// Simply instantiate the aspect
aif.getAspectInstance();
}
});
super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
(method, args, target) -> aif.getAspectInstance());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,14 +67,12 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
@Override
@SuppressWarnings("unchecked")
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors =
new ArrayList<>(advisors.size());
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
for (Advisor element : advisors) {
partiallyComparableAdvisors.add(
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
}
List<PartiallyComparableAdvisorHolder> sorted =
PartialOrder.sort(partiallyComparableAdvisors);
List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
if (sorted != null) {
List<Advisor> result = new ArrayList<>(advisors.size());
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
@@ -102,10 +100,9 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,11 +32,10 @@ import org.springframework.util.Assert;
/**
* Utility class for handling registration of AOP auto-proxy creators.
*
* <p>Only a single auto-proxy creator can be registered yet multiple concrete
* implementations are available. Therefore this class wraps a simple escalation
* protocol, allowing classes to request a particular auto-proxy creator and know
* that class, {@code or a subclass thereof}, will eventually be resident
* in the application context.
* <p>Only a single auto-proxy creator should be registered yet multiple concrete
* implementations are available. This class provides a simple escalation protocol,
* allowing a caller to request a particular auto-proxy creator and know that creator,
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
*
* @author Rob Harrop
* @author Juergen Hoeller
@@ -55,12 +54,10 @@ public abstract class AopConfigUtils {
/**
* Stores the auto proxy creator classes in escalation order.
*/
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>();
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
/**
* Setup the escalation list.
*/
static {
// Set up the escalation list...
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
@@ -73,8 +70,8 @@ public abstract class AopConfigUtils {
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
@@ -85,8 +82,8 @@ public abstract class AopConfigUtils {
}
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}
@@ -97,8 +94,8 @@ public abstract class AopConfigUtils {
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@@ -118,8 +115,8 @@ public abstract class AopConfigUtils {
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
@Nullable Object source) {
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,11 +28,11 @@ import org.springframework.lang.Nullable;
* Utility class for handling registration of auto-proxy creators used internally
* by the '{@code aop}' namespace tags.
*
* <p>Only a single auto-proxy creator can be registered and multiple tags may wish
* to register different concrete implementations. As such this class delegates to
* {@link AopConfigUtils} which wraps a simple escalation protocol. Therefore classes
* may request a particular auto-proxy creator and know that class, <i>or a subclass
* thereof</i>, will eventually be resident in the application context.
* <p>Only a single auto-proxy creator should be registered and multiple configuration
* elements may wish to register different concrete implementations. As such this class
* delegates to {@link AopConfigUtils} which provides a simple escalation protocol.
* Callers may request a particular auto-proxy creator and know that creator,
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
*
* @author Rob Harrop
* @author Juergen Hoeller
@@ -82,11 +82,11 @@ public abstract class AopNamespaceUtils {
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
@@ -95,9 +95,8 @@ public abstract class AopNamespaceUtils {
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
BeanComponentDefinition componentDefinition =
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
parserContext.registerComponent(componentDefinition);
parserContext.registerComponent(
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -253,8 +253,8 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
Element aspectElement, String aspectId, List<BeanDefinition> beanDefs,
List<BeanReference> beanRefs, ParserContext parserContext) {
BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[beanDefs.size()]);
BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[beanRefs.size()]);
BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[0]);
BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[0]);
Object source = parserContext.extractSource(aspectElement);
return new AspectComponentDefinition(aspectId, beanDefArray, beanRefArray, source);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof AopInfrastructureBean || this.advisor == null) {
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
@@ -92,7 +92,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
return proxyFactory.getProxy(getProxyClassLoader());
}
// No async proxy needed.
// No proxy needed.
return bean;
}
@@ -160,7 +160,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
* Subclasses may choose to implement this: for example,
* to change the interfaces exposed.
* <p>The default implementation is empty.
* @param proxyFactory ProxyFactory that is already configured with
* @param proxyFactory the ProxyFactory that is already configured with
* target, advisor and interfaces and will be used to create the proxy
* immediately after this method returns
* @since 4.2.3
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -94,7 +93,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
* List of Advisors. If an Advice is added, it will be wrapped
* in an Advisor before being added to this List.
*/
private List<Advisor> advisors = new LinkedList<>();
private List<Advisor> advisors = new ArrayList<>();
/**
* Array updated on changes to the advisors list, which is easier
@@ -153,11 +152,12 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
* @see #setTargetSource
* @see #setTarget
*/
public void setTargetClass(Class<?> targetClass) {
public void setTargetClass(@Nullable Class<?> targetClass) {
this.targetSource = EmptyTargetSource.forClass(targetClass);
}
@Override
@Nullable
public Class<?> getTargetClass() {
return this.targetSource.getTargetClass();
}
@@ -228,7 +228,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
@Override
public Class<?>[] getProxiedInterfaces() {
return this.interfaces.toArray(new Class<?>[this.interfaces.size()]);
return ClassUtils.toClassArray(this.interfaces);
}
@Override
@@ -372,7 +372,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
* Bring the array up to date with the list.
*/
protected final void updateAdvisorArray() {
this.advisorArray = this.advisors.toArray(new Advisor[this.advisors.size()]);
this.advisorArray = this.advisors.toArray(new Advisor[0]);
}
/**
@@ -474,7 +474,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
* for the given method, based on this configuration.
* @param method the proxied method
* @param targetClass the target class
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
* @return a List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
@@ -528,7 +528,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
/**
* Build a configuration-only copy of this AdvisedSupport,
* replacing the TargetSource
* replacing the TargetSource.
*/
AdvisedSupport getConfigurationOnlyCopy() {
AdvisedSupport copy = new AdvisedSupport();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -205,9 +205,8 @@ class CglibAopProxy implements AopProxy, Serializable {
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
@@ -292,20 +291,20 @@ class CglibAopProxy implements AopProxy, Serializable {
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = isStatic ?
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = isStatic ?
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
@@ -823,12 +822,16 @@ class CglibAopProxy implements AopProxy, Serializable {
}
// We must always proxy equals, to direct calls to this.
if (AopUtils.isEqualsMethod(method)) {
logger.debug("Found 'equals' method: " + method);
if (logger.isDebugEnabled()) {
logger.debug("Found 'equals' method: " + method);
}
return INVOKE_EQUALS;
}
// We must always calculate hashCode based on the proxy.
if (AopUtils.isHashCodeMethod(method)) {
logger.debug("Found 'hashCode' method: " + method);
if (logger.isDebugEnabled()) {
logger.debug("Found 'hashCode' method: " + method);
}
return INVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
@@ -63,9 +63,9 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
@@ -99,8 +99,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
* Determine whether the Advisors contain matching introductions.
*/
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
for (int i = 0; i < config.getAdvisors().length; i++) {
Advisor advisor = config.getAdvisors()[i];
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(actualClass)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ public class ProxyCreatorSupport extends AdvisedSupport {
private AopProxyFactory aopProxyFactory;
private List<AdvisedSupportListener> listeners = new LinkedList<>();
private final List<AdvisedSupportListener> listeners = new LinkedList<>();
/** Set to true when the first AOP proxy has been created */
private boolean active = false;
@@ -651,7 +651,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
}
public String getBeanName() {
return beanName;
return this.beanName;
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,9 +52,9 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
/**
* Set the ordering which will apply to this class's implementation
* of Ordered, used when applying multiple processors.
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
* Set the ordering which will apply to this processor's implementation
* of {@link Ordered}, used when applying multiple processors.
* <p>The default value is {@code Ordered.LOWEST_PRECEDENCE}, meaning non-ordered.
* @param order the ordering value
*/
public void setOrder(int order) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,15 +31,15 @@ import org.springframework.aop.Advisor;
public interface AdvisorAdapterRegistry {
/**
* Return an Advisor wrapping the given advice.
* Return an {@link Advisor} wrapping the given advice.
* <p>Should by default at least support
* {@link org.aopalliance.intercept.MethodInterceptor},
* {@link org.springframework.aop.MethodBeforeAdvice},
* {@link org.springframework.aop.AfterReturningAdvice},
* {@link org.springframework.aop.ThrowsAdvice}.
* @param advice object that should be an advice
* @return an Advisor wrapping the given advice. Never returns {@code null}.
* If the advice parameter is an Advisor, return it.
* @return an Advisor wrapping the given advice (never {@code null};
* if the advice parameter is an Advisor, it is to be returned as-is)
* @throws UnknownAdviceTypeException if no registered advisor adapter
* can wrap the supposed advice
*/
@@ -48,21 +48,20 @@ public interface AdvisorAdapterRegistry {
/**
* Return an array of AOP Alliance MethodInterceptors to allow use of the
* given Advisor in an interception-based framework.
* <p>Don't worry about the pointcut associated with the Advisor,
* if it's a PointcutAdvisor: just return an interceptor.
* <p>Don't worry about the pointcut associated with the {@link Advisor}, if it is
* a {@link org.springframework.aop.PointcutAdvisor}: just return an interceptor.
* @param advisor Advisor to find an interceptor for
* @return an array of MethodInterceptors to expose this Advisor's behavior
* @throws UnknownAdviceTypeException if the Advisor type is
* not understood by any registered AdvisorAdapter.
* not understood by any registered AdvisorAdapter
*/
MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException;
/**
* Register the given AdvisorAdapter. Note that it is not necessary to register
* Register the given {@link AdvisorAdapter}. Note that it is not necessary to register
* adapters for an AOP Alliance Interceptors or Spring Advices: these must be
* automatically recognized by an AdvisorAdapterRegistry implementation.
* @param adapter AdvisorAdapter that understands a particular Advisor
* or Advice types
* automatically recognized by an {@code AdvisorAdapterRegistry} implementation.
* @param adapter AdvisorAdapter that understands particular Advisor or Advice types
*/
void registerAdvisorAdapter(AdvisorAdapter adapter);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,8 @@ import org.springframework.util.Assert;
* to use this class directly.
*
* @author Rod Johnson
* @see MethodBeforeAdviceInterceptor
* @see ThrowsAdviceInterceptor
*/
@SuppressWarnings("serial")
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
@@ -47,6 +49,7 @@ public class AfterReturningAdviceInterceptor implements MethodInterceptor, After
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -90,7 +90,7 @@ public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Se
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
return interceptors.toArray(new MethodInterceptor[0]);
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import java.io.Serializable;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.util.Assert;
@@ -30,11 +31,13 @@ import org.springframework.util.Assert;
* to use this class directly.
*
* @author Rod Johnson
* @see AfterReturningAdviceInterceptor
* @see ThrowsAdviceInterceptor
*/
@SuppressWarnings("serial")
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private MethodBeforeAdvice advice;
private final MethodBeforeAdvice advice;
/**
@@ -46,9 +49,10 @@ public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Seriali
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,6 +51,8 @@ import org.springframework.util.Assert;
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see MethodBeforeAdviceInterceptor
* @see AfterReturningAdviceInterceptor
*/
public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
@@ -67,9 +69,8 @@ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
/**
* Create a new ThrowsAdviceInterceptor for the given ThrowsAdvice.
* @param throwsAdvice the advice object that defines the exception
* handler methods (usually a {@link org.springframework.aop.ThrowsAdvice}
* implementation)
* @param throwsAdvice the advice object that defines the exception handler methods
* (usually a {@link org.springframework.aop.ThrowsAdvice} implementation)
*/
public ThrowsAdviceInterceptor(Object throwsAdvice) {
Assert.notNull(throwsAdvice, "Advice must not be null");
@@ -78,13 +79,14 @@ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
Method[] methods = throwsAdvice.getClass().getMethods();
for (Method method : methods) {
if (method.getName().equals(AFTER_THROWING) &&
(method.getParameterCount() == 1 || method.getParameterCount() == 4) &&
Throwable.class.isAssignableFrom(method.getParameterTypes()[method.getParameterCount() - 1])
) {
// Have an exception handler
this.exceptionHandlerMap.put(method.getParameterTypes()[method.getParameterCount() - 1], method);
if (logger.isDebugEnabled()) {
logger.debug("Found exception handler method: " + method);
(method.getParameterCount() == 1 || method.getParameterCount() == 4)) {
Class<?> throwableParam = method.getParameterTypes()[method.getParameterCount() - 1];
if (Throwable.class.isAssignableFrom(throwableParam)) {
// An exception handler to register...
this.exceptionHandlerMap.put(throwableParam, method);
if (logger.isDebugEnabled()) {
logger.debug("Found exception handler method on throws advice: " + method);
}
}
}
}
@@ -95,14 +97,33 @@ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
}
}
/**
* Return the number of handler methods in this advice.
*/
public int getHandlerMethodCount() {
return this.exceptionHandlerMap.size();
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
Method handlerMethod = getExceptionHandler(ex);
if (handlerMethod != null) {
invokeHandlerMethod(mi, ex, handlerMethod);
}
throw ex;
}
}
/**
* Determine the exception handle method. Can return null if not found.
* Determine the exception handle method for the given exception.
* @param exception the exception thrown
* @return a handler for the given exception type
* @return a handler for the given exception type, or {@code null} if none found
*/
@Nullable
private Method getExceptionHandler(Throwable exception) {
@@ -121,24 +142,10 @@ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
return handler;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
Method handlerMethod = getExceptionHandler(ex);
if (handlerMethod != null) {
invokeHandlerMethod(mi, ex, handlerMethod);
}
throw ex;
}
}
private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
Object[] handlerArgs;
if (method.getParameterCount() == 1) {
handlerArgs = new Object[] { ex };
handlerArgs = new Object[] {ex};
}
else {
handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,7 +70,9 @@ public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyC
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -419,7 +419,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
// Found a matching TargetSource.
if (logger.isDebugEnabled()) {
logger.debug("TargetSourceCreator [" + tsc +
" found custom TargetSource for bean with name '" + beanName + "'");
"] found custom TargetSource for bean with name '" + beanName + "'");
}
return ts;
}
@@ -544,24 +544,24 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
* @see #setInterceptorNames
*/
private Advisor[] resolveInterceptorNames() {
Assert.state(this.beanFactory != null, "BeanFactory required for resolving interceptor names");
ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory ?
(ConfigurableBeanFactory) this.beanFactory : null);
BeanFactory bf = this.beanFactory;
ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
List<Advisor> advisors = new ArrayList<>();
for (String beanName : this.interceptorNames) {
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Object next = this.beanFactory.getBean(beanName);
Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
Object next = bf.getBean(beanName);
advisors.add(this.advisorAdapterRegistry.wrap(next));
}
}
return advisors.toArray(new Advisor[advisors.size()]);
return advisors.toArray(new Advisor[0]);
}
/**
* Subclasses may choose to implement this: for example,
* to change the interfaces exposed.
* <p>The default implementation is empty.
* @param proxyFactory ProxyFactory that is already configured with
* @param proxyFactory a ProxyFactory that is already configured with
* TargetSource and interfaces and will be used to create the proxy
* immediately after this method returns
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package org.springframework.aop.framework.autoproxy;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
@@ -45,7 +45,7 @@ public class BeanFactoryAdvisorRetrievalHelper {
private final ConfigurableListableBeanFactory beanFactory;
@Nullable
private String[] cachedAdvisorBeanNames;
private volatile String[] cachedAdvisorBeanNames;
/**
@@ -66,22 +66,19 @@ public class BeanFactoryAdvisorRetrievalHelper {
*/
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new LinkedList<>();
return new ArrayList<>();
}
List<Advisor> advisors = new LinkedList<>();
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
public class DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator implements BeanNameAware {
/** Separator between prefix and remainder of bean name */
public final static String SEPARATOR = ".";
public static final String SEPARATOR = ".";
private boolean usePrefix = false;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
package org.springframework.aop.framework.autoproxy.target;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -31,7 +30,6 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
@@ -150,11 +148,8 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
// Filter out BeanPostProcessors that are part of the AOP infrastructure,
// since those are only meant to apply to beans defined in the original factory.
for (Iterator<BeanPostProcessor> it = internalBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) {
if (it.next() instanceof AopInfrastructureBean) {
it.remove();
}
}
internalBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor ->
beanPostProcessor instanceof AopInfrastructureBean);
return internalBeanFactory;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,13 +29,13 @@ import org.apache.commons.logging.LogFactory;
*/
public class SimpleAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
private final Log logger = LogFactory.getLog(SimpleAsyncUncaughtExceptionHandler.class);
private static final Log logger = LogFactory.getLog(SimpleAsyncUncaughtExceptionHandler.class);
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
if (logger.isErrorEnabled()) {
logger.error(String.format("Unexpected error occurred invoking async " +
"method '%s'.", method), ex);
logger.error("Unexpected error occurred invoking async method: " + method, ex);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,7 +52,8 @@ import org.springframework.util.ClassUtils;
* @see #setProxyTargetClass
*/
@SuppressWarnings("serial")
public class ScopedProxyFactoryBean extends ProxyConfig implements FactoryBean<Object>, BeanFactoryAware {
public class ScopedProxyFactoryBean extends ProxyConfig
implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {
/** The TargetSource that manages scoping */
private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -131,8 +131,9 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
*/
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
return ((targetClass != null && matchesPattern(ClassUtils.getQualifiedMethodName(method, targetClass))) ||
matchesPattern(ClassUtils.getQualifiedMethodName(method)));
return ((targetClass != null && targetClass != method.getDeclaringClass() &&
matchesPattern(ClassUtils.getQualifiedMethodName(method, targetClass))) ||
matchesPattern(ClassUtils.getQualifiedMethodName(method, method.getDeclaringClass())));
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -192,7 +192,8 @@ public abstract class AopUtils {
* @see org.springframework.util.ClassUtils#getMostSpecificMethod
*/
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
Class<?> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass);
// If we are dealing with method with generic parameters, find the original method.
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
}
@@ -236,13 +237,17 @@ public abstract class AopUtils {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
@@ -300,7 +305,7 @@ public abstract class AopUtils {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<>();
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -131,7 +131,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
return false;
}
ControlFlowPointcut that = (ControlFlowPointcut) other;
return (this.clazz.equals(that.clazz)) && ObjectUtils.nullSafeEquals(that.methodName, this.methodName);
return (this.clazz.equals(that.clazz)) && ObjectUtils.nullSafeEquals(this.methodName, that.methodName);
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
private final Set<Class<?>> interfaces = new LinkedHashSet<>();
private int order = Integer.MAX_VALUE;
private int order = Ordered.LOWEST_PRECEDENCE;
/**
@@ -105,7 +105,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
@Override
public Class<?>[] getInterfaces() {
return this.interfaces.toArray(new Class<?>[this.interfaces.size()]);
return ClassUtils.toClassArray(this.interfaces);
}
@Override
@@ -119,7 +119,6 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
}
}
public void setOrder(int order) {
this.order = order;
}
@@ -129,7 +128,6 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
return this.order;
}
@Override
public Advice getAdvice() {
return this.advice;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@ import org.springframework.lang.Nullable;
/**
* Convenient abstract superclass for dynamic method matchers,
* which do care about arguments at runtime.
*
* @author Rod Johnson
*/
public abstract class DynamicMethodMatcher implements MethodMatcher {
@@ -24,7 +24,7 @@ import org.springframework.aop.Pointcut;
* Convenient superclass when we want to force subclasses to
* implement MethodMatcher interface, but subclasses
* will want to be pointcuts. The getClassFilter() method can
* be overriden to customize ClassFilter behaviour as well.
* be overridden to customize ClassFilter behaviour as well.
*
* @author Rod Johnson
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,15 +53,15 @@ public class IntroductionInfoSupport implements IntroductionInfo, Serializable {
* due to the delegate implementing it. Call this method to exclude
* internal interfaces from being visible at the proxy level.
* <p>Does nothing if the interface is not implemented by the delegate.
* @param intf the interface to suppress
* @param ifc the interface to suppress
*/
public void suppressInterface(Class<?> intf) {
this.publishedInterfaces.remove(intf);
public void suppressInterface(Class<?> ifc) {
this.publishedInterfaces.remove(ifc);
}
@Override
public Class<?>[] getInterfaces() {
return this.publishedInterfaces.toArray(new Class<?>[this.publishedInterfaces.size()]);
return ClassUtils.toClassArray(this.publishedInterfaces);
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -90,8 +90,8 @@ public abstract class MethodMatchers {
*/
public static boolean matches(MethodMatcher mm, Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(mm, "MethodMatcher must not be null");
return ((mm instanceof IntroductionAwareMethodMatcher &&
((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions)) ||
return (mm instanceof IntroductionAwareMethodMatcher ?
((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions) :
mm.matches(method, targetClass));
}
@@ -144,23 +144,20 @@ public abstract class MethodMatchers {
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(obj instanceof UnionMethodMatcher)) {
if (!(other instanceof UnionMethodMatcher)) {
return false;
}
UnionMethodMatcher that = (UnionMethodMatcher) obj;
UnionMethodMatcher that = (UnionMethodMatcher) other;
return (this.mm1.equals(that.mm1) && this.mm2.equals(that.mm2));
}
@Override
public int hashCode() {
int hashCode = 17;
hashCode = 37 * hashCode + this.mm1.hashCode();
hashCode = 37 * hashCode + this.mm2.hashCode();
return hashCode;
return 37 * this.mm1.hashCode() + this.mm2.hashCode();
}
}
@@ -209,6 +206,12 @@ public abstract class MethodMatchers {
}
return (this.cf1.equals(otherCf1) && this.cf2.equals(otherCf2));
}
@Override
public int hashCode() {
// Allow for matching with regular UnionMethodMatcher by providing same hash...
return super.hashCode();
}
}
@@ -231,18 +234,18 @@ public abstract class MethodMatchers {
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
return MethodMatchers.matches(this.mm1, method, targetClass, hasIntroductions) &&
MethodMatchers.matches(this.mm2, method, targetClass, hasIntroductions);
return (MethodMatchers.matches(this.mm1, method, targetClass, hasIntroductions) &&
MethodMatchers.matches(this.mm2, method, targetClass, hasIntroductions));
}
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
return this.mm1.matches(method, targetClass) && this.mm2.matches(method, targetClass);
return (this.mm1.matches(method, targetClass) && this.mm2.matches(method, targetClass));
}
@Override
public boolean isRuntime() {
return this.mm1.isRuntime() || this.mm2.isRuntime();
return (this.mm1.isRuntime() || this.mm2.isRuntime());
}
@Override
@@ -250,10 +253,10 @@ public abstract class MethodMatchers {
// Because a dynamic intersection may be composed of a static and dynamic part,
// we must avoid calling the 3-arg matches method on a dynamic matcher, as
// it will probably be an unsupported operation.
boolean aMatches = this.mm1.isRuntime() ?
this.mm1.matches(method, targetClass, args) : this.mm1.matches(method, targetClass);
boolean bMatches = this.mm2.isRuntime() ?
this.mm2.matches(method, targetClass, args) : this.mm2.matches(method, targetClass);
boolean aMatches = (this.mm1.isRuntime() ?
this.mm1.matches(method, targetClass, args) : this.mm1.matches(method, targetClass));
boolean bMatches = (this.mm2.isRuntime() ?
this.mm2.matches(method, targetClass, args) : this.mm2.matches(method, targetClass));
return aMatches && bMatches;
}
@@ -271,10 +274,7 @@ public abstract class MethodMatchers {
@Override
public int hashCode() {
int hashCode = 17;
hashCode = 37 * hashCode + this.mm1.hashCode();
hashCode = 37 * hashCode + this.mm2.hashCode();
return hashCode;
return 37 * this.mm1.hashCode() + this.mm2.hashCode();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,8 +18,8 @@ package org.springframework.aop.support;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.springframework.lang.Nullable;
@@ -38,7 +38,7 @@ import org.springframework.util.PatternMatchUtils;
@SuppressWarnings("serial")
public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut implements Serializable {
private List<String> mappedNames = new LinkedList<>();
private List<String> mappedNames = new ArrayList<>();
/**
@@ -55,11 +55,8 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
* Matching will be the union of all these; if any match,
* the pointcut matches.
*/
public void setMappedNames(@Nullable String... mappedNames) {
this.mappedNames = new LinkedList<>();
if (mappedNames != null) {
this.mappedNames.addAll(Arrays.asList(mappedNames));
}
public void setMappedNames(String... mappedNames) {
this.mappedNames = new ArrayList<>(Arrays.asList(mappedNames));
}
/**
@@ -95,7 +95,7 @@ public abstract class Pointcuts {
@SuppressWarnings("serial")
private static class SetterPointcut extends StaticMethodMatcherPointcut implements Serializable {
public static SetterPointcut INSTANCE = new SetterPointcut();
public static final SetterPointcut INSTANCE = new SetterPointcut();
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
@@ -116,7 +116,7 @@ public abstract class Pointcuts {
@SuppressWarnings("serial")
private static class GetterPointcut extends StaticMethodMatcherPointcut implements Serializable {
public static GetterPointcut INSTANCE = new GetterPointcut();
public static final GetterPointcut INSTANCE = new GetterPointcut();
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,8 @@ import java.io.Serializable;
import org.springframework.aop.ClassFilter;
/**
* Simple ClassFilter implementation that passes classes (and optionally subclasses)
* Simple ClassFilter implementation that passes classes (and optionally subclasses).
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
@@ -37,7 +38,7 @@ public class RootClassFilter implements ClassFilter, Serializable {
@Override
public boolean matches(Class<?> candidate) {
return clazz.isAssignableFrom(candidate);
return this.clazz.isAssignableFrom(candidate);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@ import org.springframework.lang.Nullable;
/**
* Convenient abstract superclass for static method matchers, which don't care
* about arguments at runtime.
*
* @author Rod Johnson
*/
public abstract class StaticMethodMatcher implements MethodMatcher {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,10 +36,10 @@ import org.springframework.util.Assert;
public abstract class StaticMethodMatcherPointcutAdvisor extends StaticMethodMatcherPointcut
implements PointcutAdvisor, Ordered, Serializable {
private int order = Integer.MAX_VALUE;
private Advice advice = EMPTY_ADVICE;
private int order = Ordered.LOWEST_PRECEDENCE;
/**
* Create a new StaticMethodMatcherPointcutAdvisor,
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.aop.support.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.StaticMethodMatcher;
@@ -71,6 +72,10 @@ public class AnnotationMethodMatcher extends StaticMethodMatcher {
if (matchesMethod(method)) {
return true;
}
// Proxy classes never have annotations on their redeclared methods.
if (targetClass != null && Proxy.isProxyClass(targetClass)) {
return false;
}
// The method may be on an interface, so let's check on the target class as well.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
return (specificMethod != method && matchesMethod(specificMethod));
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
private String targetBeanName;
/** Class of the target */
private Class<?> targetClass;
private volatile Class<?> targetClass;
/**
* BeanFactory that owns this TargetSource. We need to hold onto this
@@ -120,19 +120,28 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
@Override
public synchronized Class<?> getTargetClass() {
if (this.targetClass == null && this.beanFactory != null) {
// Determine type of the target bean.
this.targetClass = this.beanFactory.getType(this.targetBeanName);
if (this.targetClass == null) {
if (logger.isTraceEnabled()) {
logger.trace("Getting bean with name '" + this.targetBeanName + "' in order to determine type");
}
Object beanInstance = this.beanFactory.getBean(this.targetBeanName);
this.targetClass = beanInstance.getClass();
}
public Class<?> getTargetClass() {
Class<?> targetClass = this.targetClass;
if (targetClass != null) {
return targetClass;
}
synchronized (this) {
// Full check within synchronization, entering the BeanFactory interaction algorithm only once...
targetClass = this.targetClass;
if (targetClass == null && this.beanFactory != null) {
// Determine type of the target bean.
targetClass = this.beanFactory.getType(this.targetBeanName);
if (targetClass == null) {
if (logger.isTraceEnabled()) {
logger.trace("Getting bean with name '" + this.targetBeanName + "' for type determination");
}
Object beanInstance = this.beanFactory.getBean(this.targetBeanName);
targetClass = beanInstance.getClass();
}
this.targetClass = targetClass;
}
return targetClass;
}
return this.targetClass;
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,8 +74,8 @@ public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFac
* @param target the bean instance to destroy
*/
protected void destroyPrototypeInstance(Object target) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Destroying instance of bean '" + getTargetBeanName() + "'");
if (logger.isDebugEnabled()) {
logger.debug("Destroying instance of bean '" + getTargetBeanName() + "'");
}
if (getBeanFactory() instanceof ConfigurableBeanFactory) {
((ConfigurableBeanFactory) getBeanFactory()).destroyBean(getTargetBeanName(), target);
@@ -85,7 +85,7 @@ public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFac
((DisposableBean) target).destroy();
}
catch (Throwable ex) {
logger.error("Couldn't invoke destroy method of bean with name '" + getTargetBeanName() + "'", ex);
logger.error("Destroy method on bean with name '" + getTargetBeanName() + "' threw an exception", ex);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,6 @@
package org.springframework.aop.aspectj;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.Test;
@@ -30,13 +27,7 @@ import org.junit.Test;
* @author Adrian Colyer
* @author Chris Beams
*/
public class AspectJAdviceParameterNameDiscoverAnnotationTests
extends AspectJAdviceParameterNameDiscovererTests {
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {}
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
public class AspectJAdviceParameterNameDiscoverAnnotationTests extends AspectJAdviceParameterNameDiscovererTests {
@Test
public void testAnnotationBinding() {
@@ -45,4 +36,9 @@ public class AspectJAdviceParameterNameDiscoverAnnotationTests
new String[] {"thisJoinPoint","ann"});
}
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
@interface MyAnnotation {}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop.aspectj;
import java.lang.reflect.Method;
@@ -34,47 +35,6 @@ import static org.junit.Assert.*;
*/
public class AspectJAdviceParameterNameDiscovererTests {
// methods to discover parameter names for
public void noArgs() {
}
public void tjp(JoinPoint jp) {
}
public void tjpsp(JoinPoint.StaticPart tjpsp) {
}
public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
}
public void oneThrowable(Exception ex) {
}
public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
}
public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
}
public void oneObject(Object x) {
}
public void twoObjects(Object x, Object y) {
}
public void onePrimitive(int x) {
}
public void oneObjectOnePrimitive(Object x, int y) {
}
public void oneThrowableOnePrimitive(Throwable x, int y) {
}
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
}
@Test
public void testNoArgs() {
assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
@@ -221,22 +181,26 @@ public class AspectJAdviceParameterNameDiscovererTests {
@Test
public void testThisAndPrimitive() {
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)", new String[] {"obj", "count"});
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)",
new String[] {"obj", "count"});
}
@Test
public void testTargetAndPrimitive() {
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)", new String[] {"obj", "count"});
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)",
new String[] {"obj", "count"});
}
@Test
public void testThrowingAndPrimitive() {
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex", new String[] {"ex", "count"});
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex",
new String[] {"ex", "count"});
}
@Test
public void testAllTogetherNow() {
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex", new String[] {"thisJoinPoint", "ex", "x", "foo"});
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex",
new String[] {"thisJoinPoint", "ex", "x", "foo"});
}
@Test
@@ -253,8 +217,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
protected Method getMethod(String name) {
// assumes no overloading of test methods...
Method[] candidates = this.getClass().getMethods();
// Assumes no overloading of test methods...
Method[] candidates = getClass().getMethods();
for (Method candidate : candidates) {
if (candidate.getName().equals(name)) {
return candidate;
@@ -268,8 +232,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
assertParameterNames(method, pointcut, null, null, parameterNames);
}
protected void assertParameterNames(Method method, String pointcut, String returning, String throwing,
String[] parameterNames) {
protected void assertParameterNames(
Method method, String pointcut, String returning, String throwing, String[] parameterNames) {
assertEquals("bad test specification, must have same number of parameter names as method arguments",
method.getParameterCount(), parameterNames.length);
@@ -300,8 +264,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
assertException(method, pointcut, null, null, exceptionType, message);
}
protected void assertException(Method method, String pointcut, String returning, String throwing,
Class<?> exceptionType, String message) {
protected void assertException(
Method method, String pointcut, String returning, String throwing, Class<?> exceptionType, String message) {
AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
discoverer.setRaiseExceptions(true);
@@ -333,4 +297,46 @@ public class AspectJAdviceParameterNameDiscovererTests {
return sb.toString();
}
// Methods to discover parameter names for
public void noArgs() {
}
public void tjp(JoinPoint jp) {
}
public void tjpsp(JoinPoint.StaticPart tjpsp) {
}
public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
}
public void oneThrowable(Exception ex) {
}
public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
}
public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
}
public void oneObject(Object x) {
}
public void twoObjects(Object x, Object y) {
}
public void onePrimitive(int x) {
}
public void oneObjectOnePrimitive(Object x, int y) {
}
public void oneThrowableOnePrimitive(Throwable x, int y) {
}
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -218,38 +218,27 @@ public class AspectJExpressionPointcutTests {
@Test
public void testSimpleAdvice() {
String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
CallCountingInterceptor interceptor = new CallCountingInterceptor();
TestBean testBean = getAdvisedProxy(expression, interceptor);
assertEquals("Calls should be 0", 0, interceptor.getCount());
testBean.getAge();
assertEquals("Calls should be 1", 1, interceptor.getCount());
testBean.setAge(90);
assertEquals("Calls should still be 1", 1, interceptor.getCount());
}
@Test
public void testDynamicMatchingProxy() {
String expression = "execution(void org.springframework.tests.sample.beans.TestBean.setSomeNumber(Number)) && args(Double)";
CallCountingInterceptor interceptor = new CallCountingInterceptor();
TestBean testBean = getAdvisedProxy(expression, interceptor);
assertEquals("Calls should be 0", 0, interceptor.getCount());
testBean.setSomeNumber(new Double(30));
assertEquals("Calls should be 1", 1, interceptor.getCount());
testBean.setSomeNumber(new Integer(90));
assertEquals("Calls should be 1", 1, interceptor.getCount());
}
@@ -291,7 +280,7 @@ public class AspectJExpressionPointcutTests {
}
@Test
public void testWithUnsupportedPointcutPrimitive() throws Exception {
public void testWithUnsupportedPointcutPrimitive() {
String expression = "call(int org.springframework.tests.sample.beans.TestBean.getAge())";
try {
@@ -301,7 +290,6 @@ public class AspectJExpressionPointcutTests {
catch (UnsupportedPointcutPrimitiveException ex) {
assertEquals("Should not support call pointcut", PointcutPrimitive.CALL, ex.getUnsupportedPrimitive());
}
}
@Test
@@ -332,6 +320,7 @@ public class AspectJExpressionPointcutTests {
// Empty
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,6 +77,7 @@ public class BeanNamePointcutMatchingTests {
assertMisMatch("someName", "!bean(someName) || bean(someOtherName)");
}
private void assertMatch(String beanName, String pcExpression) {
assertTrue("Unexpected mismatch for bean \"" + beanName + "\" for pcExpression \"" + pcExpression + "\"",
matches(beanName, pcExpression));
@@ -98,4 +99,5 @@ public class BeanNamePointcutMatchingTests {
pointcut.setExpression(pcExpression);
return pointcut.matches(TestBean.class);
}
}
@@ -218,7 +218,7 @@ public class MethodInvocationProceedingJoinPointTests {
itb.unreliableFileOperation();
}
catch (IOException ex) {
// we don't realy care...
// we don't really care...
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,30 +26,30 @@ import org.junit.Test;
import test.annotation.EmptySpringAnnotation;
import test.annotation.transaction.Tx;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.Assert.*;
/**
* Java5-specific {@link AspectJExpressionPointcutTests}.
* Java 5 specific {@link AspectJExpressionPointcutTests}.
*
* @author Rod Johnson
* @author Chris Beams
*/
public class TigerAspectJExpressionPointcutTests {
// TODO factor into static in AspectJExpressionPointcut
private Method getAge;
private Map<String,Method> methodsOnHasGeneric = new HashMap<>();
private final Map<String, Method> methodsOnHasGeneric = new HashMap<>();
@Before
public void setUp() throws NoSuchMethodException {
public void setup() throws NoSuchMethodException {
getAge = TestBean.class.getMethod("getAge");
// Assumes no overloading
for (Method m : HasGeneric.class.getMethods()) {
methodsOnHasGeneric.put(m.getName(), m);
for (Method method : HasGeneric.class.getMethods()) {
methodsOnHasGeneric.put(method.getName(), method);
}
}
@@ -74,7 +74,7 @@ public class TigerAspectJExpressionPointcutTests {
}
@Test
public void testMatchVarargs() throws SecurityException, NoSuchMethodException {
public void testMatchVarargs() throws Exception {
@SuppressWarnings("unused")
class MyTemplate {
@@ -87,11 +87,6 @@ public class TigerAspectJExpressionPointcutTests {
AspectJExpressionPointcut jdbcVarArgs = new AspectJExpressionPointcut();
jdbcVarArgs.setExpression(expression);
// TODO: the expression above no longer matches Object[]
// assertFalse(jdbcVarArgs.matches(
// JdbcTemplate.class.getMethod("queryForInt", String.class, Object[].class),
// JdbcTemplate.class));
assertTrue(jdbcVarArgs.matches(
MyTemplate.class.getMethod("queryForInt", String.class, Object[].class),
MyTemplate.class));
@@ -105,19 +100,19 @@ public class TigerAspectJExpressionPointcutTests {
}
@Test
public void testMatchAnnotationOnClassWithAtWithin() throws SecurityException, NoSuchMethodException {
public void testMatchAnnotationOnClassWithAtWithin() throws Exception {
String expression = "@within(test.annotation.transaction.Tx)";
testMatchAnnotationOnClass(expression);
}
@Test
public void testMatchAnnotationOnClassWithoutBinding() throws SecurityException, NoSuchMethodException {
public void testMatchAnnotationOnClassWithoutBinding() throws Exception {
String expression = "within(@test.annotation.transaction.Tx *)";
testMatchAnnotationOnClass(expression);
}
@Test
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws SecurityException, NoSuchMethodException {
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws Exception {
String expression = "within(@(test.annotation..*) *)";
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class));
@@ -129,12 +124,12 @@ public class TigerAspectJExpressionPointcutTests {
}
@Test
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws SecurityException, NoSuchMethodException {
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws Exception {
String expression = "within(@(test.annotation.transaction.*) *)";
testMatchAnnotationOnClass(expression);
}
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws SecurityException, NoSuchMethodException {
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws Exception {
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(expression);
@@ -147,7 +142,7 @@ public class TigerAspectJExpressionPointcutTests {
}
@Test
public void testAnnotationOnMethodWithFQN() throws SecurityException, NoSuchMethodException {
public void testAnnotationOnMethodWithFQN() throws Exception {
String expression = "@annotation(test.annotation.transaction.Tx)";
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(expression);
@@ -161,28 +156,56 @@ public class TigerAspectJExpressionPointcutTests {
}
@Test
public void testAnnotationOnMethodWithWildcard() throws SecurityException, NoSuchMethodException {
public void testAnnotationOnCglibProxyMethod() throws Exception {
String expression = "@annotation(test.annotation.transaction.Tx)";
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(expression);
ProxyFactory factory = new ProxyFactory(new BeanA());
factory.setProxyTargetClass(true);
BeanA proxy = (BeanA) factory.getProxy();
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass()));
}
@Test
public void testAnnotationOnDynamicProxyMethod() throws Exception {
String expression = "@annotation(test.annotation.transaction.Tx)";
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(expression);
ProxyFactory factory = new ProxyFactory(new BeanA());
factory.setProxyTargetClass(false);
IBeanA proxy = (IBeanA) factory.getProxy();
assertTrue(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass()));
}
@Test
public void testAnnotationOnMethodWithWildcard() throws Exception {
String expression = "execution(@(test.annotation..*) * *(..))";
AspectJExpressionPointcut anySpringMethodAnnotation = new AspectJExpressionPointcut();
anySpringMethodAnnotation.setExpression(expression);
assertFalse(anySpringMethodAnnotation.matches(getAge, TestBean.class));
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(anySpringMethodAnnotation.matches(
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(anySpringMethodAnnotation.matches(
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
}
@Test
public void testAnnotationOnMethodArgumentsWithFQN() throws SecurityException, NoSuchMethodException {
public void testAnnotationOnMethodArgumentsWithFQN() throws Exception {
String expression = "@args(*, test.annotation.EmptySpringAnnotation))";
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
takesSpringAnnotatedArgument2.setExpression(expression);
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
@@ -203,14 +226,16 @@ public class TigerAspectJExpressionPointcutTests {
}
@Test
public void testAnnotationOnMethodArgumentsWithWildcards() throws SecurityException, NoSuchMethodException {
public void testAnnotationOnMethodArgumentsWithWildcards() throws Exception {
String expression = "execution(* *(*, @(test..*) *))";
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
takesSpringAnnotatedArgument2.setExpression(expression);
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
@@ -260,12 +285,21 @@ public class TigerAspectJExpressionPointcutTests {
@EmptySpringAnnotation
public static class SpringAnnotated {
public void foo() {
}
}
static class BeanA {
interface IBeanA {
@Tx
int getAge();
}
static class BeanA implements IBeanA {
private String name;
private int age;
@@ -275,6 +309,7 @@ public class TigerAspectJExpressionPointcutTests {
}
@Tx
@Override
public int getAge() {
return age;
}
@@ -283,6 +318,7 @@ public class TigerAspectJExpressionPointcutTests {
@Tx
static class BeanB {
private String name;
public void setName(String name) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,6 @@ import test.aop.PerTargetAspect;
import test.aop.TwoAdviceAspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.aop.framework.ProxyFactory;
@@ -82,22 +81,24 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Test
public void testRejectsPerCflowAspect() {
try {
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(),"someBean"));
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(), "someBean"));
fail("Cannot accept cflow");
}
catch (AopConfigException ex) {
assertTrue(ex.getMessage().indexOf("PERCFLOW") != -1);
assertTrue(ex.getMessage().contains("PERCFLOW"));
}
}
@Test
public void testRejectsPerCflowBelowAspect() {
try {
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(),"someBean"));
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(), "someBean"));
fail("Cannot accept cflowbelow");
}
catch (AopConfigException ex) {
assertTrue(ex.getMessage().indexOf("PERCFLOWBELOW") != -1);
assertTrue(ex.getMessage().contains("PERCFLOWBELOW"));
}
}
@@ -112,7 +113,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
assertEquals("Around advice must NOT apply", realAge, itb.getAge());
Advised advised = (Advised) itb;
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[3];
LazySingletonAspectInstanceFactoryDecorator maaif =
@@ -199,7 +201,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
Advised advised = (Advised) itb;
// Will be ExposeInvocationInterceptor, synthetic instantiation advisor, 2 method advisors
assertEquals(4, advised.getAdvisors().length);
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[2];
LazySingletonAspectInstanceFactoryDecorator maaif =
@@ -227,16 +230,15 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
int realAge = 65;
target.setAge(realAge);
PerTypeWithinAspectInstanceFactory aif = new PerTypeWithinAspectInstanceFactory();
TestBean itb = (TestBean) createProxy(target,
getFixture().getAdvisors(aif),
TestBean.class);
TestBean itb = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
assertEquals("No method calls", 0, aif.getInstantiationCount());
assertEquals("Around advice must now apply", 0, itb.getAge());
Advised advised = (Advised) itb;
// Will be ExposeInvocationInterceptor, synthetic instantiation advisor, 2 method advisors
assertEquals(4, advised.getAdvisors().length);
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[2];
LazySingletonAspectInstanceFactoryDecorator maaif =
@@ -257,9 +259,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
assertEquals("Around advice must still apply", 1, itb.getAge());
assertEquals("Around advice must still apply", 2, itb.getAge());
TestBean itb2 = (TestBean) createProxy(target,
getFixture().getAdvisors(aif),
TestBean.class);
TestBean itb2 = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
assertEquals(1, aif.getInstantiationCount());
assertEquals("Around advice be independent for second instance", 0, itb2.getAge());
assertEquals(2, aif.getInstantiationCount());
@@ -284,7 +284,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
public void testNamedPointcutFromAspectLibraryWithBinding() {
TestBean target = new TestBean();
ITestBean itb = (ITestBean) createProxy(target,
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new NamedPointcutAspectFromLibraryWithBinding(),"someBean")),
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(
new NamedPointcutAspectFromLibraryWithBinding(), "someBean")),
ITestBean.class);
itb.setAge(10);
assertEquals("Around advice must apply", 20, itb.getAge());
@@ -296,7 +297,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
int realAge = 65;
target.setAge(realAge);
ITestBean itb = (ITestBean) createProxy(target,
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance,"someBean")),
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, "someBean")),
ITestBean.class);
assertEquals("Around advice must apply", -1, itb.getAge());
assertEquals(realAge, target.getAge());
@@ -306,7 +307,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
public void testBindingWithSingleArg() {
TestBean target = new TestBean();
ITestBean itb = (ITestBean) createProxy(target,
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new BindingAspectWithSingleArg(),"someBean")),
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new BindingAspectWithSingleArg(), "someBean")),
ITestBean.class);
itb.setAge(10);
assertEquals("Around advice must apply", 20, itb.getAge());
@@ -317,7 +319,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
public void testBindingWithMultipleArgsDifferentlyOrdered() {
ManyValuedArgs target = new ManyValuedArgs();
ManyValuedArgs mva = (ManyValuedArgs) createProxy(target,
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ManyValuedArgs(),"someBean")),
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new ManyValuedArgs(), "someBean")),
ManyValuedArgs.class);
String a = "a";
@@ -338,7 +341,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
assertFalse(notLockableTarget instanceof Lockable);
NotLockable notLockable1 = (NotLockable) createProxy(notLockableTarget,
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")),
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
NotLockable.class);
assertTrue(notLockable1 instanceof Lockable);
Lockable lockable = (Lockable) notLockable1;
@@ -349,7 +352,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
NotLockable notLockable2Target = new NotLockable();
NotLockable notLockable2 = (NotLockable) createProxy(notLockable2Target,
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")),
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
NotLockable.class);
assertTrue(notLockable2 instanceof Lockable);
Lockable lockable2 = (Lockable) notLockable2;
@@ -368,11 +371,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Test
public void testIntroductionAdvisorExcludedFromTargetImplementingInterface() {
assertTrue(AopUtils.findAdvisorsThatCanApply(
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(
new MakeLockable(),"someBean")),
CannotBeUnlocked.class).isEmpty());
assertEquals(2, AopUtils.findAdvisorsThatCanApply(getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class).size());
getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
CannotBeUnlocked.class).isEmpty());
assertEquals(2, AopUtils.findAdvisorsThatCanApply(getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class).size());
}
@Test
@@ -408,42 +411,34 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
List.class
),
CannotBeUnlocked.class);
List.class);
assertFalse("Type pattern must have excluded mixin", proxy instanceof Lockable);
}
/* prereq AspectJ 1.6.7
@Test
public void testIntroductionBasedOnAnnotationMatch_Spr5307() {
public void testIntroductionBasedOnAnnotationMatch_SPR5307() {
AnnotatedTarget target = new AnnotatedTargetImpl();
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(),"someBean"));
Object proxy = createProxy(target,
advisors,
AnnotatedTarget.class);
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(), "someBean"));
Object proxy = createProxy(target, advisors, AnnotatedTarget.class);
System.out.println(advisors.get(1));
assertTrue(proxy instanceof Lockable);
Lockable lockable = (Lockable)proxy;
lockable.locked();
}
*/
// TODO: Why does this test fail? It hasn't been run before, so it maybe never actually passed...
@Test
@Ignore
public void testIntroductionWithArgumentBinding() {
TestBean target = new TestBean();
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new MakeITestBeanModifiable(),"someBean"));
new SingletonMetadataAwareAspectInstanceFactory(new MakeITestBeanModifiable(), "someBean"));
advisors.addAll(getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")));
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")));
Modifiable modifiable = (Modifiable) createProxy(target,
advisors,
ITestBean.class);
Modifiable modifiable = (Modifiable) createProxy(target, advisors, ITestBean.class);
assertThat(modifiable, instanceOf(Modifiable.class));
Lockable lockable = (Lockable) modifiable;
assertFalse(lockable.locked());
@@ -477,11 +472,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
public void testAspectMethodThrowsExceptionLegalOnSignature() {
TestBean target = new TestBean();
UnsupportedOperationException expectedException = new UnsupportedOperationException();
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException),"someBean"));
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
assertEquals("One advice method was found", 1, advisors.size());
ITestBean itb = (ITestBean) createProxy(target,
advisors,
ITestBean.class);
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
try {
itb.getAge();
fail();
@@ -497,11 +492,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
public void testAspectMethodThrowsExceptionIllegalOnSignature() {
TestBean target = new TestBean();
RemoteException expectedException = new RemoteException();
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException),"someBean"));
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
assertEquals("One advice method was found", 1, advisors.size());
ITestBean itb = (ITestBean) createProxy(target,
advisors,
ITestBean.class);
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
try {
itb.getAge();
fail();
@@ -522,10 +517,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
// Required everywhere we use AspectJ proxies
pf.addAdvice(ExposeInvocationInterceptor.INSTANCE);
for (Object a : advisors) {
pf.addAdvisor((Advisor) a);
}
pf.addAdvisors(advisors);
pf.setExposeProxy(true);
return pf.getProxy();
@@ -534,13 +526,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Test
public void testTwoAdvicesOnOneAspect() {
TestBean target = new TestBean();
TwoAdviceAspect twoAdviceAspect = new TwoAdviceAspect();
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(twoAdviceAspect,"someBean"));
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(twoAdviceAspect, "someBean"));
assertEquals("Two advice methods found", 2, advisors.size());
ITestBean itb = (ITestBean) createProxy(target,
advisors,
ITestBean.class);
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
itb.setName("");
assertEquals(0, itb.getAge());
int newAge = 32;
@@ -551,16 +541,15 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Test
public void testAfterAdviceTypes() throws Exception {
Echo target = new Echo();
ExceptionHandling afterReturningAspect = new ExceptionHandling();
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(afterReturningAspect,"someBean"));
Echo echo = (Echo) createProxy(target,
advisors,
Echo.class);
List<Advisor> advisors = getFixture().getAdvisors(
new SingletonMetadataAwareAspectInstanceFactory(afterReturningAspect, "someBean"));
Echo echo = (Echo) createProxy(target, advisors, Echo.class);
assertEquals(0, afterReturningAspect.successCount);
assertEquals("", echo.echo(""));
assertEquals(1, afterReturningAspect.successCount);
assertEquals(0, afterReturningAspect.failureCount);
try {
echo.echo(new FileNotFoundException());
fail();
@@ -580,9 +569,9 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
public void testFailureWithoutExplicitDeclarePrecedence() {
TestBean target = new TestBean();
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
new NoDeclarePrecedenceShouldFail(), "someBean");
new NoDeclarePrecedenceShouldFail(), "someBean");
ITestBean itb = (ITestBean) createProxy(target,
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
itb.getAge();
}
@@ -590,21 +579,10 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
public void testDeclarePrecedenceNotSupported() {
TestBean target = new TestBean();
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
new DeclarePrecedenceShouldSucceed(), "someBean");
createProxy(target, getFixture().getAdvisors(aspectInstanceFactory),
ITestBean.class);
new DeclarePrecedenceShouldSucceed(), "someBean");
createProxy(target, getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
}
/** Not supported in 2.0!
public void testExplicitDeclarePrecedencePreventsFailure() {
TestBean target = new TestBean();
ITestBean itb = (ITestBean) createProxy(target,
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new DeclarePrecedenceShouldSucceed(), "someBean")),
ITestBean.class);
assertEquals(666, itb.getAge());
}
*/
@Aspect("percflow(execution(* *(..)))")
public static class PerCflowAspect {
@@ -723,6 +701,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Aspect
public static class NamedPointcutAspectWithoutFQN {
@Pointcut("execution(* getAge())")
public void getAge() {
}
@@ -779,7 +758,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Around(value="setAge(age)",argNames="age")
// @ArgNames({"age"}) // AMC needs more work here? ignoring pjp arg... ok??
// argNames should be suported in Around as it is in Pointcut
// argNames should be suported in Around as it is in Pointcut
public void changeReturnType(ProceedingJoinPoint pjp, int age) throws Throwable {
pjp.proceed(new Object[] {age*2});
}
@@ -788,12 +767,12 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Aspect
public static class ManyValuedArgs {
public String mungeArgs(String a, int b, int c, String d, StringBuffer e) {
return a + b + c + d + e;
}
@Around(value="execution(String mungeArgs(..)) && args(a, b, c, d, e)",
argNames="b,c,d,e,a")
@Around(value="execution(String mungeArgs(..)) && args(a, b, c, d, e)", argNames="b,c,d,e,a")
public String reverseAdvice(ProceedingJoinPoint pjp, int b, int c, String d, StringBuffer e, String a) throws Throwable {
assertEquals(a + b+ c+ d+ e, pjp.proceed());
return a + b + c + d + e;
@@ -803,6 +782,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Aspect
public static class ExceptionAspect {
private final Exception ex;
public ExceptionAspect(Exception ex) {
@@ -829,8 +809,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
@Aspect
public static class ExceptionHandling {
public int successCount;
public int failureCount;
public int afterCount;
@AfterReturning("execution(* echo(*))")
@@ -902,10 +885,12 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
abstract class AbstractMakeModifiable {
public interface MutableModifable extends Modifiable {
void markDirty();
}
public static class ModifiableImpl implements MutableModifable {
private boolean modified;
@Override
@@ -924,10 +909,9 @@ abstract class AbstractMakeModifiable {
}
}
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)",
argNames="modifiable,newValue")
public void recordModificationIfSetterArgumentDiffersFromOldValue(JoinPoint jp,
MutableModifable mixin, Object newValue) {
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)", argNames="modifiable,newValue")
public void recordModificationIfSetterArgumentDiffersFromOldValue(
JoinPoint jp, MutableModifable mixin, Object newValue) {
/*
* We use the mixin to check and, if necessary, change,
@@ -992,6 +976,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
}
/**
* Adds a declare parents pointcut - spr5307
* @author Andy Clement
@@ -1001,8 +986,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
@DeclareParents(value = "(@org.springframework.aop.aspectj.annotation.Measured *)",
// @DeclareParents(value = "(@Measured *)", // this would be a nice alternative...
defaultImpl=DefaultLockable.class)
defaultImpl = DefaultLockable.class)
public static Lockable mixin;
}
@@ -1014,14 +998,11 @@ class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
@Aspect
class MakeLockable {
@DeclareParents(value = "org.springframework..*",
defaultImpl=DefaultLockable.class)
@DeclareParents(value = "org.springframework..*", defaultImpl = DefaultLockable.class)
public static Lockable mixin;
@Before(value="execution(void set*(*)) && this(mixin)", argNames="mixin")
public void checkNotLocked(
Lockable mixin) // Bind to arg
{
public void checkNotLocked( Lockable mixin) {
// Can also obtain the mixin (this) this way
//Lockable mixin = (Lockable) jp.getThis();
if (mixin.locked()) {
@@ -1069,6 +1050,7 @@ interface Modifiable {
}
/**
* Used as a target.
* @author Andy Clement
@@ -1076,11 +1058,12 @@ interface Modifiable {
interface AnnotatedTarget {
}
@Measured
class AnnotatedTargetImpl implements AnnotatedTarget {
}
@Retention(RetentionPolicy.RUNTIME)
@interface Measured {}
@@ -1104,9 +1087,7 @@ class PerThisAspect {
public int count;
/**
* Just to check that this doesn't cause problems with introduction processing
*/
// Just to check that this doesn't cause problems with introduction processing
private ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
@Around("execution(int *.getAge())")
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,20 +51,20 @@ public class AopNamespaceHandlerEventTests {
private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
private XmlBeanDefinitionReader reader;
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
private XmlBeanDefinitionReader reader;
@Before
public void setUp() throws Exception {
public void setup() {
this.reader = new XmlBeanDefinitionReader(this.beanFactory);
this.reader.setEventListener(this.eventListener);
}
@Test
public void testPointcutEvents() throws Exception {
public void testPointcutEvents() {
this.reader.loadBeanDefinitions(POINTCUT_EVENTS_CONTEXT);
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
assertEquals("Incorrect number of events fired", 1, componentDefinitions.length);
@@ -76,8 +76,7 @@ public class AopNamespaceHandlerEventTests {
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
PointcutComponentDefinition pcd = null;
for (int i = 0; i < nestedComponentDefs.length; i++) {
ComponentDefinition componentDefinition = nestedComponentDefs[i];
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
if (componentDefinition instanceof PointcutComponentDefinition) {
pcd = (PointcutComponentDefinition) componentDefinition;
break;
@@ -88,7 +87,7 @@ public class AopNamespaceHandlerEventTests {
}
@Test
public void testAdvisorEventsWithPointcutRef() throws Exception {
public void testAdvisorEventsWithPointcutRef() {
this.reader.loadBeanDefinitions(POINTCUT_REF_CONTEXT);
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
@@ -117,7 +116,7 @@ public class AopNamespaceHandlerEventTests {
}
@Test
public void testAdvisorEventsWithDirectPointcut() throws Exception {
public void testAdvisorEventsWithDirectPointcut() {
this.reader.loadBeanDefinitions(DIRECT_POINTCUT_EVENTS_CONTEXT);
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
@@ -146,7 +145,7 @@ public class AopNamespaceHandlerEventTests {
}
@Test
public void testAspectEvent() throws Exception {
public void testAspectEvent() {
this.reader.loadBeanDefinitions(CONTEXT);
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
assertEquals("Incorrect number of events fired", 5, componentDefinitions.length);
@@ -158,8 +157,7 @@ public class AopNamespaceHandlerEventTests {
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
AspectComponentDefinition acd = null;
for (int i = 0; i < nestedComponentDefs.length; i++) {
ComponentDefinition componentDefinition = nestedComponentDefs[i];
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
if (componentDefinition instanceof AspectComponentDefinition) {
acd = (AspectComponentDefinition) componentDefinition;
break;
@@ -175,8 +173,7 @@ public class AopNamespaceHandlerEventTests {
Set<String> expectedReferences = new HashSet<>();
expectedReferences.add("pc");
expectedReferences.add("countingAdvice");
for (int i = 0; i < beanReferences.length; i++) {
BeanReference beanReference = beanReferences[i];
for (BeanReference beanReference : beanReferences) {
expectedReferences.remove(beanReference.getBeanName());
}
assertEquals("Incorrect references found", 0, expectedReferences.size());
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ public class ConcurrencyThrottleInterceptorTests {
public void testSerializable() throws Exception {
DerivedTestBean tb = new DerivedTestBean();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
proxyFactory.setInterfaces(ITestBean.class);
ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
proxyFactory.addAdvice(cti);
proxyFactory.setTarget(tb);
@@ -75,7 +75,7 @@ public class ConcurrencyThrottleInterceptorTests {
private void testMultipleThreads(int concurrencyLimit) {
TestBean tb = new TestBean();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
proxyFactory.setInterfaces(ITestBean.class);
ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
cti.setConcurrencyLimit(concurrencyLimit);
proxyFactory.addAdvice(cti);
@@ -95,7 +95,7 @@ public class ConcurrencyThrottleInterceptorTests {
ex.printStackTrace();
}
threads[i] = new ConcurrencyThread(proxy,
i % 2 == 0 ? (Throwable) new OutOfMemoryError() : (Throwable) new IllegalStateException());
i % 2 == 0 ? new OutOfMemoryError() : new IllegalStateException());
threads[i].start();
}
for (int i = 0; i < NR_OF_THREADS; i++) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -83,7 +83,7 @@ public class CustomizableTraceInterceptorTests {
public void testSunnyDayPathLogsCorrectly() throws Throwable {
MethodInvocation methodInvocation = mock(MethodInvocation.class);
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString"));
given(methodInvocation.getThis()).willReturn(this);
Log log = mock(Log.class);
@@ -101,7 +101,7 @@ public class CustomizableTraceInterceptorTests {
MethodInvocation methodInvocation = mock(MethodInvocation.class);
IllegalArgumentException exception = new IllegalArgumentException();
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString"));
given(methodInvocation.getThis()).willReturn(this);
given(methodInvocation.proceed()).willThrow(exception);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ public class SimpleTraceInterceptorTests {
@Test
public void testSunnyDayPathLogsCorrectly() throws Throwable {
MethodInvocation mi = mock(MethodInvocation.class);
given(mi.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
given(mi.getThis()).willReturn(this);
Log log = mock(Log.class);
@@ -48,7 +48,7 @@ public class SimpleTraceInterceptorTests {
@Test
public void testExceptionPathStillLogsCorrectly() throws Throwable {
MethodInvocation mi = mock(MethodInvocation.class);
given(mi.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
given(mi.getThis()).willReturn(this);
IllegalArgumentException exception = new IllegalArgumentException();
given(mi.proceed()).willThrow(exception);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,11 +41,12 @@ public class NameMatchMethodPointcutTests {
protected SerializableNopInterceptor nop;
/**
* Create an empty pointcut, populating instance variables.
*/
@Before
public void setUp() {
public void setup() {
ProxyFactory pf = new ProxyFactory(new SerializablePerson());
nop = new SerializableNopInterceptor();
pc = new NameMatchMethodPointcut();
@@ -53,6 +54,7 @@ public class NameMatchMethodPointcutTests {
proxied = (Person) pf.getProxy();
}
@Test
public void testMatchingOnly() {
// Can't do exact matching through isMatch
@@ -94,7 +96,7 @@ public class NameMatchMethodPointcutTests {
@Test
public void testSets() throws Throwable {
pc.setMappedNames(new String[] { "set*", "echo" });
pc.setMappedNames("set*", "echo");
assertEquals(0, nop.getCount());
proxied.getName();
proxied.setName("");
@@ -116,7 +118,7 @@ public class NameMatchMethodPointcutTests {
}
@Test
public void testEqualsAndHashCode() throws Exception {
public void testEqualsAndHashCode() {
NameMatchMethodPointcut pc1 = new NameMatchMethodPointcut();
NameMatchMethodPointcut pc2 = new NameMatchMethodPointcut();
@@ -70,13 +70,13 @@ public class HotSwappableTargetSourceTests {
@Test
public void testBasicFunctionality() {
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
assertEquals(INITIAL_COUNT, proxied.getCount() );
assertEquals(INITIAL_COUNT, proxied.getCount());
proxied.doWork();
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
assertEquals(INITIAL_COUNT + 1, proxied.getCount());
proxied = (SideEffectBean) beanFactory.getBean("swappable");
proxied.doWork();
assertEquals(INITIAL_COUNT + 2, proxied.getCount() );
assertEquals(INITIAL_COUNT + 2, proxied.getCount());
}
@Test
@@ -85,9 +85,9 @@ public class HotSwappableTargetSourceTests {
SideEffectBean target2 = (SideEffectBean) beanFactory.getBean("target2");
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
assertEquals(target1.getCount(), proxied.getCount() );
assertEquals(target1.getCount(), proxied.getCount());
proxied.doWork();
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
assertEquals(INITIAL_COUNT + 1, proxied.getCount());
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
Object old = swapper.swap(target2);
@@ -56,14 +56,14 @@ public class PrototypeTargetSourceTests {
@Test
public void testPrototypeAndSingletonBehaveDifferently() {
SideEffectBean singleton = (SideEffectBean) beanFactory.getBean("singleton");
assertEquals(INITIAL_COUNT, singleton.getCount() );
assertEquals(INITIAL_COUNT, singleton.getCount());
singleton.doWork();
assertEquals(INITIAL_COUNT + 1, singleton.getCount() );
assertEquals(INITIAL_COUNT + 1, singleton.getCount());
SideEffectBean prototype = (SideEffectBean) beanFactory.getBean("prototype");
assertEquals(INITIAL_COUNT, prototype.getCount() );
assertEquals(INITIAL_COUNT, prototype.getCount());
prototype.doWork();
assertEquals(INITIAL_COUNT, prototype.getCount() );
assertEquals(INITIAL_COUNT, prototype.getCount());
}
@@ -62,9 +62,9 @@ public class ThreadLocalTargetSourceTests {
@Test
public void testUseDifferentManagedInstancesInSameThread() {
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
assertEquals(INITIAL_COUNT, apartment.getCount() );
assertEquals(INITIAL_COUNT, apartment.getCount());
apartment.doWork();
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
ITestBean test = (ITestBean) beanFactory.getBean("threadLocal2");
assertEquals("Rod", test.getName());
@@ -74,12 +74,12 @@ public class ThreadLocalTargetSourceTests {
@Test
public void testReuseInSameThread() {
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
assertEquals(INITIAL_COUNT, apartment.getCount() );
assertEquals(INITIAL_COUNT, apartment.getCount());
apartment.doWork();
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
apartment = (SideEffectBean) beanFactory.getBean("apartment");
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
}
/**
@@ -106,20 +106,20 @@ public class ThreadLocalTargetSourceTests {
@Test
public void testNewThreadHasOwnInstance() throws InterruptedException {
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
assertEquals(INITIAL_COUNT, apartment.getCount() );
assertEquals(INITIAL_COUNT, apartment.getCount());
apartment.doWork();
apartment.doWork();
apartment.doWork();
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
assertEquals(INITIAL_COUNT + 3, apartment.getCount());
class Runner implements Runnable {
public SideEffectBean mine;
@Override
public void run() {
this.mine = (SideEffectBean) beanFactory.getBean("apartment");
assertEquals(INITIAL_COUNT, mine.getCount() );
assertEquals(INITIAL_COUNT, mine.getCount());
mine.doWork();
assertEquals(INITIAL_COUNT + 1, mine.getCount() );
assertEquals(INITIAL_COUNT + 1, mine.getCount());
}
}
Runner r = new Runner();
@@ -130,11 +130,11 @@ public class ThreadLocalTargetSourceTests {
assertNotNull(r);
// Check it didn't affect the other thread's copy
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
assertEquals(INITIAL_COUNT + 3, apartment.getCount());
// When we use other thread's copy in this thread
// it should behave like ours
assertEquals(INITIAL_COUNT + 3, r.mine.getCount() );
assertEquals(INITIAL_COUNT + 3, r.mine.getCount());
// Bound to two threads
assertEquals(2, ((ThreadLocalTargetSourceStats) apartment).getObjectCount());
+11 -18
View File
@@ -1,7 +1,6 @@
description = "Spring Aspects"
// redefine the compileJava and compileTestJava tasks in order to
// compile sources with ajc instead of javac
// Redefine the compileJava and compileTestJava tasks in order to compile sources with ajc instead of javac
configurations {
rt
@@ -10,21 +9,16 @@ configurations {
ajInpath
}
// exclude spring-aspects as a module within IDEA until IDEA-64446 is resolved
tasks.getByName("idea").onlyIf { false }
tasks.getByName("ideaModule").onlyIf { false }
compileJava {
compileJava {
actions = []
dependsOn configurations.ajc.getTaskDependencyFromProjectDependency(true, "compileJava")
def outputDir = project.sourceSets.main.java.outputDir
inputs.files(project.sourceSets.main.allSource + project.sourceSets.main.compileClasspath)
outputs.dir outputDir
ext.sourceCompatibility = project(":spring-core").compileJava.sourceCompatibility
ext.targetCompatibility = project(":spring-core").compileJava.targetCompatibility
sourceCompatibility = 1.8 // fixed even when general compatibility level set to e.g. 10
targetCompatibility = 1.8
doLast{
// Assemble runtime classpath from folders and JARs that actually exist
@@ -49,18 +43,17 @@ compileJava {
}
}
compileTestJava {
compileTestJava {
actions = []
dependsOn configurations.ajc.getTaskDependencyFromProjectDependency(true, "compileTestJava")
dependsOn jar
def outputDir = project.sourceSets.test.java.outputDir
inputs.files(project.sourceSets.test.allSource + project.sourceSets.test.compileClasspath)
outputs.dir outputDir
ext.sourceCompatibility = project(":spring-core").compileTestJava.sourceCompatibility
ext.targetCompatibility = project(":spring-core").compileTestJava.targetCompatibility
sourceCompatibility = 1.8 // fixed even when general compatibility level set to e.g. 10
targetCompatibility = 1.8
doLast{
// Assemble runtime classpath from folders and JARs that actually exist
@@ -87,8 +80,8 @@ compileTestJava {
dependencies {
aspects(project(":spring-orm"))
ajc("org.aspectj:aspectjtools:1.9.0.RC2") // for JDK 9 build compatibility
rt("org.aspectj:aspectjrt:1.9.0.RC2") // for JDK 9 build compatibility
ajc("org.aspectj:aspectjtools:1.9.1") // for JDK 9+ build compatibility
rt("org.aspectj:aspectjrt:1.9.1") // for JDK 9+ build compatibility
compile("org.aspectj:aspectjweaver:${aspectjVersion}") // for Maven POM exposure
optional(project(":spring-aop")) // for @Async support
optional(project(":spring-beans")) // for @Configurable support
@@ -96,11 +89,11 @@ dependencies {
optional(project(":spring-context-support")) // for JavaMail and JSR-107 support
optional(project(":spring-orm")) // for JPA exception translation support
optional(project(":spring-tx")) // for JPA, @Transactional support
optional("javax.cache:cache-api:1.0.0") // for JCache aspect
optional("javax.cache:cache-api:1.1.0") // for JCache aspect
optional("javax.transaction:javax.transaction-api:1.2") // for @javax.transaction.Transactional support
testCompile(project(":spring-core")) // for CodeStyleAspect
testCompile(project(":spring-test"))
testCompile("javax.mail:javax.mail-api:1.6.0")
testCompile("javax.mail:javax.mail-api:1.6.1")
}
eclipse.project {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.context.annotation.Role;
* @see org.springframework.cache.annotation.CachingConfigurationSelector
*/
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
@Bean(name = CacheManagementConfigUtils.CACHE_ASPECT_BEAN_NAME)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.context.annotation.Role;
* @see org.springframework.cache.annotation.CachingConfigurationSelector
*/
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class AspectJJCacheConfiguration extends AbstractJCacheConfiguration {
@Bean(name = CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME)
@@ -45,7 +45,7 @@ import org.springframework.transaction.annotation.AnnotationTransactionAttribute
* @see javax.transaction.Transactional
* @see AnnotationTransactionAspect
*/
@RequiredTypes({"javax.transaction.Transactional"})
@RequiredTypes("javax.transaction.Transactional")
public aspect JtaAnnotationTransactionAspect extends AbstractTransactionAspect {
public JtaAnnotationTransactionAspect() {
+6 -8
View File
@@ -3,17 +3,16 @@ description = "Spring Beans"
apply plugin: "groovy"
dependencies {
compile(project(':spring-core'))
compile(project(":spring-core"))
optional("javax.inject:javax.inject:1")
optional("org.yaml:snakeyaml:1.19")
optional("org.yaml:snakeyaml:1.20")
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
}
// This modules does joint compilation for Java and Groovy code,
// with the compileGroovy task.
// This module does joint compilation for Java and Groovy code with the compileGroovy task.
sourceSets {
main.groovy.srcDirs += "src/main/java"
main.java.srcDirs = []
@@ -24,9 +23,8 @@ compileGroovy {
targetCompatibility = 1.8
}
// This module also builds Kotlin code and the compileKotlin task
// naturally depends on compileJava.
// We need to redefine dependencies to break task cycles.
compileGroovy.dependsOn = compileGroovy.taskDependencies.values - 'compileJava'
// This module also builds Kotlin code and the compileKotlin task naturally depends on
// compileJava. We need to redefine dependencies to break task cycles.
compileGroovy.dependsOn = compileGroovy.taskDependencies.values - "compileJava"
compileKotlin.dependsOn(compileGroovy)
compileKotlin.classpath += files(compileGroovy.destinationDir)
@@ -634,7 +634,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
"property path '" + propertyName + "': returned null");
}
}
String indexedPropertyName = tokens.actualName;
StringBuilder indexedPropertyName = new StringBuilder(tokens.actualName);
// apply indexes and map keys
for (int i = 0; i < tokens.keys.length; i++) {
String key = tokens.keys[i];
@@ -645,13 +645,13 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
}
else if (value.getClass().isArray()) {
int index = Integer.parseInt(key);
value = growArrayIfNecessary(value, index, indexedPropertyName);
value = growArrayIfNecessary(value, index, indexedPropertyName.toString());
value = Array.get(value, index);
}
else if (value instanceof List) {
int index = Integer.parseInt(key);
List<Object> list = (List<Object>) value;
growCollectionIfNecessary(list, index, indexedPropertyName, ph, i + 1);
growCollectionIfNecessary(list, index, indexedPropertyName.toString(), ph, i + 1);
value = list.get(index);
}
else if (value instanceof Set) {
@@ -686,7 +686,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Set nor a Map; returned value was [" + value + "]");
}
indexedPropertyName += PROPERTY_KEY_PREFIX + key + PROPERTY_KEY_SUFFIX;
indexedPropertyName.append(PROPERTY_KEY_PREFIX).append(key).append(PROPERTY_KEY_SUFFIX);
}
}
return value;
@@ -695,11 +695,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Index of out of bounds in property path '" + propertyName + "'", ex);
}
catch (NumberFormatException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid index in property path '" + propertyName + "'", ex);
}
catch (TypeMismatchException ex) {
catch (NumberFormatException | TypeMismatchException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid index in property path '" + propertyName + "'", ex);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
package org.springframework.beans;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -110,7 +110,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
}
catch (PropertyAccessException ex) {
if (propertyAccessExceptions == null) {
propertyAccessExceptions = new LinkedList<>();
propertyAccessExceptions = new ArrayList<>();
}
propertyAccessExceptions.add(ex);
}
@@ -118,8 +118,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
// If we encountered individual exceptions, throw the composite exception.
if (propertyAccessExceptions != null) {
PropertyAccessException[] paeArray =
propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);
throw new PropertyBatchUpdateException(paeArray);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,12 +98,19 @@ public abstract class BeanUtils {
}
/**
* Instantiate a class using its no-arg constructor.
* Instantiate a class using its 'primary' constructor (for Kotlin classes,
* potentially having default arguments declared) or its default constructor
* (for regular Java classes, expecting a standard no-arg setup).
* <p>Note that this method tries to set the constructor accessible
* if given a non-accessible (that is, non-public) constructor.
* @param clazz class to instantiate
* @param clazz the class to instantiate
* @return the new instance
* @throws BeanInstantiationException if the bean cannot be instantiated
* @throws BeanInstantiationException if the bean cannot be instantiated.
* The cause may notably indicate a {@link NoSuchMethodException} if no
* primary/default constructor was found, a {@link NoClassDefFoundError}
* or other {@link LinkageError} in case of an unresolvable class definition
* (e.g. due to a missing dependency at runtime), or an exception thrown
* from the constructor invocation itself.
* @see Constructor#newInstance
*/
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
@@ -113,15 +120,15 @@ public abstract class BeanUtils {
}
try {
Constructor<T> ctor = (KotlinDetector.isKotlinType(clazz) ?
KotlinDelegate.findPrimaryConstructor(clazz) : clazz.getDeclaredConstructor());
if (ctor == null) {
throw new BeanInstantiationException(clazz, "No default constructor found");
}
KotlinDelegate.getPrimaryConstructor(clazz) : clazz.getDeclaredConstructor());
return instantiateClass(ctor);
}
catch (NoSuchMethodException ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
catch (LinkageError err) {
throw new BeanInstantiationException(clazz, "Unresolvable class definition", err);
}
}
/**
@@ -360,23 +367,23 @@ public abstract class BeanUtils {
public static Method resolveSignature(String signature, Class<?> clazz) {
Assert.hasText(signature, "'signature' must not be empty");
Assert.notNull(clazz, "Class must not be null");
int firstParen = signature.indexOf("(");
int lastParen = signature.indexOf(")");
if (firstParen > -1 && lastParen == -1) {
int startParen = signature.indexOf('(');
int endParen = signature.indexOf(')');
if (startParen > -1 && endParen == -1) {
throw new IllegalArgumentException("Invalid method signature '" + signature +
"': expected closing ')' for args list");
}
else if (lastParen > -1 && firstParen == -1) {
else if (startParen == -1 && endParen > -1) {
throw new IllegalArgumentException("Invalid method signature '" + signature +
"': expected opening '(' for args list");
}
else if (firstParen == -1 && lastParen == -1) {
else if (startParen == -1) {
return findMethodWithMinimalParameters(clazz, signature);
}
else {
String methodName = signature.substring(0, firstParen);
String methodName = signature.substring(0, startParen);
String[] parameterTypeNames =
StringUtils.commaDelimitedListToStringArray(signature.substring(firstParen + 1, lastParen));
StringUtils.commaDelimitedListToStringArray(signature.substring(startParen + 1, endParen));
Class<?>[] parameterTypes = new Class<?>[parameterTypeNames.length];
for (int i = 0; i < parameterTypeNames.length; i++) {
String parameterTypeName = parameterTypeNames[i].trim();
@@ -561,13 +568,14 @@ public abstract class BeanUtils {
/**
* Check if the given type represents a "simple" value type:
* a primitive, a String or other CharSequence, a Number, a Date,
* a primitive, an enum, a String or other CharSequence, a Number, a Date,
* a URI, a URL, a Locale or a Class.
* @param clazz the type to check
* @return whether the given type represents a "simple" value type
*/
public static boolean isSimpleValueType(Class<?> clazz) {
return (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||
return (ClassUtils.isPrimitiveOrWrapper(clazz) ||
Enum.class.isAssignableFrom(clazz) ||
CharSequence.class.isAssignableFrom(clazz) ||
Number.class.isAssignableFrom(clazz) ||
Date.class.isAssignableFrom(clazz) ||
@@ -692,10 +700,26 @@ public abstract class BeanUtils {
private static class KotlinDelegate {
/**
* Return the Java constructor corresponding to the Kotlin primary constructor if any.
* Determine the Java constructor corresponding to the Kotlin primary constructor.
* @param clazz the {@link Class} of the Kotlin class
* @throws NoSuchMethodException if no such constructor found
* @since 5.0.3
* @see #findPrimaryConstructor
* @see Class#getDeclaredConstructor
*/
public static <T> Constructor<T> getPrimaryConstructor(Class<T> clazz) throws NoSuchMethodException {
Constructor<T> ctor = findPrimaryConstructor(clazz);
if (ctor == null) {
throw new NoSuchMethodException();
}
return ctor;
}
/**
* Retrieve the Java constructor corresponding to the Kotlin primary constructor, if any.
* @param clazz the {@link Class} of the Kotlin class
* @see <a href="http://kotlinlang.org/docs/reference/classes.html#constructors">
* http://kotlinlang.org/docs/reference/classes.html#constructors</a>
* http://kotlinlang.org/docs/reference/classes.html#constructors</a>
*/
@Nullable
public static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) {
@@ -705,8 +729,10 @@ public abstract class BeanUtils {
return null;
}
Constructor<T> constructor = ReflectJvmMapping.getJavaConstructor(primaryCtor);
Assert.notNull(constructor,
() -> "Failed to find Java constructor for Kotlin primary constructor: " + clazz.getName());
if (constructor == null) {
throw new IllegalStateException(
"Failed to find Java constructor for Kotlin primary constructor: " + clazz.getName());
}
return constructor;
}
catch (UnsupportedOperationException ex) {
@@ -717,7 +743,8 @@ public abstract class BeanUtils {
/**
* Instantiate a Kotlin class using the provided constructor.
* @param ctor the constructor of the Kotlin class to instantiate
* @param args the constructor arguments to apply (use null for unspecified parameter if needed)
* @param args the constructor arguments to apply
* (use {@code null} for unspecified parameter if needed)
*/
public static <T> T instantiateClass(Constructor<T> ctor, Object... args)
throws IllegalAccessException, InvocationTargetException, InstantiationException {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -228,10 +228,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
@Nullable
protected BeanPropertyHandler getLocalPropertyHandler(String propertyName) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);
if (pd != null) {
return new BeanPropertyHandler(pd);
}
return null;
return (pd != null ? new BeanPropertyHandler(pd) : null);
}
@Override
@@ -242,8 +239,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
@Override
protected NotWritablePropertyException createNotWritablePropertyException(String propertyName) {
PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());
throw new NotWritablePropertyException(
getRootClass(), getNestedPath() + propertyName,
throw new NotWritablePropertyException(getRootClass(), getNestedPath() + propertyName,
matches.buildErrorMessage(), matches.getPossibleMatches());
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@ import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -150,24 +149,12 @@ public class CachedIntrospectionResults {
* @param classLoader the ClassLoader to clear the cache for
*/
public static void clearClassLoader(@Nullable ClassLoader classLoader) {
for (Iterator<ClassLoader> it = acceptedClassLoaders.iterator(); it.hasNext();) {
ClassLoader registeredLoader = it.next();
if (isUnderneathClassLoader(registeredLoader, classLoader)) {
it.remove();
}
}
for (Iterator<Class<?>> it = strongClassCache.keySet().iterator(); it.hasNext();) {
Class<?> beanClass = it.next();
if (isUnderneathClassLoader(beanClass.getClassLoader(), classLoader)) {
it.remove();
}
}
for (Iterator<Class<?>> it = softClassCache.keySet().iterator(); it.hasNext();) {
Class<?> beanClass = it.next();
if (isUnderneathClassLoader(beanClass.getClassLoader(), classLoader)) {
it.remove();
}
}
acceptedClassLoaders.removeIf(registeredLoader ->
isUnderneathClassLoader(registeredLoader, classLoader));
strongClassCache.keySet().removeIf(beanClass ->
isUnderneathClassLoader(beanClass.getClassLoader(), classLoader));
softClassCache.keySet().removeIf(beanClass ->
isUnderneathClassLoader(beanClass.getClassLoader(), classLoader));
}
/**
@@ -244,6 +231,24 @@ public class CachedIntrospectionResults {
return false;
}
/**
* Retrieve a {@link BeanInfo} descriptor for the given target class.
* @param beanClass the target class to introspect
* @return the resulting {@code BeanInfo} descriptor (never {@code null})
* @throws IntrospectionException from the underlying {@link Introspector}
*/
private static BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
for (BeanInfoFactory beanInfoFactory : beanInfoFactories) {
BeanInfo beanInfo = beanInfoFactory.getBeanInfo(beanClass);
if (beanInfo != null) {
return beanInfo;
}
}
return (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
}
/** The BeanInfo object for the introspected bean class */
private final BeanInfo beanInfo;
@@ -265,21 +270,7 @@ public class CachedIntrospectionResults {
if (logger.isTraceEnabled()) {
logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");
}
BeanInfo beanInfo = null;
for (BeanInfoFactory beanInfoFactory : beanInfoFactories) {
beanInfo = beanInfoFactory.getBeanInfo(beanClass);
if (beanInfo != null) {
break;
}
}
if (beanInfo == null) {
// If none of the factories supported the class, fall back to the default
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
}
this.beanInfo = beanInfo;
this.beanInfo = getBeanInfo(beanClass);
if (logger.isTraceEnabled()) {
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
@@ -307,15 +298,14 @@ public class CachedIntrospectionResults {
// Explicitly check implemented interfaces for setter/getter methods as well,
// in particular for Java 8 default methods...
Class<?> clazz = beanClass;
while (clazz != null) {
Class<?>[] ifcs = clazz.getInterfaces();
for (Class<?> ifc : ifcs) {
BeanInfo ifcInfo = Introspector.getBeanInfo(ifc, Introspector.IGNORE_ALL_BEANINFO);
PropertyDescriptor[] ifcPds = ifcInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : ifcPds) {
if (!this.propertyDescriptorCache.containsKey(pd.getName())) {
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
this.propertyDescriptorCache.put(pd.getName(), pd);
while (clazz != null && clazz != Object.class) {
for (Class<?> ifc : clazz.getInterfaces()) {
if (!ClassUtils.isJavaLanguageInterface(ifc)) {
for (PropertyDescriptor pd : getBeanInfo(ifc).getPropertyDescriptors()) {
if (!this.propertyDescriptorCache.containsKey(pd.getName())) {
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
this.propertyDescriptorCache.put(pd.getName(), pd);
}
}
}
}
@@ -329,6 +319,7 @@ public class CachedIntrospectionResults {
}
}
BeanInfo getBeanInfo() {
return this.beanInfo;
}
@@ -341,10 +332,10 @@ public class CachedIntrospectionResults {
PropertyDescriptor getPropertyDescriptor(String name) {
PropertyDescriptor pd = this.propertyDescriptorCache.get(name);
if (pd == null && StringUtils.hasLength(name)) {
// Same lenient fallback checking as in PropertyTypeDescriptor...
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toLowerCase() + name.substring(1));
// Same lenient fallback checking as in Property...
pd = this.propertyDescriptorCache.get(StringUtils.uncapitalize(name));
if (pd == null) {
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toUpperCase() + name.substring(1));
pd = this.propertyDescriptorCache.get(StringUtils.capitalize(name));
}
}
return (pd == null || pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,14 +71,15 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
@Override
@Nullable
protected FieldPropertyHandler getLocalPropertyHandler(String propertyName) {
FieldPropertyHandler propertyHandler = this.fieldMap.get(propertyName);
if (propertyHandler == null) {
Field field = ReflectionUtils.findField(getWrappedClass(), propertyName);
if (field != null) {
propertyHandler = new FieldPropertyHandler(field);
this.fieldMap.put(propertyName, propertyHandler);
}
this.fieldMap.put(propertyName, propertyHandler);
}
return propertyHandler;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,8 +43,10 @@ import org.springframework.util.ObjectUtils;
* Decorator for a standard {@link BeanInfo} object, e.g. as created by
* {@link Introspector#getBeanInfo(Class)}, designed to discover and register static
* and/or non-void returning setter methods. For example:
*
* <pre class="code">
* public class Bean {
*
* private Foo foo;
*
* public Foo getFoo() {
@@ -56,6 +58,7 @@ import org.springframework.util.ObjectUtils;
* return this;
* }
* }</pre>
*
* The standard JavaBeans {@code Introspector} will discover the {@code getFoo} read
* method, but will bypass the {@code #setFoo(Foo)} write method, because its non-void
* returning signature does not comply with the JavaBeans specification.
@@ -68,6 +71,7 @@ import org.springframework.util.ObjectUtils;
* indexed properties</a> are fully supported.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see #ExtendedBeanInfo(BeanInfo)
* @see ExtendedBeanInfoFactory
@@ -79,8 +83,7 @@ class ExtendedBeanInfo implements BeanInfo {
private final BeanInfo delegate;
private final Set<PropertyDescriptor> propertyDescriptors =
new TreeSet<>(new PropertyDescriptorComparator());
private final Set<PropertyDescriptor> propertyDescriptors = new TreeSet<>(new PropertyDescriptorComparator());
/**
@@ -91,11 +94,9 @@ class ExtendedBeanInfo implements BeanInfo {
* through its method descriptors to find any non-void returning write methods and
* update or create the corresponding {@link PropertyDescriptor} for each one found.
* @param delegate the wrapped {@code BeanInfo}, which is never modified
* @throws IntrospectionException if any problems occur creating and adding new
* property descriptors
* @see #getPropertyDescriptors()
*/
public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
public ExtendedBeanInfo(BeanInfo delegate) {
this.delegate = delegate;
for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) {
try {
@@ -213,14 +214,14 @@ class ExtendedBeanInfo implements BeanInfo {
/**
* Return the set of {@link PropertyDescriptor}s from the wrapped {@link BeanInfo}
* object as well as {@code PropertyDescriptor}s for each non-void returning setter
* method found during construction.
* Return the set of {@link PropertyDescriptor PropertyDescriptors} from the wrapped
* {@link BeanInfo} object as well as {@code PropertyDescriptors} for each non-void
* returning setter method found during construction.
* @see #ExtendedBeanInfo(BeanInfo)
*/
@Override
public PropertyDescriptor[] getPropertyDescriptors() {
return this.propertyDescriptors.toArray(new PropertyDescriptor[this.propertyDescriptors.size()]);
return this.propertyDescriptors.toArray(new PropertyDescriptor[0]);
}
@Override
@@ -259,6 +260,9 @@ class ExtendedBeanInfo implements BeanInfo {
}
/**
* A simple {@link PropertyDescriptor}.
*/
static class SimplePropertyDescriptor extends PropertyDescriptor {
@Nullable
@@ -278,7 +282,9 @@ class ExtendedBeanInfo implements BeanInfo {
PropertyDescriptorUtils.copyNonMethodProperties(original, this);
}
public SimplePropertyDescriptor(String propertyName, @Nullable Method readMethod, Method writeMethod) throws IntrospectionException {
public SimplePropertyDescriptor(String propertyName, @Nullable Method readMethod, Method writeMethod)
throws IntrospectionException {
super(propertyName, null, null);
this.readMethod = readMethod;
this.writeMethod = writeMethod;
@@ -308,6 +314,7 @@ class ExtendedBeanInfo implements BeanInfo {
}
@Override
@Nullable
public Class<?> getPropertyType() {
if (this.propertyType == null) {
try {
@@ -350,6 +357,9 @@ class ExtendedBeanInfo implements BeanInfo {
}
/**
* A simple {@link IndexedPropertyDescriptor}.
*/
static class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor {
@Nullable
@@ -379,8 +389,9 @@ class ExtendedBeanInfo implements BeanInfo {
PropertyDescriptorUtils.copyNonMethodProperties(original, this);
}
public SimpleIndexedPropertyDescriptor(String propertyName, @Nullable Method readMethod, @Nullable Method writeMethod,
@Nullable Method indexedReadMethod, Method indexedWriteMethod) throws IntrospectionException {
public SimpleIndexedPropertyDescriptor(String propertyName, @Nullable Method readMethod,
@Nullable Method writeMethod, @Nullable Method indexedReadMethod, Method indexedWriteMethod)
throws IntrospectionException {
super(propertyName, null, null, null, null);
this.readMethod = readMethod;
@@ -415,6 +426,7 @@ class ExtendedBeanInfo implements BeanInfo {
}
@Override
@Nullable
public Class<?> getPropertyType() {
if (this.propertyType == null) {
try {
@@ -450,6 +462,7 @@ class ExtendedBeanInfo implements BeanInfo {
}
@Override
@Nullable
public Class<?> getIndexedPropertyType() {
if (this.indexedPropertyType == null) {
try {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ public interface Mergeable {
* @param parent the object to merge with
* @return the result of the merge operation
* @throws IllegalArgumentException if the supplied parent is {@code null}
* @exception IllegalStateException if merging is not enabled for this instance
* @throws IllegalStateException if merging is not enabled for this instance
* (i.e. {@code mergeEnabled} equals {@code false}).
*/
Object merge(@Nullable Object parent);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Default implementation of the {@link PropertyValues} interface.
* The default implementation of the {@link PropertyValues} interface.
* Allows simple manipulation of properties, and provides constructors
* to support deep copy and construction from a Map.
*
@@ -80,7 +80,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
/**
* Construct a new MutablePropertyValues object from a Map.
* @param original Map with property values keyed by property name Strings
* @param original a Map with property values keyed by property name Strings
* @see #addPropertyValues(Map)
*/
public MutablePropertyValues(@Nullable Map<?, ?> original) {
@@ -101,7 +101,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
* PropertyValue objects as-is.
* <p>This is a constructor for advanced usage scenarios.
* It is not intended for typical programmatic use.
* @param propertyValueList List of PropertyValue objects
* @param propertyValueList a List of PropertyValue objects
*/
public MutablePropertyValues(@Nullable List<PropertyValue> propertyValueList) {
this.propertyValueList =
@@ -145,7 +145,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
/**
* Add all property values from the given Map.
* @param other Map with property values keyed by property name,
* @param other a Map with property values keyed by property name,
* which must be a String
* @return this in order to allow for adding multiple property values in a chain
*/
@@ -160,7 +160,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
/**
* Add a PropertyValue object, replacing any existing one for the
* corresponding property or getting merged with it (if applicable).
* @param pv PropertyValue object to add
* @param pv the PropertyValue object to add
* @return this in order to allow for adding multiple property values in a chain
*/
public MutablePropertyValues addPropertyValue(PropertyValue pv) {
@@ -246,7 +246,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
@Override
public PropertyValue[] getPropertyValues() {
return this.propertyValueList.toArray(new PropertyValue[this.propertyValueList.size()]);
return this.propertyValueList.toArray(new PropertyValue[0]);
}
@Override
@@ -285,11 +285,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
for (PropertyValue newPv : this.propertyValueList) {
// if there wasn't an old one, add it
PropertyValue pvOld = old.getPropertyValue(newPv.getName());
if (pvOld == null) {
changes.addPropertyValue(newPv);
}
else if (!pvOld.equals(newPv)) {
// it's changed
if (pvOld == null || !pvOld.equals(newPv)) {
changes.addPropertyValue(newPv);
}
}
@@ -352,14 +348,8 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof MutablePropertyValues)) {
return false;
}
MutablePropertyValues that = (MutablePropertyValues) other;
return this.propertyValueList.equals(that.propertyValueList);
return (this == other || (other instanceof MutablePropertyValues &&
this.propertyValueList.equals(((MutablePropertyValues) other).propertyValueList)));
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,14 +30,12 @@ import org.springframework.util.ObjectUtils;
* @author Chris Beams
* @author Juergen Hoeller
*/
class PropertyDescriptorUtils {
abstract class PropertyDescriptorUtils {
/**
* See {@link java.beans.FeatureDescriptor}.
*/
public static void copyNonMethodProperties(PropertyDescriptor source, PropertyDescriptor target)
throws IntrospectionException {
public static void copyNonMethodProperties(PropertyDescriptor source, PropertyDescriptor target) {
target.setExpert(source.isExpert());
target.setHidden(source.isHidden());
target.setPreferred(source.isPreferred());
@@ -79,7 +77,7 @@ class PropertyDescriptorUtils {
}
if (writeMethod != null) {
Class<?> params[] = writeMethod.getParameterTypes();
Class<?>[] params = writeMethod.getParameterTypes();
if (params.length != 1) {
throw new IntrospectionException("Bad write method arg count: " + writeMethod);
}
@@ -114,7 +112,7 @@ class PropertyDescriptorUtils {
Class<?> indexedPropertyType = null;
if (indexedReadMethod != null) {
Class<?> params[] = indexedReadMethod.getParameterTypes();
Class<?>[] params = indexedReadMethod.getParameterTypes();
if (params.length != 1) {
throw new IntrospectionException("Bad indexed read method arg count: " + indexedReadMethod);
}
@@ -128,7 +126,7 @@ class PropertyDescriptorUtils {
}
if (indexedWriteMethod != null) {
Class<?> params[] = indexedWriteMethod.getParameterTypes();
Class<?>[] params = indexedWriteMethod.getParameterTypes();
if (params.length != 2) {
throw new IntrospectionException("Bad indexed write method arg count: " + indexedWriteMethod);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,12 +27,12 @@ import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Currency;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -318,7 +318,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
// Check property-specific editor first.
PropertyEditor editor = getCustomEditor(propertyPath, requiredType);
if (editor == null) {
List<String> strippedPaths = new LinkedList<>();
List<String> strippedPaths = new ArrayList<>();
addStrippedPropertyPaths(strippedPaths, "", propertyPath);
for (Iterator<String> it = strippedPaths.iterator(); it.hasNext() && editor == null;) {
String strippedPath = it.next();
@@ -349,10 +349,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
public boolean hasCustomEditorForElement(@Nullable Class<?> elementType, @Nullable String propertyPath) {
if (propertyPath != null && this.customEditorsForPath != null) {
for (Map.Entry<String, CustomEditorHolder> entry : this.customEditorsForPath.entrySet()) {
if (PropertyAccessorUtils.matchesProperty(entry.getKey(), propertyPath)) {
if (entry.getValue().getPropertyEditor(elementType) != null) {
return true;
}
if (PropertyAccessorUtils.matchesProperty(entry.getKey(), propertyPath) &&
entry.getValue().getPropertyEditor(elementType) != null) {
return true;
}
}
}
@@ -439,7 +438,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
if (this.customEditorsForPath != null) {
CustomEditorHolder editorHolder = this.customEditorsForPath.get(propertyName);
if (editorHolder == null) {
List<String> strippedPaths = new LinkedList<>();
List<String> strippedPaths = new ArrayList<>();
addStrippedPropertyPaths(strippedPaths, "", propertyName);
for (Iterator<String> it = strippedPaths.iterator(); it.hasNext() && editorHolder == null;) {
String strippedName = it.next();
@@ -467,9 +466,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
this.customEditors.forEach(target::registerCustomEditor);
}
if (this.customEditorsForPath != null) {
for (Map.Entry<String, CustomEditorHolder> entry : this.customEditorsForPath.entrySet()) {
String editorPath = entry.getKey();
CustomEditorHolder editorHolder = entry.getValue();
this.customEditorsForPath.forEach((editorPath, editorHolder) -> {
if (nestedProperty != null) {
int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(editorPath);
if (pos != -1) {
@@ -485,7 +482,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
target.registerCustomEditor(
editorHolder.getRegisteredType(), editorPath, editorHolder.getPropertyEditor());
}
}
});
}
}
@@ -520,7 +517,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
* Holder for a registered custom editor with property name.
* Keeps the PropertyEditor itself plus the type it was registered for.
*/
private static class CustomEditorHolder {
private static final class CustomEditorHolder {
private final PropertyEditor propertyEditor;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@ public abstract class PropertyMatches {
private final String propertyName;
private String[] possibleMatches;
private final String[] possibleMatches;
/**
@@ -155,8 +155,8 @@ public abstract class PropertyMatches {
if (s2.isEmpty()) {
return s1.length();
}
int d[][] = new int[s1.length() + 1][s2.length() + 1];
int[][] d = new int[s1.length() + 1][s2.length() + 1];
for (int i = 0; i <= s1.length(); i++) {
d[i][0] = i;
}
@@ -165,18 +165,17 @@ public abstract class PropertyMatches {
}
for (int i = 1; i <= s1.length(); i++) {
char s_i = s1.charAt(i - 1);
char c1 = s1.charAt(i - 1);
for (int j = 1; j <= s2.length(); j++) {
int cost;
char t_j = s2.charAt(j - 1);
if (s_i == t_j) {
char c2 = s2.charAt(j - 1);
if (c1 == c2) {
cost = 0;
}
else {
cost = 1;
}
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1),
d[i - 1][j - 1] + cost);
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + cost);
}
}
@@ -189,24 +188,23 @@ public abstract class PropertyMatches {
private static class BeanPropertyMatches extends PropertyMatches {
public BeanPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
super(propertyName, calculateMatches(propertyName,
BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
super(propertyName,
calculateMatches(propertyName, BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
}
/**
* Generate possible property alternatives for the given property and
* class. Internally uses the {@code getStringDistance} method, which
* in turn uses the Levenshtein algorithm to determine the distance between
* two Strings.
* @param propertyDescriptors the JavaBeans property descriptors to search
* Generate possible property alternatives for the given property and class.
* Internally uses the {@code getStringDistance} method, which in turn uses
* the Levenshtein algorithm to determine the distance between two Strings.
* @param descriptors the JavaBeans property descriptors to search
* @param maxDistance the maximum distance to accept
*/
private static String[] calculateMatches(String propertyName, PropertyDescriptor[] propertyDescriptors, int maxDistance) {
private static String[] calculateMatches(String name, PropertyDescriptor[] descriptors, int maxDistance) {
List<String> candidates = new ArrayList<>();
for (PropertyDescriptor pd : propertyDescriptors) {
for (PropertyDescriptor pd : descriptors) {
if (pd.getWriteMethod() != null) {
String possibleAlternative = pd.getName();
if (calculateStringDistance(propertyName, possibleAlternative) <= maxDistance) {
if (calculateStringDistance(name, possibleAlternative) <= maxDistance) {
candidates.add(possibleAlternative);
}
}
@@ -215,21 +213,16 @@ public abstract class PropertyMatches {
return StringUtils.toStringArray(candidates);
}
@Override
public String buildErrorMessage() {
String propertyName = getPropertyName();
String[] possibleMatches = getPossibleMatches();
StringBuilder msg = new StringBuilder();
msg.append("Bean property '");
msg.append(propertyName);
msg.append("' is not writable or has an invalid setter method. ");
if (ObjectUtils.isEmpty(possibleMatches)) {
msg.append("Does the parameter type of the setter match the return type of the getter?");
StringBuilder msg = new StringBuilder(160);
msg.append("Bean property '").append(getPropertyName()).append(
"' is not writable or has an invalid setter method. ");
if (!ObjectUtils.isEmpty(getPossibleMatches())) {
appendHintMessage(msg);
}
else {
appendHintMessage(msg);
msg.append("Does the parameter type of the setter match the return type of the getter?");
}
return msg.toString();
}
@@ -242,11 +235,11 @@ public abstract class PropertyMatches {
super(propertyName, calculateMatches(propertyName, beanClass, maxDistance));
}
private static String[] calculateMatches(final String propertyName, Class<?> beanClass, final int maxDistance) {
private static String[] calculateMatches(final String name, Class<?> clazz, final int maxDistance) {
final List<String> candidates = new ArrayList<>();
ReflectionUtils.doWithFields(beanClass, field -> {
ReflectionUtils.doWithFields(clazz, field -> {
String possibleAlternative = field.getName();
if (calculateStringDistance(propertyName, possibleAlternative) <= maxDistance) {
if (calculateStringDistance(name, possibleAlternative) <= maxDistance) {
candidates.add(possibleAlternative);
}
});
@@ -256,14 +249,10 @@ public abstract class PropertyMatches {
@Override
public String buildErrorMessage() {
String propertyName = getPropertyName();
String[] possibleMatches = getPossibleMatches();
StringBuilder msg = new StringBuilder();
msg.append("Bean property '");
msg.append(propertyName);
msg.append("' has no matching field. ");
if (!ObjectUtils.isEmpty(possibleMatches)) {
StringBuilder msg = new StringBuilder(80);
msg.append("Bean property '").append(getPropertyName()).append("' has no matching field.");
if (!ObjectUtils.isEmpty(getPossibleMatches())) {
msg.append(' ');
appendHintMessage(msg);
}
return msg.toString();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ public interface PropertyValues {
* Return the changes since the previous PropertyValues.
* Subclasses should also override {@code equals}.
* @param old old property values
* @return PropertyValues updated or new properties.
* @return the updated or new properties.
* Return empty PropertyValues if there are no changes.
* @see Object#equals
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -317,7 +317,7 @@ class TypeConverterDelegate {
if (Enum.class == requiredType && this.targetObject != null) {
// target type is declared as raw enum, treat the trimmed value as <enum.fqn>.FIELD_NAME
int index = trimmedValue.lastIndexOf(".");
int index = trimmedValue.lastIndexOf('.');
if (index > - 1) {
String enumType = trimmedValue.substring(0, index);
String fieldName = trimmedValue.substring(index + 1);
@@ -346,6 +346,7 @@ class TypeConverterDelegate {
// to be checked, hence we don't return it right away.
try {
Field enumField = requiredType.getField(trimmedValue);
ReflectionUtils.makeAccessible(enumField);
convertedValue = enumField.get(null);
}
catch (Throwable ex) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.beans;
import java.beans.PropertyChangeEvent;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -36,6 +37,9 @@ public class TypeMismatchException extends PropertyAccessException {
public static final String ERROR_CODE = "typeMismatch";
@Nullable
private String propertyName;
@Nullable
private transient Object value;
@@ -44,7 +48,7 @@ public class TypeMismatchException extends PropertyAccessException {
/**
* Create a new TypeMismatchException.
* Create a new {@code TypeMismatchException}.
* @param propertyChangeEvent the PropertyChangeEvent that resulted in the problem
* @param requiredType the required target type
*/
@@ -53,7 +57,7 @@ public class TypeMismatchException extends PropertyAccessException {
}
/**
* Create a new TypeMismatchException.
* Create a new {@code TypeMismatchException}.
* @param propertyChangeEvent the PropertyChangeEvent that resulted in the problem
* @param requiredType the required target type (or {@code null} if not known)
* @param cause the root cause (may be {@code null})
@@ -69,24 +73,27 @@ public class TypeMismatchException extends PropertyAccessException {
(propertyChangeEvent.getPropertyName() != null ?
" for property '" + propertyChangeEvent.getPropertyName() + "'" : ""),
cause);
this.propertyName = propertyChangeEvent.getPropertyName();
this.value = propertyChangeEvent.getNewValue();
this.requiredType = requiredType;
}
/**
* Create a new TypeMismatchException without PropertyChangeEvent.
* Create a new {@code TypeMismatchException} without a {@code PropertyChangeEvent}.
* @param value the offending value that couldn't be converted (may be {@code null})
* @param requiredType the required target type (or {@code null} if not known)
* @see #initPropertyName
*/
public TypeMismatchException(@Nullable Object value, @Nullable Class<?> requiredType) {
this(value, requiredType, null);
}
/**
* Create a new TypeMismatchException without PropertyChangeEvent.
* Create a new {@code TypeMismatchException} without a {@code PropertyChangeEvent}.
* @param value the offending value that couldn't be converted (may be {@code null})
* @param requiredType the required target type (or {@code null} if not known)
* @param cause the root cause (may be {@code null})
* @see #initPropertyName
*/
public TypeMismatchException(@Nullable Object value, @Nullable Class<?> requiredType, @Nullable Throwable cause) {
super("Failed to convert value of type '" + ClassUtils.getDescriptiveType(value) + "'" +
@@ -97,6 +104,28 @@ public class TypeMismatchException extends PropertyAccessException {
}
/**
* Initialize this exception's property name for exposure through {@link #getPropertyName()},
* as an alternative to having it initialized via a {@link PropertyChangeEvent}.
* @param propertyName the property name to expose
* @since 5.0.4
* @see #TypeMismatchException(Object, Class)
* @see #TypeMismatchException(Object, Class, Throwable)
*/
public void initPropertyName(String propertyName) {
Assert.state(this.propertyName == null, "Property name already initialized");
this.propertyName = propertyName;
}
/**
* Return the name of the affected property, if available.
*/
@Override
@Nullable
public String getPropertyName() {
return this.propertyName;
}
/**
* Return the offending value (may be {@code null}).
*/

Some files were not shown because too many files have changed in this diff Show More