Compare commits

...

295 Commits

Author SHA1 Message Date
Spring Buildmaster d111af1b88 Release version 4.2.8.RELEASE 2016-09-19 14:42:49 +00:00
Rossen Stoyanchev 62b02c23ab Reset connection before delegating to handler
Resetting the connection first before invoking a failure callback on
the application handler ensures that any checks to isConnected will
return false.

Issue: SPR-14721
2016-09-19 09:04:55 -04:00
Juergen Hoeller a0773aef1d Polishing 2016-09-18 21:24:19 +02:00
Juergen Hoeller cc56ef5737 Revised checkResource implementation
Issue: SPR-14729
(cherry picked from commit ca17edd)
2016-09-18 21:24:11 +02:00
Brian Clozel 97c9b05c15 Check template availability in ScriptTemplateView
This commit overrides the `checkResource` implementation in
`ScriptTemplateView` in order to check if the template file resource is
available and if the resolver can then proceed with rendering the
template.

Issue: SPR-14729
2016-09-17 22:18:55 +02:00
Juergen Hoeller ed19dc7900 Polishing 2016-09-16 11:18:50 +02:00
Juergen Hoeller 7902f63cb1 Latest applicable dependency updates (Woodstox 5.0.3, Jettison 1.3.8) 2016-09-16 11:07:45 +02:00
Juergen Hoeller 818c72a2b3 StringUtils.parseLocaleString accepts Java 7 variants
Issue: SPR-14718
(cherry picked from commit 7ddaf49)
2016-09-16 11:07:26 +02:00
Juergen Hoeller c9943aacc5 Timeout exceptions as RuntimeExceptions
Issue: SPR-14669
(cherry picked from commit e947363)
2016-09-15 10:05:04 +02:00
Rossen Stoyanchev 9fa2a46d35 Improve async request timeout handling
Rather than setting the status to 503 directly from the timeout
interceptor which no longer seems to work reliably with Servlet
containers like Jetty even performing an additional ERROR dispatch back
to the original URL, we know rather set the DeferredResult to an
AsyncTimeoutException, which results in a dispatch and standard
handling within Spring MVC. This should be a more reliable way of
dealing with timeouts.

Issue: SPR-14669
2016-09-14 21:37:30 -04:00
Rossen Stoyanchev 114b2b63b1 Check both connection and connected flag
Issue: SPR-14703
2016-09-14 17:26:13 -04:00
Juergen Hoeller 404e7cda7e Polishing 2016-09-13 23:31:09 +02:00
Juergen Hoeller b344c927bd Polishing
(cherry picked from commit 040d131)
2016-09-13 22:59:09 +02:00
Juergen Hoeller 883c3a6b4f Revised IllegalArgumentException handling for Formatter parse calls
Issue: SPR-14661
(cherry picked from commit 73bbe08)
2016-09-13 22:58:58 +02:00
Juergen Hoeller 68332bf240 Correct ISO DateTime example
Issue: SPR-14675
(cherry picked from commit db196ce)
2016-09-13 22:58:01 +02:00
Juergen Hoeller 53fc1e96c6 Avoid outdated Tibco workaround in shouldCommitAfterNoMessageReceived
Issue: SPR-14697
(cherry picked from commit 4396b21)
2016-09-13 22:57:39 +02:00
Juergen Hoeller 53dc996be8 PropertyValue stores source object in common superclass field
Issue: SPR-8337
(cherry picked from commit 367949e)
2016-09-13 22:57:29 +02:00
Juergen Hoeller 338a4a581e MappingJackson2MessageConverter adds message id and destination to type resolution exception
Issue: SPR-14672
(cherry picked from commit ae2bbe7)
2016-09-13 22:57:22 +02:00
Juergen Hoeller 1bde1ff263 Documentation updates around configuration classes
(cherry picked from commit efb5f17)
2016-09-01 13:00:13 +02:00
Juergen Hoeller 5f55add4bb ResolvableType.java.forRawClass(Class) supports isAssignableFrom(ResolvableType) as well
Issue: SPR-14648
(cherry picked from commit 086e764)
2016-08-31 15:30:12 +02:00
Juergen Hoeller a3b94eb17c Upgrade to Netty 4.0.41 2016-08-31 01:31:33 +02:00
Juergen Hoeller 458d49bdb8 Polishing
(cherry picked from commit acbb254)
2016-08-31 01:31:06 +02:00
Juergen Hoeller e76ed49513 CommonsMultipartResolver explicitly converts FileSizeLimitExceededException
Issue: SPR-14638
(cherry picked from commit 05f74b4)
2016-08-31 01:31:01 +02:00
Juergen Hoeller aa12288d50 Avoid collection lookups in StompCommand
Issue: SPR-14636
(cherry picked from commit 8e98177)
2016-08-31 01:30:55 +02:00
Rossen Stoyanchev cc33bfaf61 Support receipt on DISCONNECT with simple broker
Issue: SPR-14568
2016-08-29 18:32:33 -04:00
Rossen Stoyanchev 91387a5ae7 Harden synchronization around SockJS heartbeats
Create an explicit heartbeat task with an experiration flag so that
it can be cancelled reliably vs relying on the ScheduledFutureTask
cancel method which may return true even if the task is already
running.

Issue: SPR-14356
2016-08-29 14:17:27 -04:00
Juergen Hoeller 5b0722ed28 Polishing
(cherry picked from commit e828be9)
2016-08-26 18:10:43 +02:00
Juergen Hoeller 2adbfb6d02 Avoid getParameterType use with Oracle 12c driver by default
Issue: SPR-14629
Issue: SPR-14574
Issue: SPR-14191
(cherry picked from commit 52447ef)
2016-08-26 18:10:34 +02:00
Juergen Hoeller d03afeb296 Consistent use of Charset.forName over JDK 7 StandardCharsets in 4.x line
(cherry picked from commit 2a82b8f)
2016-08-26 18:10:27 +02:00
Juergen Hoeller f4037bf522 Polishing 2016-08-24 23:50:19 +02:00
Juergen Hoeller db037e490a Revised assertions in StompHeaderAccessor
Issue: SPR-14625
(cherry picked from commit c2feedb)
2016-08-24 23:49:22 +02:00
Juergen Hoeller 3811a595ed Avoid unnecessary String concatenation in StompSubProtocolHandler
Issue: SPR-14624
(cherry picked from commit 0735e9b)
2016-08-24 23:49:12 +02:00
Juergen Hoeller 2a9ca66cee Restored hard reference cache in TransactionAspectSupport for 4.2.8
Issue: SPR-14511
Issue: SPR-14609
2016-08-24 14:52:52 +02:00
Juergen Hoeller 081c3ac44f Polishing 2016-08-24 12:46:30 +02:00
Juergen Hoeller aac0e632ae Various @since tags (and varargs on setInterceptors) 2016-08-18 12:31:21 +02:00
Juergen Hoeller 96f1a0ecae Polishing 2016-08-18 10:50:56 +02:00
Juergen Hoeller 78049d3d25 Polishing 2016-08-17 22:26:03 +02:00
Juergen Hoeller f4d45ddbf7 Upgrade to EhCache 3.0.3 2016-08-17 21:13:39 +02:00
Juergen Hoeller e9f48a44f4 Removed duplicate NoHandlerFoundException entry
Issue: SPR-14598
2016-08-17 21:10:37 +02:00
Juergen Hoeller de91b1a8a0 Polishing
(cherry picked from commit b9a2d0a)
2016-08-17 21:10:17 +02:00
Juergen Hoeller 22ca7ac927 Polishing
(cherry picked from commit c926ec4)
2016-08-17 18:04:00 +02:00
Juergen Hoeller 264f5335a3 Polishing 2016-08-11 23:42:16 +02:00
Juergen Hoeller b2a0b75f7e Avoid stack overflow in case of chained factory-bean references to FactoryBean class
Issue: SPR-14551
(cherry picked from commit e23ac03)
2016-08-11 23:42:09 +02:00
Juergen Hoeller 41d2d2d270 Polishing 2016-08-10 17:09:27 +02:00
Juergen Hoeller 7b33cd6476 Polishing
(cherry picked from commit 67ba187)
2016-08-10 15:50:47 +02:00
Juergen Hoeller 349f2ad578 Consistent spelling for StandaloneMockMvcBuilder's addPlaceholderValue
(cherry picked from commit 67f0b19)
2016-08-10 15:50:42 +02:00
Juergen Hoeller 48980a247a MethodBasedEvaluationContext reliably exposes varargs
Issue: SPR-14554
(cherry picked from commit 4543a28)
2016-08-09 21:59:24 +02:00
Juergen Hoeller 9475c06eb5 Polishing 2016-08-09 12:29:15 +02:00
Juergen Hoeller 8c6cb3e59d Polishing
(cherry picked from commit 4627545)
2016-08-09 11:31:05 +02:00
Juergen Hoeller 8e0b7c408c Upgrade to Hibernate ORM 5.0.10 and Undertow 1.3.24 2016-08-09 11:30:59 +02:00
Rossen Stoyanchev c7daa4e94c Fix failing test 2016-08-08 21:43:42 -04:00
Rossen Stoyanchev 977b67e418 Protect sendHeartbeat from cancellation
Issue: SPR-14564
2016-08-08 17:33:57 -04:00
Juergen Hoeller 5c8573233a ConfigurationClassParser uses unified ImportStack with chained import analysis
Issue: SPR-14517
(cherry picked from commit d96a66a)
(cherry picked from commit ff878ea)
2016-07-28 00:33:09 +02:00
Juergen Hoeller 4e94e848c9 JndiPropertySource defensively skips invalid JNDI lookup for property name with colon in resource-ref mode
Issue: SPR-14518
(cherry picked from commit 7021a4b)
2016-07-28 00:33:01 +02:00
Juergen Hoeller f8abba0118 Upgrade to Netty 4.0.40 2016-07-27 17:05:26 +02:00
Juergen Hoeller 5f44d54d20 Polishing
(cherry picked from commit fbf3807)
2016-07-27 17:03:15 +02:00
Juergen Hoeller 0464363ac0 Isolated circular import detection for scanned configuration classes
Issue: SPR-14517
(cherry picked from commit 703c37e)
2016-07-27 17:02:53 +02:00
Juergen Hoeller fbc45ed7b6 Polishing 2016-07-27 12:51:24 +02:00
Juergen Hoeller 9789f00ad3 Fixed Quartz javadoc URL 2016-07-26 22:03:56 +02:00
Juergen Hoeller 74f64696b3 TransactionAspectSupport avoids hard references to transaction manager beans
Issue: SPR-14511
(cherry picked from commit 67176e2)
2016-07-26 21:49:17 +02:00
Juergen Hoeller 442f89bfbd Deprecate JpaSystemException(PersistenceException) constructor to prepare for removal in Spring 5
Issue: SPR-13827
(cherry picked from commit 9ee1dc7)
2016-07-26 01:32:33 +02:00
Juergen Hoeller 23135b19b3 Fixed ConcurrentMap declaration 2016-07-26 00:27:42 +02:00
Juergen Hoeller 29e8ba3efc Polishing
(cherry picked from commit cc93c2a)
2016-07-26 00:09:35 +02:00
Juergen Hoeller dadd2c3709 LinkedCaseInsensitiveMap properly overrides HashMap.clone()
Issue: SPR-14509
(cherry picked from commit 6459559)
2016-07-25 15:24:29 +02:00
Juergen Hoeller f1fc74c4ec ResourcePatternUtils.getResourcePatternResolver actually accepts null argument
Issue: SPR-14500
(cherry picked from commit 8ccfdbb)
2016-07-25 15:22:56 +02:00
Juergen Hoeller a39276addc Polishing 2016-07-20 23:22:06 +02:00
Juergen Hoeller b5127dc152 Polishing 2016-07-20 22:16:35 +02:00
Rossen Stoyanchev a9136d9638 Remove isAsyncStarted assertion
Issue: SPR-14444
2016-07-19 16:44:59 -04:00
Juergen Hoeller 5a479b8793 Upgrade to Netty 4.0.39 2016-07-15 23:01:41 +02:00
Juergen Hoeller 068186ca59 Polishing
(cherry picked from commit afe106e)
2016-07-15 23:01:20 +02:00
Juergen Hoeller 392f9c8deb Javadoc fixes and pruning of deprecated references
(cherry picked from commit 69dd40e)
2016-07-15 23:01:14 +02:00
Juergen Hoeller 3500bdce0a ConfigurationClassParser load annotations through source class loader
Issue: SPR-10343
(cherry picked from commit 9e93403)
2016-07-15 17:09:26 +02:00
Juergen Hoeller 4be5541c0e MessageHeaderAccessor properly removes header even in case of null value
Issue: SPR-14468
(cherry picked from commit 4ea5f07)
2016-07-15 17:09:13 +02:00
Juergen Hoeller 44152ce401 CronSequenceGenerator prevents stack overflow in case of inverted range
Issue: SPR-14462
(cherry picked from commit da59b4d)
2016-07-15 17:08:59 +02:00
Juergen Hoeller 97d73eb70c StandardTypeConverter initializes default ConversionService against volatile field
Issue: SPR-14465
(cherry picked from commit 0065a16)
2016-07-15 17:08:42 +02:00
Juergen Hoeller c627c408a0 Aspect actually applies in PersistenceExceptionTranslationPostProcessorTests
Issue: SPR-14457
(cherry picked from commit 52f46c7)
2016-07-15 17:08:27 +02:00
Juergen Hoeller e4179553b6 AbstractHandlerMethodMapping adds type+method info to getMappingForMethod exceptions
Issue: SPR-14452
(cherry picked from commit f0a826e)
2016-07-15 17:08:18 +02:00
Juergen Hoeller 82ca2011e3 Configurable UrlPathHelper in PathExtensionContentNegotiationStrategy
This commit also aligns ResourceUrlProvider's and RequestMappingInfo's UrlPathHelper setter/getter signatures.

Issue: SPR-14454
(cherry picked from commit 5c3c0f7)
2016-07-15 17:08:06 +02:00
Juergen Hoeller 482dd2cf37 Fixed typo: "occured"->"occurred"
(cherry picked from commit be0b71c)
2016-07-15 17:07:37 +02:00
Juergen Hoeller f51c90c1cc DigestUtils processes InputStream with buffered read instead of full copy
Issue: SPR-14427
(cherry picked from commit a1b58ee)
2016-07-15 17:07:25 +02:00
Juergen Hoeller b02744d42e Polishing
(cherry picked from commit e304290)
2016-07-15 17:07:12 +02:00
Juergen Hoeller 0445ce6c53 Polishing (backported from master)
(cherry picked from commit 92d78c1)
2016-07-06 17:35:30 +02:00
Juergen Hoeller 2e075baede Avoid canonicalName call for already-seen bean name
Issue: SPR-14433
(cherry picked from commit 52065a7)
2016-07-06 17:35:20 +02:00
Stephane Nicoll 7dbb1ca466 Upgrade copyright 2016-07-04 12:46:04 +02:00
Spring Buildmaster 4b5eedfeb4 Next Development Version 2016-07-04 10:26:51 +00:00
Juergen Hoeller a637213246 Aligned default Map capacity 2016-07-02 15:15:09 +02:00
Juergen Hoeller 6500018730 HtmlUnitRequestBuilder decodes request parameter names (backport)
Issue: SPR-14177
2016-07-02 14:08:24 +02:00
Juergen Hoeller fa624cd095 Avoid wrapping in plain RuntimeException in favor of IllegalStateException
(cherry picked from commit e5122d0)
2016-07-02 14:07:18 +02:00
Juergen Hoeller cd37873971 Avoid stateful MethodParameter nesting level changes in MVC processing
(cherry picked from commit e7a53e3)
2016-07-02 14:07:11 +02:00
Juergen Hoeller 4ddd9572f7 Leniently accept custom DeferredResult etc subclasses for null values
Issue: SPR-14423
(cherry picked from commit cfc560c)
2016-07-02 14:07:04 +02:00
Juergen Hoeller 3d106eb655 Upgrade to WebJars Locator 0.32 2016-07-01 15:51:40 +02:00
Juergen Hoeller 3dad61fbbf Backported applicable beans chapter revisions 2016-07-01 15:40:45 +02:00
Stephane Nicoll d73f91eaf0 Polish
Closes gh-1097
(cherry picked from commit 037746d)
2016-07-01 15:40:06 +02:00
Juergen Hoeller db4882cea4 Polishing 2016-06-30 21:45:55 +02:00
Juergen Hoeller 833ed7168e Add missing package-info files for common packages
Issue: SPR-14420
(cherry picked from commit 66ec1c1)
2016-06-30 21:43:29 +02:00
Juergen Hoeller 09c7194c78 Polishing
(cherry picked from commit 232cfe5)
2016-06-30 14:16:20 +02:00
Juergen Hoeller a63247b281 Polishing 2016-06-29 16:07:03 +02:00
Juergen Hoeller dd7ddc08ff Polishing 2016-06-29 14:48:09 +02:00
Stephane Nicoll 3564616b7f Align caching AspectJ configuration
The `CacheResolver` and `ErrorHandler` features introduced in 4.1 were
not properly enabled in AspectJ mode. This commit adds more tests from
the regular proxy-based mode and align the AspectJ caching configuration.

Issue: SPR-14413
(cherry picked from commit 6cd85dd)
2016-06-29 14:47:39 +02:00
Juergen Hoeller 07c9c55fd3 PayloadArgumentResolver's MessageConversionException includes original payload type
Issue: SPR-14394
(cherry picked from commit f5282bc)
2016-06-29 14:47:20 +02:00
Juergen Hoeller 0d3a22c487 Avoid potential deadlock in AbstractBeanFactoryPointcutAdvisor
Issue: SPR-14388
(cherry picked from commit fd9d518)
2016-06-29 14:46:41 +02:00
Juergen Hoeller f19599884d Fixed ambiguous sentence in conditional cache documentation
Issue: SPR-14399
(cherry picked from commit 4102c62)
2016-06-29 14:46:23 +02:00
Juergen Hoeller f60c6c90c1 Upgrade to CGLIB 3.2.4
Issue: SPR-14385
2016-06-29 14:46:15 +02:00
Rossen Stoyanchev 269742589b Improve static resource path check 2016-06-28 16:50:32 -04:00
Rossen Stoyanchev 4c87167c98 Add heartbeat lock to SockJS server sessions
Even before this change SockJS sessions always cancelled the heartbeat
task first prior to sending messages. However when the heartbeat task
is already in progress, cancellation of it is not enough and we must
wait until the heartbeat is sent.

This commit adds a heartbeat write lock which is obtained and held
during the sending of a heartbeat. Now when sessions send a message
they still cancel the heartbeat task but if that fails they also wait
for the heartbeat write lock.

Issue: SPR-14356
2016-06-17 17:10:49 -04:00
Juergen Hoeller 71df9cef80 ObjectUtils.nullSafeEquals allows for JVM method inlining (through reducing its bytecode size)
Issue: SPR-14349
(cherry picked from commit ca12e13)
2016-06-09 22:42:05 +02:00
Juergen Hoeller 3680ec5a0d Polishing 2016-06-09 17:21:23 +02:00
Juergen Hoeller f9e8924b3d Consistent processing of empty values and catching of RuntimeExceptions for Formatters
Issue: SPR-14345
(cherry picked from commit d51c22a)
2016-06-09 10:59:13 +02:00
Juergen Hoeller 367e663730 Assertions for error codes in case of formatting failures
Issue: SPR-14345
(cherry picked from commit c6f63bd)
2016-06-08 16:26:48 +02:00
Juergen Hoeller 9ac661df82 Polishing 2016-06-08 14:13:22 +02:00
Juergen Hoeller 57aa2afaa0 Upgrade to Jackson 2.6.7 and Netty 4.0.37 2016-06-08 10:06:26 +02:00
Juergen Hoeller c349ac9d42 Upgrade to Groovy 2.4.7
(cherry picked from commit f5a9d5e)
2016-06-07 18:10:02 +02:00
Juergen Hoeller 7001707028 CorsFilter asserts presence of CorsConfigurationSource
(cherry picked from commit 31aed61)
2016-06-07 16:50:24 +02:00
Juergen Hoeller 9a41774364 Fixed @since references after SPR-14080 backport
Issue: SPR-14305
2016-06-07 13:35:19 +02:00
Juergen Hoeller d0b2fe5e8c Allow JAXB to be registered next to plain Jackson
Issue: SPR-14336
(cherry picked from commit abcfffd)
2016-06-07 13:30:11 +02:00
Juergen Hoeller e9ba64ae49 Upgrade to EhCache 3.0.2 and Castor 1.4.1
(cherry picked from commit 3c987b1)
2016-06-06 22:23:39 +02:00
Juergen Hoeller 47c62fd173 Synchronized access to method overrides (in particular for @Lookup)
Issue: SPR-14333
(cherry picked from commit 9131ebb)
2016-06-06 17:45:21 +02:00
Juergen Hoeller 24b3525f8d Upgrade to Undertow 1.3.23 2016-06-04 11:20:21 +02:00
Juergen Hoeller e219576414 Defensive catching of any Throwable subclasses instead of just Error
Issue: SPR-14329
Issue: SPR-14323
(cherry picked from commit a9fda3e)
2016-06-04 00:27:24 +02:00
Juergen Hoeller 2fd691b340 EventListenerMethodProcessor defensively handles unresolvable method signatures
Issue: SPR-14330
(cherry picked from commit f657952)
2016-06-04 00:22:46 +02:00
Juergen Hoeller d467dc2a05 Avoid double getFlushMode call 2016-06-04 00:20:46 +02:00
Juergen Hoeller 24b9e3a0be Latest applicable dependency updates (Commons FileUpload 1.3.2, Tomcat 8.0.35, HSQLDB 2.3.4, H2 1.4.192) 2016-06-02 17:14:29 +02:00
Juergen Hoeller f36070b560 Polishing
(cherry picked from commit 521c41d)
2016-06-02 17:14:07 +02:00
Juergen Hoeller 899131997e Less restrictive CORS origin comparison
UriComponentsBuilder allows more efficient (and less restrictive) CORS
origin comparison.

Also introduces a specifically narrowed cloneBuilder() method for
UriComponentsBuilders.

Cherry-picked from 9a52c8.

Issue: SPR-14080
2016-05-31 12:25:16 -04:00
Juergen Hoeller a27200e753 Polishing 2016-05-31 13:27:34 +02:00
Juergen Hoeller 933bbf2de9 AbstractBeanFactory.markBeanAsCreated() reliably clears merged bean definition only once
Issue: SPR-14269
(cherry picked from commit 9064d38)
2016-05-31 13:26:33 +02:00
Juergen Hoeller 1d0c305a25 BeanWrapper avoids StringIndexOutOfBoundsException for incompletely quoted keys
Issue: SPR-14293
(cherry picked from commit cf0a0cd)
2016-05-31 13:22:44 +02:00
Juergen Hoeller 62199e82ef ConfigurationClassParser detects @Bean methods in interface hierarchies as well
Issue: SPR-14288
(cherry picked from commit 03affa0)
2016-05-31 13:22:29 +02:00
Juergen Hoeller 7de2976c1e Consistent meta-annotation attributes lookup through ASM
Issue: SPR-14257
(cherry picked from commit 24f5f36)
2016-05-31 13:22:21 +02:00
Juergen Hoeller cc7758869c SettableListenableFuture properly rethrows Error
Issue: SPR-14298
(cherry picked from commit a979885)
2016-05-31 13:22:16 +02:00
Juergen Hoeller f64ed69280 ServletServerHttpRequest.getHeaders() ignores invalid content type
Issue: SPR-14309
(cherry picked from commit f7f2327)
2016-05-31 13:21:46 +02:00
Juergen Hoeller 07b5763324 SpringTilesContainerFactory uses Tiles 3's createDecoratedContainer
Issue: SPR-14311
(cherry picked from commit 2d85acc)
2016-05-31 13:21:38 +02:00
Juergen Hoeller 7b73f23f43 For attribute is not actually required
Issue: SPR-14287
(cherry picked from commit dacc31e)
2016-05-31 13:21:06 +02:00
Juergen Hoeller a0a2a3337a @Bean's "autowire" attribute does not affect annotation-driven autowiring
Issue: SPR-14282
(cherry picked from commit 98eaf05)
2016-05-31 13:21:00 +02:00
Juergen Hoeller ad29db8675 Reference documentation updates
Issue: SPR-14087
Issue: SPR-14272
Issue: SPR-13535
Issue: SPR-13843
Issue: SPR-14164
Issue: SPR-14319
2016-05-31 13:20:33 +02:00
Juergen Hoeller a2088c38ad Latest applicable dependency updates (Joda-Time 2.9.4, Jetty 9.3.9, EhCache 3.0.1) 2016-05-31 13:19:52 +02:00
Rossen Stoyanchev 28321946bf Remove unnecessary assertion
Issue: SPR-14279
2016-05-22 06:23:57 -04:00
Rossen Stoyanchev b5022108c7 Fix STOMP connect failure related memory leak
Normally heartbeats keep connections from hanging. However in some
cases a connection may hang before a CONNECTED frame is received
and heartbeats are put in place. This commit adds a change to enforce
a 60 limit on receiving the CONNECTED frame.

Issue: SPR-14266
2016-05-13 07:47:11 -04:00
Spring Buildmaster 6eba220d1b Next Development Version 2016-05-06 07:56:13 +00:00
Juergen Hoeller 5fc0d43852 AsyncResult properly propagates execution exception
Issue: SPR-14249
(cherry picked from commit 1b1aac9)
2016-05-05 20:57:42 +02:00
Juergen Hoeller 2dbc8b0381 Latest applicable dependency updates (EhCache 2.10.2, JRuby 1.7.25, Quartz 2.2.3, Undertow 1.3.22) 2016-05-04 18:44:11 +02:00
Juergen Hoeller 0f2bc3f6bf AbstractRequestLoggingFilter ignores non-available query string
Issue: SPR-14244
(cherry picked from commit 08ddd1b)
2016-05-04 18:44:04 +02:00
Juergen Hoeller 1e491f11d7 Polishing
(cherry picked from commit 8c139ef)
2016-05-04 18:43:59 +02:00
Juergen Hoeller 68cdd5d358 LazySingletonAspectInstanceFactoryDecorator uses shared singleton mutex
Issue: SPR-14241
2016-05-04 09:13:09 +02:00
Juergen Hoeller bf3dee9492 Polishing 2016-05-03 18:47:33 +02:00
Juergen Hoeller a6563a3263 Explicit note on Java deserialization
(cherry picked from commit 76964e1)
2016-05-03 18:46:40 +02:00
Juergen Hoeller 0589c1b4b5 Warn about non-static BeanDefinitionRegistryPostProcessor declarations on @Configuration classes
Issue: SPR-14234
(cherry picked from commit 7737c3c)
2016-05-02 15:20:15 +02:00
Juergen Hoeller 85675fbe2e Consistent SmartLifecycle implementations
Issue: SPR-14233
(cherry picked from commit f83cbff)
2016-05-02 14:07:32 +02:00
Juergen Hoeller 85faeef816 DefaultMessageListenerContainer immediately invokes stop callback when not running
Issue: SPR-14233
(cherry picked from commit e45d33f)
2016-05-02 14:07:25 +02:00
Juergen Hoeller d49ecab89a Polishing 2016-04-29 11:12:20 +02:00
Rossen Stoyanchev f7ace54488 Ensure Environment.shutdown() in Reactor2TcpClient
Issue: SPR-14229
2016-04-28 17:48:38 -04:00
Rossen Stoyanchev d48eeb2c84 Reactor2TcpClient cleans up TcpClient instances
Issue: SPR-14231
2016-04-28 15:48:13 -04:00
Rossen Stoyanchev a3da6b186f Upgrade to Reactor 2.0.8
(cherry picked from commit 6e4e52b)
2016-04-27 21:57:16 +02:00
Juergen Hoeller d66186a90b Polishing
(cherry picked from commit 8ddb432)
2016-04-27 21:42:01 +02:00
Juergen Hoeller 75a8f5b3ca ApplicationListenerDetector explicitly prevents serialization of its ApplicationContext reference
Issue: SPR-14214
(cherry picked from commit e0734ae)
2016-04-27 21:41:55 +02:00
Juergen Hoeller 6a3d4940b5 SpringServletContainerInitializer does not log WebApplicationInitializer class names
Issue: SPR-14213
(cherry picked from commit f73df2e)
2016-04-27 21:41:44 +02:00
Juergen Hoeller 002d6d70a5 SocketUtils considers port range including maxPort
Issue: SPR-14211
(cherry picked from commit bf7b475)
2016-04-27 21:41:36 +02:00
Juergen Hoeller b9fa67e0e6 FastByteArrayInputStream returns correct count from read(byte[])
Issue: SPR-14209
(cherry picked from commit 9bf5a5c)
2016-04-27 21:41:30 +02:00
Rossen Stoyanchev 9fa061431c XML config properly initialize WS message broker stats
Issue: SPR-14190
2016-04-26 17:24:48 -04:00
Rossen Stoyanchev 6314df367c Update spring-mvc-3.2.xsd
The backport in commit cf39078 changed the spring-mvc-3.2.xsd.
This change updates the same in the 4.2.x branch.

Issue: SPR-14186
2016-04-21 14:07:27 -04:00
Venil Noronha e67a274b32 Remove isOpen assertion when sending WebSocket message
Issue: SPR-14138
2016-04-18 09:45:01 -04:00
Venil Noronha 2eab3df4d1 Delegate sendMessage
Issue: SPR-14139
2016-04-18 09:29:33 -04:00
Juergen Hoeller e205a1b30a Upgrade to EhCache 3.0 GA
Issue: SPR-14185
2016-04-18 14:43:05 +02:00
Juergen Hoeller 4be22c4938 Consistent public constructors in ast package
Issue: SPR-14181
(cherry picked from commit e38bfb1)
2016-04-15 22:30:36 +02:00
Rob Winch 9438c41853 Add --no-daemon to Gradle import
Previously using the Gradle Daemon with import eclipse scripts would cause
issues with the merge plugin. Specifically, projects would randomly not
be associated to the classpath.

This change explicitly adds --no-daemon in the import scripts to ensure
that the problem does not occur.

Issue SPR-14102
(cherry picked from commit 970dc4a)
2016-04-15 22:30:11 +02:00
Rob Winch 0075240d8f Change Eclipse Settings to allow forbidden references
Spring uses lots of forbidden references. The current Eclipse settings
set forbiddenReference=error This was not ideal because there were lots of
errors in the workspace.

This commit changes forbiddenReference=warning since we nee to allow
forbidden references.
(cherry picked from commit 6489a76)
2016-04-15 22:30:03 +02:00
Juergen Hoeller f83e149f8a Strong Hibernate 5.1 recommendation
Issue: SPR-13480
Issue: SPR-14176
(cherry picked from commit 44a9c49)
2016-04-15 12:11:25 +02:00
Juergen Hoeller 4c41b9d4b9 Polishing
(cherry picked from commit 3b44c47)
2016-04-14 16:41:39 +02:00
Juergen Hoeller 1d39c97def Downgrade to Protobuf Java Format 1.2
Issue: SPR-14171
2016-04-14 15:54:52 +02:00
Juergen Hoeller fd954ef1d6 Upgrade to Jackson 2.6.6 and Protobuf Java Format 1.4 2016-04-14 14:48:57 +02:00
Juergen Hoeller 334b4a99b0 Jackson-based message converters consistently check media type first
Issue: SPR-14163
2016-04-14 14:22:23 +02:00
Juergen Hoeller 416a24c6bc Avoid unnecessary GenericHttpMessageConverter re-declaration
(cherry picked from commit 96875fe)
2016-04-13 19:02:52 +02:00
Juergen Hoeller 7f438dc9aa Consistent headers.getContentLength() checks 2016-04-13 18:44:56 +02:00
Juergen Hoeller bf3cadb908 AbstractJackson2HttpMessageConverter's canRead/canWrite checks media type first before delegating to Jackson
Issue: SPR-14163
(cherry picked from commit e366746)
2016-04-13 18:44:13 +02:00
Juergen Hoeller 863bae7d86 Drop outdated support for building on JDK 9 (not compatible with JDK 9 b111+) 2016-04-13 13:58:34 +02:00
Juergen Hoeller 09b7735b0f Polishing 2016-04-13 13:33:39 +02:00
Juergen Hoeller e6ae437038 Latest dependency updates (AspectJ 1.8.9, Rhino 1.7.7.1, WebJars Locator 0.30) 2016-04-13 13:13:11 +02:00
Juergen Hoeller b1c70729c2 Polishing 2016-04-12 23:33:58 +02:00
Juergen Hoeller 33dcef3583 SpringCacheAnnotationParser properly accepts empty @Caching annotation
Issue: SPR-14162
(cherry picked from commit da11261)
2016-04-12 23:32:42 +02:00
Juergen Hoeller 3829a77894 Polishing
(cherry picked from commit 74608e6)
2016-04-12 16:09:48 +02:00
Juergen Hoeller e9382b2c0b SimpleTransactionScope properly suspends and resumes scoped objects
Issue: SPR-14148
(cherry picked from commit 831f09c)
2016-04-12 16:09:43 +02:00
Stephane Nicoll e5477ea19d Add interface-based detection test
Add a test that explicitely validates that `@ManagedResource` and friends
can be set on an interface.

Issue: SPR-13138
(cherry picked from commit eb49f3c)
2016-04-11 22:07:52 +02:00
Juergen Hoeller b7890ca28e Consistent license header
(cherry picked from commit 537193a)
2016-04-11 21:14:05 +02:00
Juergen Hoeller b9fd8586ff Fixed XML example for setup of scheduled tasks
Issue: SPR-14145
(cherry picked from commit 550a320)
2016-04-11 20:52:54 +02:00
Juergen Hoeller e0642c77c3 HttpHeaders consistently ignores invalid date header values
Issue: SPR-14144
(cherry picked from commit 448621a)
2016-04-11 20:52:43 +02:00
Juergen Hoeller d303ac94dc Polishing 2016-04-11 12:22:37 +02:00
Juergen Hoeller 053ebb180e Polishing 2016-04-10 12:37:55 +02:00
Juergen Hoeller 2b6ec6a85e Upgrade to CGLIB 3.2.2
Issue: SPR-13934
(cherry picked from commit dc7ec44)
2016-04-09 23:13:30 +02:00
Juergen Hoeller aa5c12c534 Polishing 2016-04-08 22:52:36 +02:00
Stephane Nicoll 67a65ea600 Support Quartz trigger without JobDetail
This commit allows to create a Quartz trigger implementation via
either `CronTriggerFactoryBean` or `SimpleTriggerFactoryBean` even if no
job detail is provided.

Issue: SPR-13604
(cherry picked from commit 2970065)
2016-04-08 22:52:29 +02:00
Rossen Stoyanchev 35f0fce2ae Remove section on spring-framework-contrib group 2016-04-08 15:44:22 -04:00
Juergen Hoeller 9c30a1f8df Latest dependency updates (EhCache 3.0 RC3, Undertow 1.3.21)
(cherry picked from commit e365ffb)
2016-04-08 16:51:18 +02:00
Juergen Hoeller 0864834077 Cleanup of remaining direct BeanWrapper usage
Issue: SPR-14121
(cherry picked from commit 157dcab)
2016-04-07 14:52:03 +02:00
Juergen Hoeller 7659101843 BeanDefinitionBuilder keeps providing addConstructorArg(Object) for Spring Security 2.x compatibility
Issue: SPR-14123
(cherry picked from commit 4ea4257)
2016-04-07 14:51:57 +02:00
Juergen Hoeller 5f9113678f Consistent use of LinkedHashMap in StaticListableBeanFactory 2016-04-05 15:57:05 +02:00
Juergen Hoeller 51f356f518 Quartz ResourceLoaderClassLoadHelper explicitly falls back to classpath lookup
Issue: SPR-13706
(cherry picked from commit 6db6f23)
2016-04-05 12:23:44 +02:00
Juergen Hoeller 0ecbeafd2b Polishing
(cherry picked from commit d2d528d)
2016-04-05 11:42:17 +02:00
Juergen Hoeller 6b0f26c335 StatementCreatorUtils handles Types.BOOLEAN through PreparedStatement.setBoolean
Issue: SPR-14116
(cherry picked from commit 797f5db)
2016-04-05 11:40:50 +02:00
Juergen Hoeller 2166f2060f Latest applicable dependency updates (AspectJ 1.8.9, EhCache 3.0 RC2, Hibernate 5.0.9, Joda-Time 2.9.3, Netty 4.0.36, SLF4J 1.7.21, Tomcat 8.0.33, Undertow 1.3.20, Woodstox 5.0.2) 2016-04-05 11:38:51 +02:00
Rossen Stoyanchev 000a0a0006 Call resetRequest after writeFrame for polling sessions
Previous refactoring (fcf6ae and also 43d937) in the SockJsSession
hierarchy consolidated access to the request and response in the
base class AbstractHttpSockJsSession in order to keep synchronization
concerns there. However that also unintentionally removed the call to
resetRequest() after sending a heartbeat for any of the
PollingSockJsSession classes. In general a polling session should call
resetRequest after every frame written.

This commit brings back the writeFrame override in PollingSockJsSession
with an extra call to resetRequest().

Issue: SPR-14107
2016-04-04 19:30:33 -04:00
Juergen Hoeller 6d479b2060 Polishing 2016-04-04 20:59:40 +02:00
Stephane Nicoll 9443c1c5dd Fix Auto-Startup for @JmsListener
Ignore container's auto-startup once the context is refreshed.

Issue: SPR-14015
(cherry picked from commit 996c1cc)
2016-04-04 20:59:33 +02:00
Rossen Stoyanchev 01d50e9bde Fix incomplete log message
Commit 48236b from 2014 introduced a logging improvement to avoid
logging each removed session per line and instead log one line at
the end with all removed sessions ids. However that list of removed
session ids wasn't populated. This commit fixes that.

Issue: SPR-14111
2016-04-04 14:02:23 -04:00
Juergen Hoeller d7fe92d022 Abstract(Stax)XMLReader recognizes standard features as not supported
Issue: SPR-14056
(cherry picked from commit 35eb52e)
2016-04-04 15:10:08 +02:00
Juergen Hoeller 3b7ca7e76a Further tests for getBeanNamesForType(ResolvableType)
Issue: SPR-14097
(cherry picked from commit edea66a)
2016-04-04 15:10:02 +02:00
Juergen Hoeller dc6e512275 EhCacheManagerFactoryBean logs cache manager name
Issue: SPR-14110
(cherry picked from commit 8bfba6a)
2016-04-04 15:09:57 +02:00
Juergen Hoeller 0ed7f9aebb SimpleApplicationEventMulticaster leniently handles ClassCastException
Issue: SPR-14109
(cherry picked from commit 13f889e)
2016-04-04 15:09:52 +02:00
Juergen Hoeller 02a6f31807 ASM ClassReader leniently handles label offset mismatch
Issue: SPR-14089
(cherry picked from commit 3910350)
2016-03-30 10:46:45 +02:00
Juergen Hoeller 8f6ede519d RequestHeaderMapMethodArgumentResolver defensively checks for non-existing header values
Issue: SPR-14091
(cherry picked from commit b2a17ba)
2016-03-30 10:46:33 +02:00
Juergen Hoeller 756301b7c5 Polishing
(cherry picked from commit 94cb778)
2016-03-25 23:38:23 +01:00
Juergen Hoeller ccaa504378 Polishing
(cherry picked from commit 775bccc)
2016-03-24 21:47:56 +01:00
Juergen Hoeller 0891fbaf97 Consistent formatting 2016-03-24 19:54:28 +01:00
Juergen Hoeller 2ea7fcde3e Polishing
(cherry picked from commit 9af12d2)
2016-03-24 17:17:58 +01:00
Juergen Hoeller 7c5aac122a Restored lazy resolution of default executor for AsyncAnnotationBeanPostProcessor
Issue: SPR-14030
(cherry picked from commit 155fa37)
2016-03-24 17:17:52 +01:00
Juergen Hoeller 05ab769555 Bsh/GroovyScriptFactory reset script cache in case of compilation error
Issue: SPR-14007
(cherry picked from commit 0597ff1)
2016-03-24 17:17:10 +01:00
Juergen Hoeller a19be754c8 DefaultCorsProcessor checks for existing CORS response before attempting to compare origin
Issue: SPR-14080
(cherry picked from commit abe7345)
2016-03-24 17:17:04 +01:00
Juergen Hoeller 8994498b44 Revised newline handling tests pass on Windows now
Issue: SPR-13503
(cherry picked from commit 311d4c9)
2016-03-24 17:16:52 +01:00
Juergen Hoeller fcd155a92c Correct RFC 4648 references in method-level javadoc
Issue: SPR-14067
(cherry picked from commit ec7c3aa)
2016-03-24 17:16:41 +01:00
Juergen Hoeller bfe8d15e97 Removed invalid quoting of message arguments from MessageSource examples
Issue: SPR-14003
(cherry picked from commit 100f3c5)
2016-03-24 17:16:33 +01:00
Juergen Hoeller a5904efbde Upgrade to XStream 1.4.9
Issue: SPR-14084
(cherry picked from commit 7e4563a)
2016-03-24 17:16:24 +01:00
Brian Clozel ed34ea4876 Reset Expires HTTP header when caching configured
Just like SPR-13252 addressed this issue for the "Pragma" header, this
issue resets the HTTP 1.0 "Expires" header.
When such a header has been set (by a filter, for example) and HTTP
caching has been configured at the WebContentGenerator, this header
value is reset to "". In this case, "Cache-Control" and "Expires" might
have inconsistent values and we consider that the HTTP caching
configuration should take precedence.

Depending on the servlet container chosen to deploy the application,
this might result in empty "" header values or no header set at all.

Issue: SPR-14053
Cherry picked from 15fe8279e6
2016-03-23 16:35:53 +01:00
Kazuki Shimizu 2267b14055 Add newline at the beginning of textarea macro for FreeMarker and Velocity
Issue: SPR-13503
Cherry-picked from 9b2023111d
2016-03-23 11:56:28 +01:00
Stephane Nicoll 0c8a40bdbc Fix escaping of #
This commit disables the "quotes" substitutions on specific XML
examples that require to use the reserved `#` character.

Issue: SPR-14074
2016-03-21 12:51:40 +01:00
Rossen Stoyanchev d7062f6291 Ensure RedirectModel is initialized
This commit fixes an old bug in ModelAndViewContainer where getModel
returns a new ModelMap instance that isn't saved and re-used.

Issue: SPR-14045
2016-03-14 23:04:58 -04:00
Stephane Nicoll bd82acbf99 Support ResolvableTypeProvider on simple event pojo
Previously, the generic type of a simple pojo event implementing
ResolvableTypeProvider wasn't detected properly. This commit fixes the
logic when the generic type is not provided to reuse what
PayloadApplicationEvent is already doing anyway.

Issue: SPR-14029
2016-03-10 09:51:43 +01:00
Brian Clozel f76b38c506 Fix SpringUrl Velocity macro URI encoding
Prior to this commit, the springUrl Velocity macro would only prepend
the context to the given URL; this means that the
ServletHttpResponse.encodeUri method is not called and neither the
ResourceUrlProvider.

This commit changes this macro to use RequestContext.getContextUrl which
prepends the context and encodes the URI.

Issue: SPR-14027
Cherry-picked from 0a56667093
2016-03-08 18:01:29 +01:00
Brian Clozel b88c39955b Add newline at the beginning of textarea JSP tags
This commit adds a newline char at the beginning of textarea tags
values. As per the HTML 4.01 spec (and browsers behavior), a line break
following a start tag is ignored.

This can lead to Spring's textarea tag to ignore a line break char at
the beginning of a tag value.

See https://www.w3.org/TR/html401/appendix/notes.html#notes-line-breaks

Issue: SPR-13503
Cherry picked from 44c32128
2016-03-03 16:52:16 +01:00
Brian Clozel 0ef90df120 Relax SPR-13867 changes for ResourceHttpRequestHandler
Prior to this change, SPR-13867 made sure that any class extending
WebContentGenerator would not overwrite existing HTTP "Cache-Control"
response headers - set by a filter, a Controller handler, etc.

This caused issues with resource handling, since specifying a cache
configuration there would not overwrite default headers set by filters,
for example by Spring Security.

This commit restricts the previous changes to the
RequestMappingHandlerAdapter, in order to avoid overwriting header set
by a filter or a Controller handler in those cases.

Issue: SPR-14005
Cherry-picked from 50bcd67fb6
2016-03-02 17:45:50 +01:00
Juergen Hoeller 8a44560d82 RequestMappingHandlerAdapter properly invokes handler method in case of no session as well
Issue: SPR-13999
(cherry picked from commit a02fd7c)
2016-02-29 15:08:00 +01:00
Juergen Hoeller 0349abc565 RequestMappingHandlerAdapter properly invokes handler method in synchronizeOnSession mode again
Issue: SPR-13999
(cherry picked from commit 1815a6a)
2016-02-29 11:46:16 +01:00
Juergen Hoeller 9129ec2623 LinkedCaseInsensitiveMap provides reliable getOrDefault implementation
Issue: SPR-13981
(cherry picked from commit 7a32ce3)
2016-02-29 11:42:43 +01:00
Spring Buildmaster 2cbc5ff0c8 Next Development Version 2016-02-25 01:36:20 -08:00
Juergen Hoeller cafb99a33d Polishing
(cherry picked from commit 028a690)
2016-02-24 17:59:15 +01:00
Juergen Hoeller 9c5cabf4ba Refined ApplicationContextInitializer assignability exception
(cherry picked from commit ca19920)
2016-02-24 17:58:29 +01:00
Juergen Hoeller 97b017781a TimerScheduledFuture correctly calculates getDelay result
Issue: SPR-13977
(cherry picked from commit a68b910)
2016-02-24 17:56:30 +01:00
Juergen Hoeller 9f2b3ca8b8 Polishing
(cherry picked from commit 1899fb3)
2016-02-23 00:05:44 +01:00
Juergen Hoeller 3f795e64c6 Avoid NPE in case of @Lazy @Autowired(required=false)
Issue: SPR-13967
(cherry picked from commit b9fe6d8)
2016-02-23 00:05:17 +01:00
Juergen Hoeller 99dc7769a6 Latest dependency updates (EhCache 3.0 M5, Groovy 2.4.6, Gson 2.6.1, Hibernate ORM 5.0.8, Hibernate Validator 5.2.4, SLF4J 1.7.16, SnakeYAML 1.17, Undertow 1.3.18) 2016-02-23 00:04:49 +01:00
Juergen Hoeller a620770470 Polishing 2016-02-19 16:02:25 +01:00
Juergen Hoeller 167ba8387a ScriptUtils.executeSqlScript logs SQLWarnings at debug level
Issue: SPR-13959
(cherry picked from commit 9235345)
2016-02-19 15:59:47 +01:00
Juergen Hoeller 4320161172 Shared EntityManager Query unwrapping before passing it to addNamedQuery
Issue: SPR-13957
(cherry picked from commit 7fcb277)
2016-02-19 15:59:24 +01:00
Juergen Hoeller 659e44146c Consistent equals implementations across class hierarchies
Issue: SPR-13951
(cherry picked from commit ac44f9e)
2016-02-19 15:56:36 +01:00
Juergen Hoeller 08f2ab942c DefaultMessageListenerContainer stops if recovery failed after interrupt signal
Issue: SPR-11787
(cherry picked from commit 1253b45)
2016-02-19 15:54:52 +01:00
Juergen Hoeller d2b9dbf181 BeanMethodInterceptor does not pass on null arguments for singleton beans
Issue: SPR-13887
(cherry picked from commit 5ed9046)
2016-02-19 15:54:26 +01:00
Sebastien Deleuze 09db26af2b Improve Jackson 2.7 compatibility
This commit introduces a conditional call in
AbstractJackson2HttpMessageConverter#getJavaType() in order to avoid
calling TypeFactory#constructType() with a null contextClass parameter,
since this is not supported by Jackson 2.7 anymore.

It allows to use Spring Framework 4.2.x with Jackson 2.7.1+ for most use
cases, but with some limitations. For example, with Jackson 2.7
TypeVariable resolution from method parameters does not work.

As a consequence, after this commit Spring Framework 4.2.x still fully
supports Jackson up to version 2.6, but improves Jackson 2.7 compatibility.
Full support for Jackson 2.7 is provided as of Spring Framework 4.3.x.

Issue: SPR-13853
2016-02-11 13:45:49 +01:00
Juergen Hoeller 19c5462b13 Polishing 2016-02-10 20:48:10 +01:00
Juergen Hoeller 5047e90625 AbstractMarshaller defensively uses DocumentBuilderFactory within synchronized block
Issue: SPR-13935
(cherry picked from commit f61b998)
2016-02-10 20:47:54 +01:00
Juergen Hoeller cf3e460a8b ReflectiveMethodResolver lets local static methods override java.lang.Class methods
Issue: SPR-13918
(cherry picked from commit 43bcab9)
2016-02-10 20:47:41 +01:00
Juergen Hoeller c960d9733d DisposableBeanAdapter ignores bridge method conflicts
Issue: SPR-13922
(cherry picked from commit 903ae48)
2016-02-10 20:47:31 +01:00
Juergen Hoeller 9e7f6ba0b1 PathMatchingResourcePatternResolver consistently logs retrieval results
Issue: SPR-13923
(cherry picked from commit 449f704)
2016-02-10 20:47:24 +01:00
Juergen Hoeller d8a7b6f0f8 Latest dependency updates (Hibernate Validator 5.2.3, Joda-Time 2.9.2, OkHttp 2.7.4, SLF4J 1.7.15, Netty 4.0.34, Tomcat 8.0.32, Undertow 1.3.17) 2016-02-10 20:40:18 +01:00
Rossen Stoyanchev 6ef2d827c6 Reduce log level for @ExceptionHandler failure
Issue: SPR-13932
2016-02-09 12:58:08 -05:00
Rossen Stoyanchev b1a46ccbd9 Fix NPE in InvocableHandlerMethod
Issue: SPR-13917
2016-02-04 23:33:04 -05:00
Rossen Stoyanchev f053cdec51 Improve close in ConcurrentWebSocketSessionDecorator
Before this commit the concurrent session wrapper mainly protected the
sending of messages. The close itself however may also cause a message
to be sent as is the case of the SockJS protocol.

This change protects the close and checks if the session has exceeded
send time or buffer limits in which case the close status is changed
to SESSION_NOT_RELIABLE (introduced in commit cbd5af3a) which in turn
signals that extra care should be exercised when closing the session.

Issue: SPR-13904
2016-02-04 17:22:36 -05:00
Rossen Stoyanchev 39c05c56c4 BufferedImage converter writes Content-Type again
Issue: SPR-13906
2016-02-04 15:01:13 -05:00
Juergen Hoeller 4418331429 Polishing
(cherry picked from commit e903106)
2016-02-04 20:50:21 +01:00
Juergen Hoeller e48315549e AbstractXlsView does not explicitly flush (for compatibility with WebSphere Liberty)
Issue: SPR-13910
(cherry picked from commit 28e8af2)
2016-02-04 20:49:48 +01:00
Sam Brannen 484dd96606 Throw exception if TxMgr cannot be retrieved for @Transactional test
Prior to this commit, a @Transactional integration test would silently
be executed without a transaction if the transaction manager could not
be retrieved from the application context -- for example, it no such
bean was defined or if multiple beans were present but none satisfied
the qualifier.

This commit addresses this issue by throwing an IllegalStateException
if the PlatformTransactionManager cannot be retrieved for a
@Transactional test.

Issue: SPR-13895
(cherry picked from commit 6d2b9a0136)
2016-02-03 18:18:55 +01:00
Juergen Hoeller bb12e0ea70 Latest dependency updates (AspectJ 1.8.8, Hibernate ORM 5.0.7, Jackson 2.6.5, Jetty 9.3.7, Undertow 1.3.14, SLF4J 1.7.14) 2016-01-26 22:25:22 +01:00
Juergen Hoeller 30ef893c28 Polishing 2016-01-26 22:23:56 +01:00
Juergen Hoeller a58eee6ad1 RequestParamMethodArgumentResolver defensively handles MethodParameter nesting level and java.util.Optional access
Issue: SPR-13850
2016-01-26 22:07:27 +01:00
Juergen Hoeller 0866aa923a LocalSessionFactoryBuilder provides ClassLoader to Hibernate BootstrapServiceRegistry
Issue: SPR-13879
2016-01-26 20:35:30 +01:00
Juergen Hoeller d152259673 Clarify component scan include-filter semantics
Issue: SPR-13844
(cherry picked from commit 837cb75)
2016-01-26 20:30:34 +01:00
Juergen Hoeller 14babb78b4 Clarify environment property precedence rules
Issue: SPR-13845
(cherry picked from commit ebad8db)
2016-01-26 20:30:05 +01:00
Juergen Hoeller 4fc6ead548 SessionDisconnectEvent actually preserves given session user
Issue: SPR-13871
(cherry picked from commit cdc9bf7)
2016-01-26 20:29:08 +01:00
Juergen Hoeller c1f233c787 Shared EntityManager does not insist on actualTransactionActive flag anymore
Issue: SPR-13838
(cherry picked from commit 50829c9)
2016-01-26 20:28:07 +01:00
Juergen Hoeller 77b8f4d6af ImportStack extends ArrayDeque instead of Stack and relies on standard contains implementation
Issue: SPR-13852
(cherry picked from commit e14c2de)
2016-01-26 20:27:28 +01:00
Juergen Hoeller 8516de62e3 FastByteArrayInputStream consistently returns -1 when no data available
Issue: SPR-13858
(cherry picked from commit 5d4547d)
2016-01-26 20:26:44 +01:00
Brian Clozel bcebc9db7e Register prefixed path patterns with FixedVersionStrategy
Prior to this change, configuring a `FixedVersionStrategy` like so
would configure a single "/js/**" path pattern:

```
versionResourceResolver.addFixedVersionStrategy("v1.0.0","/js/**");
```

This commit makes sure that for each path pattern, its prefixed version
is added to the map. For example, the previous configuration also
adds "/v1.0.0/js/**".

Issue: SPR-13883
cherry-picked from 84fe46cd
2016-01-22 19:03:52 +01:00
Brian Clozel fc34b0c592 Reorder HTTP headers processing in RequestMappingHandlerAdapter
Prior to this change, the `RequestMappingHandlerAdapter` would first add
a "Cache-Control" HTTP header to the response (depending on its
`WebContentGenerator` configuration and `@SessionAttributes` on the
handler class); then, the Adapter would delegate the actual handler the
processing of the request.
This leads to issues, as the handler does not have full control to the
response and has to deal with pre-existing headers in the response. This
means that the Adapter and the handler can add incompatible
Cache-Control directives without knowing it, since one cannot see the
headers added by the other until the response is committed.

This commit switches the order of execution: first, the handler is
called (possibly adding HTTP headers), then the RMHA processes the
response and adds "Cache-Control" directives *only if there's no
Cache-Control header already defined*.

Issue: SPR-13867
cherry-picked from 8f1d06f19
2016-01-22 16:36:48 +01:00
Brian Clozel a4cb3cf900 Fix OutOfBoundsException in ResourceUrlEncodingFilter
Prior to this change, the `ResourceUrlEncodingFilter` would try to
lookup resources URLs as soon as the given URL would be longer than the
expected context+servlet prefix path. This can lead to
OutOfBoundsExceptions when the provided URL does not start with that
prefix and still has the required length.

This commit makes sure that all candidate URLs for resources lookup are
prefixed with the cached servlet and context path. This underlines the
fact that the `ResourceUrlEncodingFilter` does not support relative URLs
for now and delegates to the native servlet implementation in that case.

Issue: SPR-13861
cherry-picked from 2f6d86b7
2016-01-21 17:39:37 +01:00
Rossen Stoyanchev 33112df237 Fix second failing test 2016-01-20 23:13:34 -05:00
Rossen Stoyanchev e159086201 Fix failing test 2016-01-20 21:39:41 -05:00
Rossen Stoyanchev ab16adab2e Avoid double encoding URI in ServletServerHttpRequest
Issue: SPR-13876
2016-01-20 17:58:07 -05:00
Ian Chan 29692fcc21 Catch RejectedExecutionException in WebAsyncManager
Issue: SPR-13836
2016-01-14 15:50:20 -05:00
Rossen Stoyanchev 73df50db3c Fix javadoc issue in ResponseEntityExceptionHandler
Issue: SPR-13869
2016-01-14 14:28:15 -05:00
Brian Clozel 3af62bd0dd Polish
Issue: SPR-13817
(cherry picked from d681f77d)
2016-01-05 17:33:04 +01:00
Brian Clozel 1581597092 Preserve ETag HTTP header for versioned resources
Prior to this change, a resource handler chain configured with a
`VersionResourceResolver` would add the resource version to the request
attributes when serving that resource. This approach would not work when
a `CachingResourceResolver` is configured and the resource is already
cached. Indeed, that code path is not executed when the resource is
resolved from the cache.

This commit adds a new `VersionedResource` interface that's used by the
`VersionResourceResolver`, adding a `getVersion()` method that returns
the version string for that resource. This way, the version information
is cached with the resource itself and the request attributes are no
longer used for this.

Issue: SPR-13817
(cherry picked from commit 473cf9c)
2016-01-05 15:04:05 +01:00
Juergen Hoeller 84e5234eb5 Avoid getTypeForFactoryBean warn logging for lazy-init beans
Issue: SPR-13833
(cherry picked from commit 04f3181)
2015-12-31 11:52:55 +01:00
Juergen Hoeller 24e58c1ac3 Refined RequestMappingHandlerMapping bean definition
Issue: SPR-13832
(cherry picked from commit 9bffb9e)
2015-12-31 11:52:47 +01:00
holub 15da48eba5 Update SockJS client code snippet 2015-12-30 10:29:01 +01:00
Juergen Hoeller 342d760f70 Polishing
(cherry picked from commit 27c2e8c)
2015-12-29 21:51:04 +01:00
Juergen Hoeller acecda7153 Avoid sensitive Proxy.getInvocationHandler call in synthesizeAnnotation
Issue: SPR-13829
(cherry picked from commit aecb8b6)
2015-12-29 21:50:49 +01:00
Juergen Hoeller 4a863c9066 Upgrade to Undertow 1.3.11
(cherry picked from commit 873b173)
2015-12-29 11:26:52 +01:00
Juergen Hoeller 35b8696523 Polishing 2015-12-29 11:24:56 +01:00
Juergen Hoeller e1bdf5577e StatementCreatorUtils always tries getParameterType on Oracle 12c driver
Issue: SPR-13825
(cherry picked from commit e48ec4f)
2015-12-29 11:23:49 +01:00
Juergen Hoeller deae872912 Consistent use of varargs plus related polishing 2015-12-22 23:50:05 +01:00
Juergen Hoeller 36940e003d Polishing 2015-12-21 22:38:25 +01:00
Juergen Hoeller 935d714333 SimpleNamespaceContext implements all subtleties of the NamespaceContext contract
Issue: SPR-13713
(cherry picked from commit f8860e2)
2015-12-21 22:35:47 +01:00
Juergen Hoeller 9021f8fd71 Upgrade to JavaMail 1.5.5 and Hibernate ORM 5.0.6
(cherry picked from commit 06056e6)
2015-12-21 22:35:23 +01:00
Juergen Hoeller 6f2f3595e9 Backported import and declaration cleanup 2015-12-18 00:18:09 +01:00
Juergen Hoeller d59a97c101 Polishing 2015-12-18 00:02:48 +01:00
Juergen Hoeller 7344dd259c Allow for explicit spring-websocket-4.2.xsd declarations
Issue: SPR-13804
2015-12-18 00:02:14 +01:00
Juergen Hoeller f3ac64153e Correct spring-websocket-4.2 versus spring-websocket-4.1 xsd declarations
Issue: SPR-13804
(cherry picked from commit 2fd48c9)
2015-12-17 18:34:47 +01:00
Stephane Nicoll 7b35103135 Switch to 4.2.5.BUILD-SNAPSHOT 2015-12-17 12:53:44 +01:00
788 changed files with 10811 additions and 7750 deletions
-8
View File
@@ -29,14 +29,6 @@ do not find something similar, please create a new JIRA issue before submitting
a pull request unless the change is truly trivial -- for example: typo fixes,
removing compiler warnings, etc.
### Discuss non-trivial contribution ideas with committers
If you're considering anything more than correcting a typo or fixing a minor
bug, please discuss it on the [spring-framework-contrib][] mailing list before
submitting a pull request. We're happy to provide guidance, but please spend an
hour or two researching the subject on your own, including searching the mailing
list for prior discussions.
### Sign the Individual Contributor License Agreement (ICLA)
If you have not previously done so, please fill out and submit the
+105 -119
View File
@@ -27,57 +27,52 @@ configure(allprojects) { project ->
group = "org.springframework"
version = qualifyVersionIfNecessary(version)
ext.aspectjVersion = "1.8.7"
ext.aspectjVersion = "1.8.9"
ext.eclipselinkVersion = "2.4.2"
ext.ehcacheVersion = "2.10.1"
ext.ehcacheVersion = "2.10.2"
ext.ehcachejcacheVersion = "1.0.1"
ext.ehcache3Version = "3.0.0.m4"
ext.ejbApiVersion = "3.0"
ext.fileuploadVersion = "1.3.1"
ext.ehcache3Version = "3.0.3"
ext.ejbVersion = "3.0"
ext.fileuploadVersion = "1.3.2"
ext.freemarkerVersion = "2.3.23"
ext.groovyVersion = "2.4.5"
ext.gsonVersion = "2.5"
ext.groovyVersion = "2.4.7"
ext.gsonVersion = "2.6.2"
ext.guavaVersion = "19.0"
ext.hamcrestVersion = "1.3"
ext.hibernate3Version = "3.6.10.Final"
ext.hibernate4Version = "4.3.11.Final"
ext.hibernate5Version = "5.0.5.Final"
ext.hibernate5Version = "5.0.10.Final"
ext.hibval4Version = "4.3.2.Final"
ext.hibval5Version = "5.2.2.Final"
ext.hsqldbVersion = "2.3.3"
ext.htmlunitVersion = "2.19"
ext.hibval5Version = "5.2.4.Final"
ext.hsqldbVersion = "2.3.4"
ext.httpasyncVersion = "4.1.1"
ext.httpclientVersion = "4.5.1"
ext.jackson2Version = "2.6.4"
ext.jasperreportsVersion = "6.2.0"
ext.javamailVersion = "1.5.4"
ext.jettyVersion = "9.3.6.v20151106"
ext.jodaVersion = "2.9.1"
ext.jrubyVersion = "1.7.23" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
ext.jsonassertVersion = "1.2.3"
ext.jsonpathVersion = "2.1.0"
ext.httpclientVersion = "4.5.2"
ext.jackson2Version = "2.6.7"
ext.jasperreportsVersion = "6.2.1"
ext.javamailVersion = "1.5.5"
ext.jettyVersion = "9.3.9.v20160517"
ext.jodaVersion = "2.9.4"
ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.nettyVersion = "4.0.33.Final"
ext.okhttpVersion = "2.7.0"
ext.openjpaVersion = "2.4.0"
ext.log4jVersion = "1.2.17"
ext.nettyVersion = "4.0.41.Final"
ext.okhttpVersion = "2.7.5"
ext.openjpaVersion = "2.4.1"
ext.poiVersion = "3.13"
ext.protobufVersion = "2.6.1"
ext.reactorVersion = "2.0.7.RELEASE"
ext.reactorVersion = "2.0.8.RELEASE"
ext.romeVersion = "1.5.1"
ext.seleniumVersion = "2.48.2"
ext.slf4jVersion = "1.7.13"
ext.snakeyamlVersion = "1.16"
ext.slf4jVersion = "1.7.21"
ext.snakeyamlVersion = "1.17"
ext.snifferVersion = "1.14"
ext.testngVersion = "6.9.10"
ext.tiles2Version = "2.2.2"
ext.tiles3Version = "3.0.5"
ext.tomcatVersion = "8.0.30"
ext.tomcatVersion = "8.0.36"
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
ext.undertowVersion = "1.3.10.Final"
ext.woodstoxVersion = "5.0.1"
ext.undertowVersion = "1.3.24.Final"
ext.xmlunitVersion = "1.6"
ext.xstreamVersion = "1.4.8"
ext.xstreamVersion = "1.4.9"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
@@ -130,8 +125,6 @@ configure(allprojects) { project ->
repositories {
maven { url "https://repo.spring.io/libs-release" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/snapshot" } // reactor 2.0.6 snapshot
}
dependencies {
@@ -200,7 +193,7 @@ configure(allprojects) { project ->
"http://aopalliance.sourceforge.net/doc/",
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
"http://ehcache.org/apidocs/",
"http://quartz-scheduler.org/api/2.2.0/",
"http://quartz-scheduler.org/api/2.2.1/",
"http://fasterxml.github.com/jackson-core/javadoc/2.3.0/",
"http://fasterxml.github.com/jackson-databind/javadoc/2.3.0/",
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.3.0/",
@@ -291,7 +284,7 @@ project("spring-core") {
// both into the spring-core jar. cglib 3.2 itself depends on asm 5.0 and is therefore
// further transformed by the JarJar task to depend on org.springframework.asm; this
// avoids including two different copies of asm unnecessarily.
def cglibVersion = "3.2.0"
def cglibVersion = "3.2.4"
def objenesisVersion = "2.2"
configurations {
@@ -353,10 +346,10 @@ project("spring-core") {
optional("commons-codec:commons-codec:1.10")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("net.sf.jopt-simple:jopt-simple:4.9")
optional("log4j:log4j:1.2.17")
optional("log4j:log4j:${log4jVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
testCompile("com.fasterxml.woodstox:woodstox-core:${woodstoxVersion}") {
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") {
exclude group: "stax", module: "stax-api"
}
}
@@ -384,9 +377,9 @@ project("spring-beans") {
optional("javax.inject:javax.inject:1")
optional("javax.el:javax.el-api:2.2.5")
optional("org.yaml:snakeyaml:${snakeyamlVersion}")
testCompile("log4j:log4j:1.2.17")
testCompile("log4j:log4j:${log4jVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
}
}
}
project("spring-beans-groovy") {
@@ -477,7 +470,7 @@ project("spring-context") {
compile(files(project(":spring-core").cglibRepackJar))
optional(project(":spring-instrument"))
optional("javax.inject:javax.inject:1")
optional("javax.ejb:ejb-api:${ejbApiVersion}")
optional("javax.ejb:ejb-api:${ejbVersion}")
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
optional("javax.money:money-api:1.0")
optional("org.eclipse.persistence:javax.persistence:2.0.0")
@@ -531,7 +524,7 @@ project("spring-messaging") {
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
testCompile("io.netty:netty-all:${nettyVersion}")
testCompile("commons-dbcp:commons-dbcp:1.4")
testCompile("log4j:log4j:1.2.17")
testCompile("log4j:log4j:${log4jVersion}")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
}
@@ -548,7 +541,7 @@ project("spring-tx") {
optional("aopalliance:aopalliance:1.0")
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
optional("javax.resource:connector-api:1.5")
optional("javax.ejb:ejb-api:${ejbApiVersion}")
optional("javax.ejb:ejb-api:${ejbVersion}")
optional("com.ibm.websphere:uow:6.0.2.17")
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile("org.eclipse.persistence:javax.persistence:2.0.0")
@@ -566,15 +559,10 @@ project("spring-oxm") {
targetCompatibility = 1.6
}
if (!System.getProperty("java.version").contains("1.8.")) {
// necessary because castor and xjc tasks cannot find the JDK's compiler on JDK 9
compileTestJava.enabled = false
}
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
optional("org.codehaus.castor:castor-xml:1.4.0") {
optional("org.codehaus.castor:castor-xml:1.4.1") {
exclude group: 'stax', module: 'stax-api'
exclude group: "org.springframework", module: "spring-context"
}
@@ -589,7 +577,7 @@ project("spring-oxm") {
testCompile(project(":spring-context"))
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
testCompile("xpp3:xpp3:1.1.4c")
testCompile("org.codehaus.jettison:jettison:1.3.7") {
testCompile("org.codehaus.jettison:jettison:1.3.8") {
exclude group: 'stax', module: 'stax-api'
}
if (compileTestJava.enabled) {
@@ -630,7 +618,7 @@ project("spring-jdbc") {
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
optional("com.mchange:c3p0:0.9.5.2")
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
optional("com.h2database:h2:1.4.190")
optional("com.h2database:h2:1.4.192")
optional("org.apache.derby:derby:10.12.1.1")
optional("org.apache.derby:derbyclient:10.12.1.1")
}
@@ -649,7 +637,7 @@ project("spring-context-support") {
optional("javax.cache:cache-api:1.0.0")
optional("com.google.guava:guava:${guavaVersion}")
optional("net.sf.ehcache:ehcache:${ehcacheVersion}")
optional("org.quartz-scheduler:quartz:2.2.2")
optional("org.quartz-scheduler:quartz:2.2.3")
optional("org.codehaus.fabric3.api:commonj:1.1.0")
optional("org.apache.velocity:velocity:1.7")
optional("org.freemarker:freemarker:${freemarkerVersion}")
@@ -722,9 +710,9 @@ project("spring-web") {
optional("org.eclipse.jetty:jetty-server:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet-api"
}
optional("log4j:log4j:1.2.17")
optional("log4j:log4j:${log4jVersion}")
optional("com.google.protobuf:protobuf-java:2.6.1")
optional("com.googlecode.protobuf-java-format:protobuf-java-format:1.2")
optional("com.google.protobuf:protobuf-java:${protobufVersion}")
optional("javax.mail:javax.mail-api:${javamailVersion}")
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
@@ -739,52 +727,6 @@ project("spring-web") {
}
}
project("spring-websocket") {
description = "Spring WebSocket"
dependencies {
compile(project(":spring-core"))
compile(project(":spring-context"))
compile(project(":spring-web"))
optional(project(":spring-messaging"))
optional(project(":spring-webmvc"))
optional("javax.servlet:javax.servlet-api:3.1.0")
optional("javax.websocket:javax.websocket-api:1.0")
optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
}
optional("org.glassfish.tyrus:tyrus-spi:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-core:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-server:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-container-servlet:${tyrusVersion}")
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
optional("org.eclipse.jetty:jetty-client:${jettyVersion}")
optional("io.undertow:undertow-core:${undertowVersion}")
optional("io.undertow:undertow-servlet:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.2_spec"
}
optional("io.undertow:undertow-websockets-jsr:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.1_spec"
}
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
testCompile("io.projectreactor:reactor-net:${reactorVersion}")
testCompile("io.netty:netty-all:${nettyVersion}")
testCompile("log4j:log4j:1.2.17")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
}
project("spring-orm") {
description = "Spring Object/Relational Mapping"
@@ -837,7 +779,7 @@ project("spring-orm-hibernate4") {
optional("org.hibernate:hibernate-core:${hibernate4Version}")
optional("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
optional("javax.servlet:javax.servlet-api:3.0.1")
optional("aopalliance:aopalliance:1.0")
optional("aopalliance:aopalliance:1.0")
testCompile("javax.validation:validation-api:1.1.0.GA")
testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
testCompile("javax.el:javax.el-api:2.2.5")
@@ -913,9 +855,8 @@ project("spring-webmvc") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
exclude group: "org.springframework", module: "spring-web"
}
optional('org.webjars:webjars-locator:0.28')
optional('org.webjars:webjars-locator:0.32')
testCompile(project(":spring-aop"))
testCompile("rhino:js:1.7R1")
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
testCompile("dom4j:dom4j:1.6.1") {
exclude group: "xml-apis", module: "xml-apis"
@@ -938,9 +879,10 @@ project("spring-webmvc") {
testCompile("commons-io:commons-io:1.3")
testCompile("joda-time:joda-time:${jodaVersion}")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("org.jruby:jruby:${jrubyVersion}")
testCompile("org.python:jython-standalone:2.5.3")
testCompile("org.webjars:underscorejs:1.8.3")
testCompile("org.mozilla:rhino:1.7.7.1")
testRuntime("org.jruby:jruby:${jrubyVersion}")
testRuntime("org.python:jython-standalone:2.5.3")
testRuntime("org.webjars:underscorejs:1.8.3")
}
}
@@ -991,6 +933,52 @@ project("spring-webmvc-portlet") {
}
}
project("spring-websocket") {
description = "Spring WebSocket"
dependencies {
compile(project(":spring-core"))
compile(project(":spring-context"))
compile(project(":spring-web"))
optional(project(":spring-messaging"))
optional(project(":spring-webmvc"))
optional("javax.servlet:javax.servlet-api:3.1.0")
optional("javax.websocket:javax.websocket-api:1.0")
optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
}
optional("org.glassfish.tyrus:tyrus-spi:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-core:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-server:${tyrusVersion}")
optional("org.glassfish.tyrus:tyrus-container-servlet:${tyrusVersion}")
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
optional("org.eclipse.jetty:jetty-client:${jettyVersion}")
optional("io.undertow:undertow-core:${undertowVersion}")
optional("io.undertow:undertow-servlet:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.2_spec"
}
optional("io.undertow:undertow-websockets-jsr:${undertowVersion}") {
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.1_spec"
}
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
testCompile("io.projectreactor:reactor-net:${reactorVersion}")
testCompile("io.netty:netty-all:${nettyVersion}")
testCompile("log4j:log4j:${log4jVersion}")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
}
project("spring-test") {
description = "Spring TestContext Framework"
@@ -1018,15 +1006,15 @@ project("spring-test") {
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
optional("org.hamcrest:hamcrest-core:${hamcrestVersion}")
optional("com.jayway.jsonpath:json-path:${jsonpathVersion}")
optional("org.skyscreamer:jsonassert:${jsonassertVersion}")
optional("xmlunit:xmlunit:${xmlunitVersion}")
optional("net.sourceforge.htmlunit:htmlunit:${htmlunitVersion}")
optional("org.seleniumhq.selenium:selenium-htmlunit-driver:${seleniumVersion}")
optional("net.sourceforge.htmlunit:htmlunit:2.19")
optional("org.seleniumhq.selenium:selenium-htmlunit-driver:2.48.2")
optional("org.skyscreamer:jsonassert:1.2.3")
optional("com.jayway.jsonpath:json-path:2.1.0")
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
testCompile("javax.mail:javax.mail-api:${javamailVersion}")
testCompile("javax.ejb:ejb-api:${ejbApiVersion}")
testCompile("javax.ejb:ejb-api:${ejbVersion}")
testCompile("org.hibernate:hibernate-core:${hibernate4Version}")
testCompile("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
@@ -1044,6 +1032,7 @@ project("spring-test") {
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}")
testCompile("javax.cache:cache-api:1.0.0")
testRuntime("log4j:log4j:${log4jVersion}")
testRuntime("org.ehcache:ehcache:${ehcache3Version}")
testRuntime("org.terracotta:management-model:2.0.0")
}
@@ -1080,8 +1069,8 @@ project("spring-aspects") {
dependencies {
aspects(project(":spring-orm"))
ajc("org.aspectj:aspectjtools:1.9.0.BETA-2") // for the ability to build on JDK 9, not exposed in the POMs yet
rt("org.aspectj:aspectjrt:${aspectjVersion}") // regular AspectJ version here, to be exposed in the POMs
ajc("org.aspectj:aspectjtools:${aspectjVersion}")
rt("org.aspectj:aspectjrt:${aspectjVersion}")
compile("org.aspectj:aspectjweaver:${aspectjVersion}")
provided("org.eclipse.persistence:javax.persistence:2.0.0")
optional(project(":spring-aop")) // for @Async support
@@ -1099,8 +1088,7 @@ project("spring-aspects") {
eclipse.project {
natures += "org.eclipse.ajdt.ui.ajnature"
buildCommands = [new org.gradle.plugins.ide.eclipse.model.
BuildCommand("org.eclipse.ajdt.core.ajbuilder")]
buildCommands = [new org.gradle.plugins.ide.eclipse.model.BuildCommand("org.eclipse.ajdt.core.ajbuilder")]
}
}
@@ -1170,9 +1158,7 @@ configure(rootProject) {
separateOutputDirs = false
backends = ['docbook']
options doctype: 'book', eruby: 'erubis'
attributes 'spring-version': project.version,
'revnumber' : project.version,
'docinfo' : ""
attributes 'spring-version': project.version, 'revnumber': project.version, 'docinfo': ""
}
reference {
@@ -1308,7 +1294,7 @@ configure(rootProject) {
baseName = "spring-framework"
classifier = "dist"
description = "Builds -${classifier} archive, containing all jars and docs, " +
"suitable for community download page."
"suitable for community download page."
ext.baseDir = "${baseName}-${project.version}";
View File
+1 -1
View File
@@ -1 +1 @@
version=4.2.4.BUILD-SNAPSHOT
version=4.2.8.RELEASE
+3 -3
View File
@@ -29,8 +29,8 @@ REM - generates OXM test classes to avoid errors on import into Eclipse
REM - generates metadata for all subprojects
REM - skips metadata gen for the root project (-x :eclipse) to work
REM around Eclipse's inability to import hierarchical project structures
REM SET COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
SET COMMAND=gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
REM SET COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
SET COMMAND=gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
echo.
echo -----------------------------------------------------------------------
@@ -69,7 +69,7 @@ echo When the above is complete, return here and press the enter key.
pause
set COMMAND=gradlew :eclipse
set COMMAND=gradlew --no-daemon :eclipse
echo.
echo -----------------------------------------------------------------------
+2 -2
View File
@@ -42,7 +42,7 @@ read
# - generates metadata for all subprojects
# - skips metadata gen for the root project (-x :eclipse) to work
# around Eclipse's inability to import hierarchical project structures
COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
cat <<EOM
@@ -84,7 +84,7 @@ EOM
read
COMMAND="./gradlew :eclipse"
COMMAND="./gradlew --no-daemon :eclipse"
cat <<EOM
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -86,7 +86,7 @@ public interface MethodMatcher {
* @return whether there's a runtime match
* @see MethodMatcher#matches(Method, Class)
*/
boolean matches(Method method, Class<?> targetClass, Object[] args);
boolean matches(Method method, Class<?> targetClass, Object... args);
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,12 +29,14 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
/**
* Enforce Singleton pattern.
*/
private TrueMethodMatcher() {
}
@Override
public boolean isRuntime() {
return false;
@@ -46,11 +48,17 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// Should never be invoked as isRuntime returns false.
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return "MethodMatcher.TRUE";
}
/**
* Required to support serialization. Replaces with canonical
* instance on deserialization, protecting Singleton pattern.
@@ -60,9 +68,4 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
return INSTANCE;
}
@Override
public String toString() {
return "MethodMatcher.TRUE";
}
}
@@ -135,7 +135,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
*/
private int joinPointStaticPartArgumentIndex = -1;
private Map<String, Integer> argumentBindings = null;
private Map<String, Integer> argumentBindings;
private boolean argumentsIntrospected = false;
@@ -250,17 +250,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
this.argumentNames[i] + "' that is not a valid Java identifier");
}
}
if (argumentNames != null) {
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
if (this.argumentNames != null) {
if (this.aspectJAdviceMethod.getParameterTypes().length == this.argumentNames.length + 1) {
// May need to add implicit join point arg name...
Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
if (firstArgType == JoinPoint.class ||
firstArgType == ProceedingJoinPoint.class ||
firstArgType == JoinPoint.StaticPart.class) {
String[] oldNames = argumentNames;
argumentNames = new String[oldNames.length + 1];
argumentNames[0] = "THIS_JOIN_POINT";
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
String[] oldNames = this.argumentNames;
this.argumentNames = new String[oldNames.length + 1];
this.argumentNames[0] = "THIS_JOIN_POINT";
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
}
}
}
@@ -456,8 +456,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
if (this.argumentNames.length != numExpectedArgumentNames) {
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames
+ " arguments to bind by name in advice, but actually found " +
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
" arguments to bind by name in advice, but actually found " +
this.argumentNames.length + " arguments.");
}
@@ -471,8 +471,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
// specified, and find the discovered argument types.
if (this.returningName != null) {
if (!this.argumentBindings.containsKey(this.returningName)) {
throw new IllegalStateException("Returning argument name '"
+ this.returningName + "' was not bound in advice arguments");
throw new IllegalStateException("Returning argument name '" + this.returningName +
"' was not bound in advice arguments");
}
else {
Integer index = this.argumentBindings.get(this.returningName);
@@ -482,8 +482,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
if (this.throwingName != null) {
if (!this.argumentBindings.containsKey(this.throwingName)) {
throw new IllegalStateException("Throwing argument name '"
+ this.throwingName + "' was not bound in advice arguments");
throw new IllegalStateException("Throwing argument name '" + this.throwingName +
"' was not bound in advice arguments");
}
else {
Integer index = this.argumentBindings.get(this.throwingName);
@@ -581,10 +581,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
if (numBound != this.adviceInvocationArgumentCount) {
throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount
+ " arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") +
" bound in invocation)");
throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount +
" arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
}
return adviceInvocationArgs;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -37,6 +37,7 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodI
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -40,6 +40,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -62,6 +63,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
}
}
/**
* Following AspectJ semantics, if a returning clause was specified, then the
* advice is only invoked if the returned value is an instance of the given
@@ -96,7 +98,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
else if (Object.class == type && void.class == method.getReturnType()) {
return true;
}
else{
else {
return ClassUtils.isAssignable(type, method.getReturnType());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -37,6 +37,7 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -57,11 +58,11 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements
try {
return mi.proceed();
}
catch (Throwable t) {
if (shouldInvokeOnThrowing(t)) {
invokeAdviceMethod(getJoinPointMatch(), null, t);
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw t;
throw ex;
}
}
@@ -69,8 +70,8 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements
* In AspectJ semantics, after throwing advice that specifies a throwing clause
* is only invoked if the thrown exception is a subtype of the given throwing type.
*/
private boolean shouldInvokeOnThrowing(Throwable t) {
return getDiscoveredThrowingType().isAssignableFrom(t.getClass());
private boolean shouldInvokeOnThrowing(Throwable ex) {
return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,6 +41,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
super(aspectJAroundAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
@@ -56,7 +57,6 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
return true;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
@@ -305,7 +305,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
checkReadyToMatch();
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -35,6 +35,7 @@ public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -61,34 +61,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static final String AJC_MAGIC = "ajc$";
/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...)
*/
@SuppressWarnings("unchecked")
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);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<A>(result);
}
else {
return null;
}
}
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@@ -181,6 +153,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
throw new IllegalStateException("Expecting at least " + argNames.length +
" arguments in the advice declaration, but only found " + paramTypes.length);
}
// Make the simplifying assumption for now that all of the JoinPoint based arguments
// come first in the advice declaration.
int typeOffset = paramTypes.length - argNames.length;
@@ -191,7 +164,36 @@ 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...)
*/
@SuppressWarnings("unchecked")
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);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<A>(result);
}
else {
return null;
}
}
protected enum AspectJAnnotationType {
AtPointcut,
AtBefore,
AtAfter,
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,31 +63,31 @@ public interface AspectJAdvisorFactory {
/**
* Build Spring AOP Advisors for all annotated At-AspectJ methods
* on the specified aspect instance.
* @param aif the aspect instance factory (not the aspect instance itself
* in order to avoid eager instantiation)
* @param aspectInstanceFactory the aspect instance factory
* (not the aspect instance itself in order to avoid eager instantiation)
* @return a list of advisors for this class
*/
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aif);
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);
/**
* Build a Spring AOP Advisor for the given AspectJ advice method.
* @param candidateAdviceMethod the candidate advice method
* @param aif the aspect instance factory
* @param declarationOrderInAspect the declaration order within the aspect
* @param aspectInstanceFactory the aspect instance factory
* @param declarationOrder the declaration order within the aspect
* @param aspectName the name of the aspect
* @return {@code null} if the method is not an AspectJ advice method
* or if it is a pointcut that will be used by other advice but will not
* create a Spring advice in its own right
*/
Advisor getAdvisor(Method candidateAdviceMethod,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName);
/**
* Build a Spring AOP Advice for the given AspectJ advice method.
* @param candidateAdviceMethod the candidate advice method
* @param pointcut the corresponding AspectJ expression pointcut
* @param aif the aspect instance factory
* @param declarationOrderInAspect the declaration order within the aspect
* @param expressionPointcut the AspectJ expression pointcut
* @param aspectInstanceFactory the aspect instance factory
* @param declarationOrder the declaration order within the aspect
* @param aspectName the name of the aspect
* @return {@code null} if the method is not an AspectJ advice method
* or if it is a pointcut that will be used by other advice but will not
@@ -98,7 +98,7 @@ public interface AspectJAdvisorFactory {
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
*/
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut pointcut,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
}
@@ -42,6 +42,13 @@ import org.springframework.aop.support.ComposablePointcut;
*/
public class AspectMetadata {
/**
* The name of this aspect as defined to Spring (the bean name) -
* allows us to determine if two pieces of advice come from the
* same aspect and hence their relative precedence.
*/
private final String aspectName;
/**
* AspectJ reflection information (AspectJ 5 / Java 5 specific).
*/
@@ -54,13 +61,6 @@ public class AspectMetadata {
*/
private final Pointcut perClausePointcut;
/**
* The name of this aspect as defined to Spring (the bean name) -
* allows us to determine if two pieces of advice come from the
* same aspect and hence their relative precedence.
*/
private String aspectName;
/**
* Create a new AspectMetadata instance for the given aspect class.
@@ -83,10 +83,10 @@ public class AspectMetadata {
if (ajType == null) {
throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
}
this.ajType = ajType;
if (this.ajType.getDeclarePrecedence().length > 0) {
if (ajType.getDeclarePrecedence().length > 0) {
throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
}
this.ajType = ajType;
switch (this.ajType.getPerClause().getKind()) {
case SINGLETON :
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.OrderUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -66,6 +67,8 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
* @param type the type that should be introspected by AspectJ
*/
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class<?> type) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
Assert.notNull(name, "Bean name must not be null");
this.beanFactory = beanFactory;
this.name = name;
this.aspectMetadata = new AspectMetadata(type, name);
@@ -79,12 +82,9 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
@Override
public ClassLoader getAspectClassLoader() {
if (this.beanFactory instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
}
else {
return ClassUtils.getDefaultClassLoader();
}
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
}
@Override
@@ -92,6 +92,11 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
return this.aspectMetadata;
}
public Object getAspectCreationMutex() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
}
/**
* Determine the order for this factory's target aspect, either
* an instance-specific order expressed through implementing the
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,53 +42,55 @@ class InstantiationModelAwarePointcutAdvisorImpl
private final AspectJExpressionPointcut declaredPointcut;
private Pointcut pointcut;
private final Method aspectJAdviceMethod;
private final AspectJAdvisorFactory aspectJAdvisorFactory;
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
private final Method method;
private final int declarationOrder;
private final String aspectName;
private final Pointcut pointcut;
private final boolean lazy;
private final AspectJAdvisorFactory atAspectJAdvisorFactory;
private Advice instantiatedAdvice;
private int declarationOrder;
private String aspectName;
private Boolean isBeforeAdvice;
private Boolean isAfterAdvice;
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = ajexp;
this.method = method;
this.atAspectJAdvisorFactory = af;
this.aspectInstanceFactory = aif;
this.declarationOrder = declarationOrderInAspect;
this.declaredPointcut = declaredPointcut;
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aif.getAspectMetadata().isLazilyInstantiated()) {
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut =
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
this.pointcut = declaredPointcut;
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
@@ -142,8 +144,8 @@ class InstantiationModelAwarePointcutAdvisorImpl
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.atAspectJAdvisorFactory.getAdvice(
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
@@ -191,7 +193,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
*/
private void determineAdviceType() {
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod);
if (aspectJAnnotation == null) {
this.isBeforeAdvice = false;
this.isAfterAdvice = false;
@@ -220,7 +222,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.method + "]; perClauseKind=" +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
@@ -256,7 +258,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// This can match only on declared pointcut.
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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,9 +43,13 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
@Override
public synchronized Object getAspectInstance() {
public Object getAspectInstance() {
if (this.materialized == null) {
synchronized (this) {
Object mutex = this;
if (this.maaif instanceof BeanFactoryAspectInstanceFactory) {
mutex = ((BeanFactoryAspectInstanceFactory) this.maaif).getAspectCreationMutex();
}
synchronized (mutex) {
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2015 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,8 +19,8 @@ package org.springframework.aop.aspectj.annotation;
import org.springframework.beans.factory.BeanFactory;
/**
* AspectInstanceFactory backed by a BeanFactory-provided prototype,
* enforcing prototype semantics.
* {@link org.springframework.aop.aspectj.AspectInstanceFactory} backed by a
* {@link BeanFactory}-provided prototype, enforcing prototype semantics.
*
* <p>Note that this may instantiate multiple times, which probably won't give the
* semantics you expect. Use a {@link LazySingletonAspectInstanceFactoryDecorator}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,8 +77,9 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
new Converter<Method, Annotation>() {
@Override
public Annotation convert(Method method) {
AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return annotation == null ? null : annotation.getAnnotation();
AspectJAnnotation<?> annotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (annotation != null ? annotation.getAnnotation() : null);
}
}));
comparator.addComparator(new ConvertingComparator<Method, String>(
@@ -93,17 +94,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
final String aspectName = maaif.getAspectMetadata().getAspectName();
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(maaif);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
final List<Advisor> advisors = new LinkedList<Advisor>();
List<Advisor> advisors = new LinkedList<Advisor>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
@@ -169,18 +170,19 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aif.getAspectMetadata().getAspectClass());
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut ajexp =
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
if (ajexp == null) {
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
@@ -189,6 +191,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
@@ -197,10 +200,10 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
@@ -225,27 +228,32 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
@@ -254,12 +262,12 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method " + candidateAdviceMethod);
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrderInAspect);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
@@ -268,6 +276,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
return springAdvice;
}
/**
* Synthetic advisor that instantiates the aspect.
* Triggered by per-clause pointcut on non-singleton aspect.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -113,7 +113,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
* Create a AdvisedSupport instance with the given parameters.
* @param interfaces the proxied interfaces
*/
public AdvisedSupport(Class<?>[] interfaces) {
public AdvisedSupport(Class<?>... interfaces) {
this();
setInterfaces(interfaces);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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,9 +22,9 @@ import org.springframework.aop.TargetSource;
import org.springframework.util.ClassUtils;
/**
* Factory for AOP proxies for programmatic use, rather than via a bean
* factory. This class provides a simple way of obtaining and configuring
* AOP proxies in code.
* Factory for AOP proxies for programmatic use, rather than via declarative
* setup in a bean factory. This class provides a simple way of obtaining
* and configuring AOP proxy instances in custom user code.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,9 +31,12 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.core.task.support.TaskExecutorAdapter;
import org.springframework.lang.UsesJava8;
import org.springframework.util.ClassUtils;
@@ -58,6 +61,15 @@ import org.springframework.util.concurrent.ListenableFuture;
*/
public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
/**
* The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
* <p>Note that the initial lookup happens by type; this is just the fallback
* in case of multiple executor beans found in the context.
* @since 4.2.6
*/
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor";
// Java 8's CompletableFuture type present?
private static final boolean completableFuturePresent = ClassUtils.isPresent(
"java.util.concurrent.CompletableFuture", AsyncExecutionInterceptor.class.getClassLoader());
@@ -67,7 +79,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<Method, AsyncTaskExecutor>(16);
private Executor defaultExecutor;
private volatile Executor defaultExecutor;
private AsyncUncaughtExceptionHandler exceptionHandler;
@@ -75,10 +87,22 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
/**
* Create a new {@link AsyncExecutionAspectSupport}, using the provided default
* executor unless individual async methods indicate via qualifier that a more
* specific executor should be used.
* @param defaultExecutor the executor to use when executing asynchronous methods
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
* executor has been requested via a qualifier on the async method, in which case the
* executor will be looked up at invocation time against the enclosing bean factory
*/
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
this(defaultExecutor, new SimpleAsyncUncaughtExceptionHandler());
}
/**
* Create a new {@link AsyncExecutionAspectSupport} with the given exception handler.
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
* executor has been requested via a qualifier on the async method, in which case the
* executor will be looked up at invocation time against the enclosing bean factory
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
*/
public AsyncExecutionAspectSupport(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
@@ -86,23 +110,16 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
this.exceptionHandler = exceptionHandler;
}
/**
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
*/
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
this(defaultExecutor, new SimpleAsyncUncaughtExceptionHandler());
}
/**
* Supply the executor to be used when executing async methods.
* @param defaultExecutor the {@code Executor} (typically a Spring {@code
* AsyncTaskExecutor} or {@link java.util.concurrent.ExecutorService}) to delegate to
* unless a more specific executor has been requested via a qualifier on the async
* method, in which case the executor will be looked up at invocation time against the
* enclosing bean factory.
* @see #getExecutorQualifier
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
* executor has been requested via a qualifier on the async method, in which case the
* executor will be looked up at invocation time against the enclosing bean factory
* @see #getExecutorQualifier(Method)
* @see #setBeanFactory(BeanFactory)
* @see #getDefaultExecutor(BeanFactory)
*/
public void setExecutor(Executor defaultExecutor) {
this.defaultExecutor = defaultExecutor;
@@ -117,7 +134,10 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
}
/**
* Set the {@link BeanFactory} to be used when looking up executors by qualifier.
* Set the {@link BeanFactory} to be used when looking up executors by qualifier
* or when relying on the default executor lookup algorithm.
* @see #findQualifiedExecutor(BeanFactory, String)
* @see #getDefaultExecutor(BeanFactory)
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) {
@@ -128,26 +148,32 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
/**
* Determine the specific executor to use when executing the given method.
* Should preferably return an {@link AsyncListenableTaskExecutor} implementation.
* @return the executor to use (or {@code null}, but just if no default executor has been set)
* @return the executor to use (or {@code null}, but just if no default executor is available)
*/
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor executorToUse = this.defaultExecutor;
Executor targetExecutor;
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
" to access qualified executor '" + qualifier + "'");
}
executorToUse = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
this.beanFactory, Executor.class, qualifier);
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else if (executorToUse == null) {
else {
targetExecutor = this.defaultExecutor;
if (targetExecutor == null) {
synchronized (this.executors) {
if (this.defaultExecutor == null) {
this.defaultExecutor = getDefaultExecutor(this.beanFactory);
}
targetExecutor = this.defaultExecutor;
}
}
}
if (targetExecutor == null) {
return null;
}
executor = (executorToUse instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) executorToUse : new TaskExecutorAdapter(executorToUse));
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
this.executors.put(method, executor);
}
return executor;
@@ -160,11 +186,69 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
* been specified and that the {@linkplain #setExecutor(Executor) default executor}
* should be used.
* @param method the method to inspect for executor qualifier metadata
* @return the qualifier if specified, otherwise empty string or {@code null}
* @return the qualifier if specified, otherwise empty String or {@code null}
* @see #determineAsyncExecutor(Method)
* @see #findQualifiedExecutor(BeanFactory, String)
*/
protected abstract String getExecutorQualifier(Method method);
/**
* Retrieve a target executor for the given qualifier.
* @param qualifier the qualifier to resolve
* @return the target executor, or {@code null} if none available
* @since 4.2.6
* @see #getExecutorQualifier(Method)
*/
protected Executor findQualifiedExecutor(BeanFactory beanFactory, String qualifier) {
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
" to access qualified executor '" + qualifier + "'");
}
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
}
/**
* Retrieve or build a default executor for this advice instance.
* An executor returned from here will be cached for further use.
* <p>The default implementation searches for a unique {@link TaskExecutor} bean
* in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
* If neither of the two is resolvable, this implementation will return {@code null}.
* @param beanFactory the BeanFactory to use for a default executor lookup
* @return the default executor, or {@code null} if none available
* @since 4.2.6
* @see #findQualifiedExecutor(BeanFactory, String)
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
if (beanFactory != null) {
try {
// Search for TaskExecutor bean... not plain Executor since that would
// match with ScheduledExecutorService as well, which is unusable for
// our purposes here. TaskExecutor is more clearly designed for it.
return beanFactory.getBean(TaskExecutor.class);
}
catch (NoUniqueBeanDefinitionException ex) {
try {
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
}
catch (NoSuchBeanDefinitionException ex2) {
if (logger.isInfoEnabled()) {
logger.info("More than one TaskExecutor bean found within the context, and none is named " +
"'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
"as an alias) in order to use it for async processing.");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
logger.debug("Could not find default TaskExecutor bean", ex);
// Giving up -> either using local default executor or none at all...
logger.info("No TaskExecutor bean found for async processing");
}
}
return null;
}
/**
* Delegate for actually executing the given task with the chosen executor.
* @param task the task to execute
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,9 +26,11 @@ import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.Ordered;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.util.ClassUtils;
/**
@@ -65,22 +67,27 @@ import org.springframework.util.ClassUtils;
*/
public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {
/**
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
* as of 4.2.6, a local executor for this interceptor will be built otherwise
*/
public AsyncExecutionInterceptor(Executor defaultExecutor) {
super(defaultExecutor);
}
/**
* Create a new {@code AsyncExecutionInterceptor}.
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
* as of 4.2.6, a local executor for this interceptor will be built otherwise
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
*/
public AsyncExecutionInterceptor(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
super(defaultExecutor, exceptionHandler);
}
/**
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
*/
public AsyncExecutionInterceptor(Executor defaultExecutor) {
super(defaultExecutor);
}
/**
* Intercept the given method invocation, submit the actual calling of the method to
@@ -136,6 +143,20 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
return null;
}
/**
* This implementation searches for a unique {@link org.springframework.core.task.TaskExecutor}
* bean in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
* If neither of the two is resolvable (e.g. if no {@code BeanFactory} was configured at all),
* this implementation falls back to a newly created {@link SimpleAsyncTaskExecutor} instance
* for local use if no default could be found.
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
@Override
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -23,6 +23,7 @@ import org.aopalliance.aop.Advice;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.util.Assert;
/**
@@ -72,8 +73,23 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
resetAdviceMonitor();
}
private void resetAdviceMonitor() {
if (this.beanFactory instanceof ConfigurableBeanFactory) {
this.adviceMonitor = ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
}
else {
this.adviceMonitor = new Object();
}
}
/**
* Specify a particular instance of the target advice directly,
* avoiding lazy resolution in {@link #getAdvice()}.
* @since 3.1
*/
public void setAdvice(Advice advice) {
synchronized (this.adviceMonitor) {
this.advice = advice;
@@ -93,7 +109,15 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
@Override
public String toString() {
return getClass().getName() + ": advice bean '" + getAdviceBeanName() + "'";
StringBuilder sb = new StringBuilder(getClass().getName());
sb.append(": advice ");
if (this.adviceBeanName != null) {
sb.append("bean '").append(this.adviceBeanName).append("'");
}
else {
sb.append(this.advice);
}
return sb.toString();
}
@@ -106,7 +130,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
ois.defaultReadObject();
// Initialize transient fields.
this.adviceMonitor = new Object();
resetAdviceMonitor();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,17 +91,17 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
++this.evaluations;
public boolean matches(Method method, Class<?> targetClass, Object... args) {
this.evaluations++;
ControlFlow cflow = ControlFlowFactory.createControlFlow();
return (this.methodName != null) ? cflow.under(this.clazz, this.methodName) : cflow.under(this.clazz);
return (this.methodName != null ? cflow.under(this.clazz, this.methodName) : cflow.under(this.clazz));
}
/**
* It's useful to know how many times we've fired, for optimization.
*/
public int getEvaluations() {
return evaluations;
return this.evaluations;
}
@@ -115,6 +115,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
return this;
}
@Override
public boolean equals(Object other) {
if (this == other) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -138,7 +138,7 @@ public abstract class MethodMatchers {
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return this.mm1.matches(method, targetClass, args) || this.mm2.matches(method, targetClass, args);
}
@@ -245,7 +245,7 @@ public abstract class MethodMatchers {
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,7 +71,7 @@ public abstract class Pointcuts {
* @param args arguments to the method
* @return whether there's a runtime match
*/
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object[] args) {
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object... args) {
Assert.notNull(pointcut, "Pointcut must not be null");
if (pointcut == Pointcut.TRUE) {
return true;
@@ -98,9 +98,9 @@ public abstract class Pointcuts {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getName().startsWith("set") &&
method.getParameterTypes().length == 1 &&
method.getReturnType() == Void.TYPE;
return (method.getName().startsWith("set") &&
method.getParameterTypes().length == 1 &&
method.getReturnType() == Void.TYPE);
}
private Object readResolve() {
@@ -119,8 +119,8 @@ public abstract class Pointcuts {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getName().startsWith("get") &&
method.getParameterTypes().length == 0;
return (method.getName().startsWith("get") &&
method.getParameterTypes().length == 0);
}
private Object readResolve() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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,7 +32,7 @@ public abstract class StaticMethodMatcher implements MethodMatcher {
}
@Override
public final boolean matches(Method method, Class<?> targetClass, Object[] args) {
public final boolean matches(Method method, Class<?> targetClass, Object... args) {
// should never be invoked because isRuntime() returns false
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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,17 +53,15 @@ public final class AspectJExpressionPointcutTests {
private Method setSomeNumber;
private Method isPostProcessed;
@Before
public void setUp() throws NoSuchMethodException {
getAge = TestBean.class.getMethod("getAge", (Class<?>[])null);
setAge = TestBean.class.getMethod("setAge", new Class[]{int.class});
setSomeNumber = TestBean.class.getMethod("setSomeNumber", new Class[]{Number.class});
isPostProcessed = TestBean.class.getMethod("isPostProcessed", (Class[]) null);
getAge = TestBean.class.getMethod("getAge");
setAge = TestBean.class.getMethod("setAge", int.class);
setSomeNumber = TestBean.class.getMethod("setSomeNumber", Number.class);
}
@Test
public void testMatchExplicit() {
String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
@@ -111,21 +109,9 @@ public final class AspectJExpressionPointcutTests {
testThisOrTarget("target");
}
public static class OtherIOther implements IOther {
@Override
public void absquatulate() {
// Empty
}
}
/**
* This and target are equivalent. Really instanceof pointcuts.
* @param which this or target
* @throws Exception
* @throws NoSuchMethodException
* @throws SecurityException
*/
private void testThisOrTarget(String which) throws SecurityException, NoSuchMethodException {
String matchesTestBean = which + "(org.springframework.tests.sample.beans.TestBean)";
@@ -138,11 +124,8 @@ public final class AspectJExpressionPointcutTests {
assertTrue(testBeanPc.matches(TestBean.class));
assertTrue(testBeanPc.matches(getAge, TestBean.class));
assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
OtherIOther.class));
assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
OtherIOther.class));
assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
}
@Test
@@ -171,8 +154,7 @@ public final class AspectJExpressionPointcutTests {
assertEquals(matchSubpackages, withinBeansPc.matches(
DeepBean.class.getMethod("aMethod", String.class), DeepBean.class));
assertFalse(withinBeansPc.matches(String.class));
assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
OtherIOther.class));
assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
}
@Test
@@ -183,7 +165,7 @@ public final class AspectJExpressionPointcutTests {
fail();
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().indexOf("expression") != -1);
assertTrue(ex.getMessage().contains("expression"));
}
}
@@ -195,7 +177,7 @@ public final class AspectJExpressionPointcutTests {
fail();
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().indexOf("expression") != -1);
assertTrue(ex.getMessage().contains("expression"));
}
}
@@ -207,7 +189,7 @@ public final class AspectJExpressionPointcutTests {
fail();
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().indexOf("expression") != -1);
assertTrue(ex.getMessage().contains("expression"));
}
}
@@ -226,10 +208,10 @@ public final class AspectJExpressionPointcutTests {
//assertDoesNotMatchStringClass(classFilter);
assertTrue("Should match with setSomeNumber with Double input",
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Double(12)}));
methodMatcher.matches(setSomeNumber, TestBean.class, new Double(12)));
assertFalse("Should not match setSomeNumber with Integer input",
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Integer(11)}));
assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class, null));
methodMatcher.matches(setSomeNumber, TestBean.class, new Integer(11)));
assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class));
assertTrue("Should be a runtime match", methodMatcher.isRuntime());
}
@@ -281,7 +263,6 @@ public final class AspectJExpressionPointcutTests {
}
catch (IllegalArgumentException ex) {
assertTrue(true);
System.out.println(ex.getMessage());
}
}
@@ -326,16 +307,14 @@ public final class AspectJExpressionPointcutTests {
@Test
public void testAndSubstitution() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
PointcutExpression expr =
((AspectJExpressionPointcut) pc).getPointcutExpression();
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
assertEquals("execution(* *(..)) && args(String)",expr.getPointcutExpression());
}
@Test
public void testMultipleAndSubstitutions() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
PointcutExpression expr =
((AspectJExpressionPointcut) pc).getPointcutExpression();
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
assertEquals("execution(* *(..)) && args(String) && this(Object)",expr.getPointcutExpression());
}
@@ -344,6 +323,15 @@ public final class AspectJExpressionPointcutTests {
pointcut.setExpression(expression);
return pointcut;
}
public static class OtherIOther implements IOther {
@Override
public void absquatulate() {
// Empty
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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,7 +36,7 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class TigerAspectJExpressionPointcutTests {
public class TigerAspectJExpressionPointcutTests {
// TODO factor into static in AspectJExpressionPointcut
private Method getAge;
@@ -46,7 +46,7 @@ public final class TigerAspectJExpressionPointcutTests {
@Before
public void setUp() throws NoSuchMethodException {
getAge = TestBean.class.getMethod("getAge", (Class[]) null);
getAge = TestBean.class.getMethod("getAge");
// Assumes no overloading
for (Method m : HasGeneric.class.getMethods()) {
methodsOnHasGeneric.put(m.getName(), m);
@@ -54,18 +54,6 @@ public final class TigerAspectJExpressionPointcutTests {
}
public static class HasGeneric {
public void setFriends(List<TestBean> friends) {
}
public void setEnemies(List<TestBean> enemies) {
}
public void setPartners(List<?> partners) {
}
public void setPhoneNumbers(List<String> numbers) {
}
}
@Test
public void testMatchGenericArgument() {
String expression = "execution(* set*(java.util.List<org.springframework.tests.sample.beans.TestBean>) )";
@@ -132,15 +120,12 @@ public final class TigerAspectJExpressionPointcutTests {
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws SecurityException, NoSuchMethodException {
String expression = "within(@(test.annotation..*) *)";
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class),
TestBean.class));
assertTrue(springAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo", (Class[]) null),
SpringAnnotated.class));
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class));
assertTrue(springAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class));
expression = "within(@(test.annotation.transaction..*) *)";
AspectJExpressionPointcut springTxAnnotatedPc = testMatchAnnotationOnClass(expression);
assertFalse(springTxAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo", (Class[]) null),
SpringAnnotated.class));
assertFalse(springTxAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo"), SpringAnnotated.class));
}
@Test
@@ -154,7 +139,7 @@ public final class TigerAspectJExpressionPointcutTests {
ajexp.setExpression(expression);
assertFalse(ajexp.matches(getAge, TestBean.class));
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertTrue(ajexp.matches(BeanB.class.getMethod("setName", String.class), BeanB.class));
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
@@ -168,10 +153,10 @@ public final class TigerAspectJExpressionPointcutTests {
ajexp.setExpression(expression);
assertFalse(ajexp.matches(getAge, TestBean.class));
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
}
@@ -182,10 +167,10 @@ public final class TigerAspectJExpressionPointcutTests {
anySpringMethodAnnotation.setExpression(expression);
assertFalse(anySpringMethodAnnotation.matches(getAge, TestBean.class));
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), 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", (Class[]) null), BeanA.class));
assertTrue(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
}
@@ -196,10 +181,10 @@ public final class TigerAspectJExpressionPointcutTests {
takesSpringAnnotatedArgument2.setExpression(expression);
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), 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", (Class[]) null), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(takesSpringAnnotatedArgument2.matches(
@@ -213,8 +198,7 @@ public final class TigerAspectJExpressionPointcutTests {
assertFalse(takesSpringAnnotatedArgument2.matches(
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
ProcessesSpringAnnotatedParameters.class,
new Object[] { new TestBean(), new BeanA()})
ProcessesSpringAnnotatedParameters.class, new TestBean(), new BeanA())
);
}
@@ -225,10 +209,10 @@ public final class TigerAspectJExpressionPointcutTests {
takesSpringAnnotatedArgument2.setExpression(expression);
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), 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", (Class[]) null), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
assertTrue(takesSpringAnnotatedArgument2.matches(
@@ -240,6 +224,19 @@ public final class TigerAspectJExpressionPointcutTests {
}
public static class HasGeneric {
public void setFriends(List<TestBean> friends) {
}
public void setEnemies(List<TestBean> enemies) {
}
public void setPartners(List<?> partners) {
}
public void setPhoneNumbers(List<String> numbers) {
}
}
public static class ProcessesSpringAnnotatedParameters {
public void takesAnnotatedParameters(TestBean tb, SpringAnnotated sa) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.annotation;
import java.io.FileNotFoundException;
@@ -961,7 +962,7 @@ abstract class AbstractMakeModifiable {
private Method getGetterFromSetter(Method setter) {
String getterName = setter.getName().replaceFirst("set", "get");
try {
return setter.getDeclaringClass().getMethod(getterName, (Class[]) null);
return setter.getDeclaringClass().getMethod(getterName);
}
catch (NoSuchMethodException ex) {
// must be write only
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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,18 +31,21 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class AspectJPointcutAdvisorTests {
public class AspectJPointcutAdvisorTests {
private final AspectJAdvisorFactory af = new ReflectiveAspectJAdvisorFactory();
private AspectJAdvisorFactory af = new ReflectiveAspectJAdvisorFactory();
@Test
public void testSingleton() throws SecurityException, NoSuchMethodException {
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS);
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp,
new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null),"someBean"),
TestBean.class.getMethod("getAge", (Class[]) null),1,"someBean");
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(
ajexp, TestBean.class.getMethod("getAge"), af,
new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null), "someBean"),
1, "someBean");
assertSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut());
assertFalse(ajpa.isPerInstance());
}
@@ -52,34 +55,35 @@ public final class AspectJPointcutAdvisorTests {
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS);
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp,
new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(),"someBean"), null, 1, "someBean");
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(
ajexp, TestBean.class.getMethod("getAge"), af,
new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(), "someBean"),
1, "someBean");
assertNotSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut());
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut() instanceof AspectJExpressionPointcut);
assertTrue(ajpa.isPerInstance());
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getClassFilter().matches(TestBean.class));
assertFalse(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches(
TestBean.class.getMethod("getAge", (Class[]) null),
TestBean.class));
TestBean.class.getMethod("getAge"), TestBean.class));
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches(
TestBean.class.getMethod("getSpouse", (Class[]) null),
TestBean.class));
TestBean.class.getMethod("getSpouse"), TestBean.class));
}
@Test(expected=AopConfigException.class)
@Test(expected = AopConfigException.class)
public void testPerCflowTarget() {
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowAspect.class);
}
@Test(expected=AopConfigException.class)
@Test(expected = AopConfigException.class)
public void testPerCflowBelowTarget() {
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowBelowAspect.class);
}
private void testIllegalInstantiationModel(Class<?> c) throws AopConfigException {
new AspectMetadata(c,"someBean");
new AspectMetadata(c, "someBean");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -37,7 +37,7 @@ public final class MethodInvocationTests {
@Test
public void testValidInvocation() throws Throwable {
Method m = Object.class.getMethod("hashCode", (Class[]) null);
Method m = Object.class.getMethod("hashCode");
Object proxy = new Object();
final Object returnValue = new Object();
List<Object> is = new LinkedList<Object>();
@@ -67,7 +67,7 @@ public final class MethodInvocationTests {
};
List<Object> is = new LinkedList<Object>();
Method m = Object.class.getMethod("hashCode", (Class[]) null);
Method m = Object.class.getMethod("hashCode");
Object proxy = new Object();
ReflectiveMethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, m, null, null, is);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -78,7 +78,7 @@ public final class ThrowsAdviceInterceptorTests {
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
FileNotFoundException ex = new FileNotFoundException();
MethodInvocation mi = mock(MethodInvocation.class);
given(mi.getMethod()).willReturn(Object.class.getMethod("hashCode", (Class[]) null));
given(mi.getMethod()).willReturn(Object.class.getMethod("hashCode"));
given(mi.getThis()).willReturn(new Object());
given(mi.proceed()).willThrow(ex);
try {
@@ -140,12 +140,15 @@ public final class ThrowsAdviceInterceptorTests {
assertEquals(1, th.getCalls("remoteException"));
}
@SuppressWarnings("serial")
static class MyThrowsHandler extends MethodCounter implements ThrowsAdvice {
// Full method signature
public void afterThrowing(Method m, Object[] args, Object target, IOException ex) {
count("ioException");
}
public void afterThrowing(RemoteException ex) throws Throwable {
count("remoteException");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -54,8 +54,8 @@ public abstract class AbstractRegexpMethodPointcutTests {
}
protected void noPatternSuppliedTests(AbstractRegexpMethodPointcut rpc) throws Exception {
assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertFalse(rpc.matches(Object.class.getMethod("wait"), Object.class));
assertEquals(0, rpc.getPatterns().length);
}
@@ -69,38 +69,38 @@ public abstract class AbstractRegexpMethodPointcutTests {
protected void exactMatchTests(AbstractRegexpMethodPointcut rpc) throws Exception {
// assumes rpc.setPattern("java.lang.Object.hashCode");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait"), Object.class));
}
@Test
public void testSpecificMatch() throws Exception {
rpc.setPattern("java.lang.String.hashCode");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertFalse(rpc.matches(Object.class.getMethod("hashCode"), Object.class));
}
@Test
public void testWildcard() throws Exception {
rpc.setPattern(".*Object.hashCode");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), Object.class));
assertFalse(rpc.matches(Object.class.getMethod("wait"), Object.class));
}
@Test
public void testWildcardForOneClass() throws Exception {
rpc.setPattern("java.lang.Object.*");
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
assertTrue(rpc.matches(Object.class.getMethod("wait", (Class[]) null), String.class));
assertTrue(rpc.matches(Object.class.getMethod("hashCode"), String.class));
assertTrue(rpc.matches(Object.class.getMethod("wait"), String.class));
}
@Test
public void testMatchesObjectClass() throws Exception {
rpc.setPattern("java.lang.Object.*");
assertTrue(rpc.matches(Exception.class.getMethod("hashCode", (Class[]) null), IOException.class));
assertTrue(rpc.matches(Exception.class.getMethod("hashCode"), IOException.class));
// Doesn't match a method from Throwable
assertFalse(rpc.matches(Exception.class.getMethod("getMessage", (Class[]) null), Exception.class));
assertFalse(rpc.matches(Exception.class.getMethod("getMessage"), Exception.class));
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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,7 +32,7 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class ComposablePointcutTests {
public class ComposablePointcutTests {
public static MethodMatcher GETTER_METHOD_MATCHER = new StaticMethodMatcher() {
@Override
@@ -62,11 +62,12 @@ public final class ComposablePointcutTests {
}
};
@Test
public void testMatchAll() throws NoSuchMethodException {
Pointcut pc = new ComposablePointcut();
assertTrue(pc.getClassFilter().matches(Object.class));
assertTrue(pc.getMethodMatcher().matches(Object.class.getMethod("hashCode", (Class[]) null), Exception.class));
assertTrue(pc.getMethodMatcher().matches(Object.class.getMethod("hashCode"), Exception.class));
}
@Test
@@ -93,23 +94,23 @@ public final class ComposablePointcutTests {
public void testUnionMethodMatcher() {
// Matches the getAge() method in any class
ComposablePointcut pc = new ComposablePointcut(ClassFilter.TRUE, GET_AGE_METHOD_MATCHER);
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
pc.union(GETTER_METHOD_MATCHER);
// Should now match all getter methods
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
pc.union(ABSQUATULATE_METHOD_MATCHER);
// Should now match absquatulate() as well
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
// But it doesn't match everything
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_SET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_SET_AGE, TestBean.class));
}
@Test
@@ -124,9 +125,9 @@ public final class ComposablePointcutTests {
assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
pc.intersection(GET_AGE_METHOD_MATCHER);
// Use the Pointcuts matches method
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
}
@Test
@@ -153,4 +154,5 @@ public final class ComposablePointcutTests {
assertEquals(pc1, pc2);
assertEquals(pc1.hashCode(), pc2.hashCode());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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,7 +32,7 @@ import static org.junit.Assert.*;
* @author Juergen Hoeller
* @author Chris Beams
*/
public final class MethodMatchersTests {
public class MethodMatchersTests {
private final Method EXCEPTION_GETMESSAGE;
@@ -44,10 +44,10 @@ public final class MethodMatchersTests {
public MethodMatchersTests() throws Exception {
EXCEPTION_GETMESSAGE = Exception.class.getMethod("getMessage", (Class[]) null);
ITESTBEAN_GETAGE = ITestBean.class.getMethod("getAge", (Class[]) null);
ITESTBEAN_SETAGE = ITestBean.class.getMethod("setAge", new Class[] { int.class });
IOTHER_ABSQUATULATE = IOther.class.getMethod("absquatulate", (Class[]) null);
EXCEPTION_GETMESSAGE = Exception.class.getMethod("getMessage");
ITESTBEAN_GETAGE = ITestBean.class.getMethod("getAge");
ITESTBEAN_SETAGE = ITestBean.class.getMethod("setAge", int.class);
IOTHER_ABSQUATULATE = IOther.class.getMethod("absquatulate");
}
@@ -82,12 +82,12 @@ public final class MethodMatchersTests {
MethodMatcher intersection = MethodMatchers.intersection(mm1, mm2);
assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
assertTrue("3Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
assertTrue("3Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Integer(5)));
// Knock out dynamic part
intersection = MethodMatchers.intersection(intersection, new TestDynamicMethodMatcherWhichDoesNotMatch());
assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
assertFalse("3 - not Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
assertFalse("3 - not Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Integer(5)));
}
@Test
@@ -125,18 +125,20 @@ public final class MethodMatchersTests {
}
}
private static class TestDynamicMethodMatcherWhichMatches extends DynamicMethodMatcher {
@Override
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
public boolean matches(Method m, Class<?> targetClass, Object... args) {
return true;
}
}
private static class TestDynamicMethodMatcherWhichDoesNotMatch extends DynamicMethodMatcher {
@Override
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
public boolean matches(Method m, Class<?> targetClass, Object... args) {
return false;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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,7 +30,7 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Chris Beams
*/
public final class PointcutsTests {
public class PointcutsTests {
public static Method TEST_BEAN_SET_AGE;
public static Method TEST_BEAN_GET_AGE;
@@ -39,10 +39,10 @@ public final class PointcutsTests {
static {
try {
TEST_BEAN_SET_AGE = TestBean.class.getMethod("setAge", new Class[] { int.class });
TEST_BEAN_GET_AGE = TestBean.class.getMethod("getAge", (Class[]) null);
TEST_BEAN_GET_NAME = TestBean.class.getMethod("getName", (Class[]) null);
TEST_BEAN_ABSQUATULATE = TestBean.class.getMethod("absquatulate", (Class[]) null);
TEST_BEAN_SET_AGE = TestBean.class.getMethod("setAge", int.class);
TEST_BEAN_GET_AGE = TestBean.class.getMethod("getAge");
TEST_BEAN_GET_NAME = TestBean.class.getMethod("getName");
TEST_BEAN_ABSQUATULATE = TestBean.class.getMethod("absquatulate");
}
catch (Exception ex) {
throw new RuntimeException("Shouldn't happen: error in test suite");
@@ -125,22 +125,22 @@ public final class PointcutsTests {
@Test
public void testTrue() {
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
@Test
public void testMatches() {
assertTrue(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
/**
@@ -149,29 +149,29 @@ public final class PointcutsTests {
@Test
public void testUnionOfSettersAndGetters() {
Pointcut union = Pointcuts.union(allClassGetterPointcut, allClassSetterPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
@Test
public void testUnionOfSpecificGetters() {
Pointcut union = Pointcuts.union(allClassGetAgePointcut, allClassGetNamePointcut);
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
// Union with all setters
union = Pointcuts.union(union, allClassSetterPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
}
/**
@@ -180,16 +180,16 @@ public final class PointcutsTests {
*/
@Test
public void testUnionOfAllSettersAndSubclassSetters() {
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertTrue(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
Pointcut union = Pointcuts.union(myTestBeanSetterPointcut, allClassGetterPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class));
// Still doesn't match superclass setter
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
}
/**
@@ -198,44 +198,44 @@ public final class PointcutsTests {
*/
@Test
public void testIntersectionOfSpecificGettersAndSubclassGetters() {
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, MyTestBean.class));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, MyTestBean.class));
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, MyTestBean.class));
Pointcut intersection = Pointcuts.intersection(allClassGetAgePointcut, myTestBeanGetterPointcut);
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class));
// Matches subclass of MyTestBean
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class));
// Now intersection with MyTestBeanSubclass getters should eliminate MyTestBean target
intersection = Pointcuts.intersection(intersection, myTestBeanSubclassGetterPointcut);
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class));
// Still matches subclass of MyTestBean
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class));
// Now union with all TestBean methods
Pointcut union = Pointcuts.union(intersection, allTestBeanMethodsPointcut);
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class));
// Still matches subclass of MyTestBean
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class));
assertTrue(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, MyTestBean.class, null));
assertTrue(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class));
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, MyTestBean.class));
}
@@ -245,9 +245,9 @@ public final class PointcutsTests {
@Test
public void testSimpleIntersection() {
Pointcut intersection = Pointcuts.intersection(allClassGetterPointcut, allClassSetterPointcut);
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, new Integer(6)));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class));
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_ABSQUATULATE, TestBean.class));
}
}
@@ -1,6 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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,27 +28,21 @@ public class NopInterceptor implements MethodInterceptor {
private int count;
/**
* @see org.aopalliance.intercept.MethodInterceptor#invoke(MethodInvocation)
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
increment();
return invocation.proceed();
}
protected void increment() {
this.count++;
}
public int getCount() {
return this.count;
}
protected void increment() {
++count;
}
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object other) {
@@ -62,5 +55,9 @@ public class NopInterceptor implements MethodInterceptor {
return this.count == ((NopInterceptor) other).count;
}
@Override
public int hashCode() {
return NopInterceptor.class.hashCode();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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,22 +28,10 @@ import org.springframework.util.ObjectUtils;
@SuppressWarnings("serial")
public class SerializablePerson implements Person, Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public String getName() {
@@ -55,6 +43,16 @@ public class SerializablePerson implements Person, Serializable {
this.name = name;
}
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public Object echo(Object o) throws Throwable {
if (o instanceof Throwable) {
@@ -63,10 +61,6 @@ public class SerializablePerson implements Person, Serializable {
return o;
}
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object other) {
@@ -77,4 +71,9 @@ public class SerializablePerson implements Person, Serializable {
return p.age == age && ObjectUtils.nullSafeEquals(name, p.name);
}
@Override
public int hashCode() {
return SerializablePerson.class.hashCode();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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,10 +24,11 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
/**
* {@code @Configuration} class that registers the Spring infrastructure beans necessary
* to enable AspectJ-based annotation-driven cache management.
* {@code @Configuration} class that registers the Spring infrastructure beans
* necessary to enable AspectJ-based annotation-driven cache management.
*
* @author Chris Beams
* @author Stephane Nicoll
* @since 3.1
* @see org.springframework.cache.annotation.EnableCaching
* @see org.springframework.cache.annotation.CachingConfigurationSelector
@@ -39,12 +40,18 @@ public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationCacheAspect cacheAspect() {
AnnotationCacheAspect cacheAspect = AnnotationCacheAspect.aspectOf();
if (this.cacheManager != null) {
if (this.cacheResolver != null) {
cacheAspect.setCacheResolver(this.cacheResolver);
}
else if (this.cacheManager != null) {
cacheAspect.setCacheManager(this.cacheManager);
}
if (this.keyGenerator != null) {
cacheAspect.setKeyGenerator(this.keyGenerator);
}
if (this.errorHandler != null) {
cacheAspect.setErrorHandler(this.errorHandler);
}
return cacheAspect;
}
@@ -29,8 +29,8 @@ import org.springframework.context.annotation.Role;
* Configurable}.
*
* <p>This configuration class is automatically imported when using the
* @{@link EnableSpringConfigured} annotation. See {@code @EnableSpringConfigured}'s
* javadoc for complete usage details.
* {@link EnableSpringConfigured @EnableSpringConfigured} annotation. See
* {@code @EnableSpringConfigured}'s javadoc for complete usage details.
*
* @author Chris Beams
* @since 3.1
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,47 +17,49 @@
package org.springframework.scheduling.aspectj;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.interceptor.AsyncExecutionAspectSupport;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.util.concurrent.ListenableFuture;
/**
* Abstract aspect that routes selected methods asynchronously.
*
* <p>This aspect needs to be injected with an implementation of
* {@link Executor} to activate it for a specific thread pool.
* Otherwise it will simply delegate all calls synchronously.
* <p>This aspect needs to be injected with an implementation of a task-oriented
* {@link java.util.concurrent.Executor} to activate it for a specific thread pool,
* or with a {@link org.springframework.beans.factory.BeanFactory} for default
* executor lookup. Otherwise it will simply delegate all calls synchronously.
*
* @author Ramnivas Laddad
* @author Juergen Hoeller
* @author Chris Beams
* @author Stephane Nicoll
* @since 3.0.5
* @see #setExecutor
* @see #setBeanFactory
* @see #getDefaultExecutor
*/
public abstract aspect AbstractAsyncExecutionAspect extends AsyncExecutionAspectSupport {
/**
* Create an {@code AnnotationAsyncExecutionAspect} with a {@code null} default
* executor, which should instead be set via {@code #aspectOf} and
* {@link #setExecutor(Executor)}. The same applies for {@link #setExceptionHandler}
* Create an {@code AnnotationAsyncExecutionAspect} with a {@code null}
* default executor, which should instead be set via {@code #aspectOf} and
* {@link #setExecutor}. The same applies for {@link #setExceptionHandler}.
*/
public AbstractAsyncExecutionAspect() {
super(null);
}
/**
* Apply around advice to methods matching the {@link #asyncMethod()} pointcut,
* submit the actual calling of the method to the correct task executor and return
* immediately to the caller.
* @return {@link Future} if the original method returns {@code Future}; {@code null}
* otherwise.
* @return {@link Future} if the original method returns {@code Future};
* {@code null} otherwise
*/
@SuppressAjWarnings("adviceDidNotMatch")
Object around() : asyncMethod() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,9 +33,17 @@ import org.springframework.scheduling.annotation.Async;
* on the return type. If, however, a class marked with {@code @Async} contains a method
* that violates this constraint, it produces only a warning.
*
* <p>This aspect needs to be injected with an implementation of a task-oriented
* {@link java.util.concurrent.Executor} to activate it for a specific thread pool,
* or with a {@link org.springframework.beans.factory.BeanFactory} for default
* executor lookup. Otherwise it will simply delegate all calls synchronously.
*
* @author Ramnivas Laddad
* @author Chris Beams
* @since 3.0.5
* @see #setExecutor
* @see #setBeanFactory
* @see #getDefaultExecutor
*/
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
@@ -74,7 +82,6 @@ public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspec
declare warning:
execution(!(void || Future+) (@Async *).*(..)):
"Methods in a class marked with @Async that do not return void or Future will " +
"be routed synchronously";
"Methods in a class marked with @Async that do not return void or Future will be routed synchronously";
}
@@ -0,0 +1,285 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.aspectj;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.cache.CacheManager;
import org.springframework.cache.CacheTestUtils;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.config.AnnotatedClassCacheableService;
import org.springframework.cache.config.CacheableService;
import org.springframework.cache.config.DefaultCacheableService;
import org.springframework.cache.config.SomeCustomKeyGenerator;
import org.springframework.cache.config.SomeKeyGenerator;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.NamedCacheResolver;
import org.springframework.cache.interceptor.SimpleCacheErrorHandler;
import org.springframework.cache.interceptor.SimpleCacheResolver;
import org.springframework.cache.support.NoOpCacheManager;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.*;
/**
* @author Stephane Nicoll
*/
public class AspectJEnableCachingIsolatedTests {
private ConfigurableApplicationContext ctx;
private void load(Class<?>... config) {
this.ctx = new AnnotationConfigApplicationContext(config);
}
@After
public void closeContext() {
if (this.ctx != null) {
this.ctx.close();
}
}
@Test
public void testKeyStrategy() {
load(EnableCachingConfig.class);
AnnotationCacheAspect aspect = this.ctx.getBean(AnnotationCacheAspect.class);
assertSame(this.ctx.getBean("keyGenerator", KeyGenerator.class), aspect.getKeyGenerator());
}
@Test
public void testCacheErrorHandler() {
load(EnableCachingConfig.class);
AnnotationCacheAspect aspect = this.ctx.getBean(AnnotationCacheAspect.class);
assertSame(this.ctx.getBean("errorHandler", CacheErrorHandler.class), aspect.getErrorHandler());
}
// --- local tests -------
@Test
public void singleCacheManagerBean() {
load(SingleCacheManagerConfig.class);
}
@Test
public void multipleCacheManagerBeans() {
try {
load(MultiCacheManagerConfig.class);
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().contains("bean of type CacheManager"));
}
}
@Test
public void multipleCacheManagerBeans_implementsCachingConfigurer() {
load(MultiCacheManagerConfigurer.class); // does not throw
}
@Test
public void multipleCachingConfigurers() {
try {
load(MultiCacheManagerConfigurer.class, EnableCachingConfig.class);
}
catch (BeanCreationException ex) {
Throwable root = ex.getRootCause();
assertTrue(root instanceof IllegalStateException);
assertTrue(ex.getMessage().contains("implementations of CachingConfigurer"));
}
}
@Test
public void noCacheManagerBeans() {
try {
load(EmptyConfig.class);
}
catch (IllegalStateException ex) {
assertTrue(ex.getMessage().contains("No bean of type CacheManager"));
}
}
@Test
@Ignore("AspectJ has some sort of caching that makes this one fail")
public void emptyConfigSupport() {
load(EmptyConfigSupportConfig.class);
AnnotationCacheAspect aspect = this.ctx.getBean(AnnotationCacheAspect.class);
assertNotNull(aspect.getCacheResolver());
assertEquals(SimpleCacheResolver.class, aspect.getCacheResolver().getClass());
assertSame(this.ctx.getBean(CacheManager.class),
((SimpleCacheResolver) aspect.getCacheResolver()).getCacheManager());
}
@Test
public void bothSetOnlyResolverIsUsed() {
load(FullCachingConfig.class);
AnnotationCacheAspect aspect = this.ctx.getBean(AnnotationCacheAspect.class);
assertSame(this.ctx.getBean("cacheResolver"), aspect.getCacheResolver());
assertSame(this.ctx.getBean("keyGenerator"), aspect.getKeyGenerator());
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class EnableCachingConfig extends CachingConfigurerSupport {
@Override
@Bean
public CacheManager cacheManager() {
return CacheTestUtils.createSimpleCacheManager("testCache", "primary", "secondary");
}
@Bean
public CacheableService<?> service() {
return new DefaultCacheableService();
}
@Bean
public CacheableService<?> classService() {
return new AnnotatedClassCacheableService();
}
@Override
@Bean
public KeyGenerator keyGenerator() {
return new SomeKeyGenerator();
}
@Override
@Bean
public CacheErrorHandler errorHandler() {
return new SimpleCacheErrorHandler();
}
@Bean
public KeyGenerator customKeyGenerator() {
return new SomeCustomKeyGenerator();
}
@Bean
public CacheManager customCacheManager() {
return CacheTestUtils.createSimpleCacheManager("testCache");
}
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class EmptyConfig {
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class SingleCacheManagerConfig {
@Bean
public CacheManager cm1() {
return new NoOpCacheManager();
}
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class MultiCacheManagerConfig {
@Bean
public CacheManager cm1() {
return new NoOpCacheManager();
}
@Bean
public CacheManager cm2() {
return new NoOpCacheManager();
}
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class MultiCacheManagerConfigurer extends CachingConfigurerSupport {
@Bean
public CacheManager cm1() {
return new NoOpCacheManager();
}
@Bean
public CacheManager cm2() {
return new NoOpCacheManager();
}
@Override
public CacheManager cacheManager() {
return cm1();
}
@Override
public KeyGenerator keyGenerator() {
return null;
}
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class EmptyConfigSupportConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cm() {
return new NoOpCacheManager();
}
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class FullCachingConfig extends CachingConfigurerSupport {
@Override
@Bean
public CacheManager cacheManager() {
return new NoOpCacheManager();
}
@Override
@Bean
public KeyGenerator keyGenerator() {
return new SomeKeyGenerator();
}
@Override
@Bean
public CacheResolver cacheResolver() {
return new NamedCacheResolver(cacheManager(), "foo");
}
}
}
@@ -0,0 +1,92 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.aspectj;
import org.springframework.cache.CacheManager;
import org.springframework.cache.CacheTestUtils;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.config.AbstractCacheAnnotationTests;
import org.springframework.cache.config.AnnotatedClassCacheableService;
import org.springframework.cache.config.CacheableService;
import org.springframework.cache.config.DefaultCacheableService;
import org.springframework.cache.config.SomeCustomKeyGenerator;
import org.springframework.cache.config.SomeKeyGenerator;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleCacheErrorHandler;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Stephane Nicoll
*/
public class AspectJEnableCachingTests extends AbstractCacheAnnotationTests {
@Override
protected ConfigurableApplicationContext getApplicationContext() {
return new AnnotationConfigApplicationContext(EnableCachingConfig.class);
}
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
static class EnableCachingConfig extends CachingConfigurerSupport {
@Override
@Bean
public CacheManager cacheManager() {
return CacheTestUtils.createSimpleCacheManager("testCache", "primary", "secondary");
}
@Bean
public CacheableService<?> service() {
return new DefaultCacheableService();
}
@Bean
public CacheableService<?> classService() {
return new AnnotatedClassCacheableService();
}
@Override
@Bean
public KeyGenerator keyGenerator() {
return new SomeKeyGenerator();
}
@Override
@Bean
public CacheErrorHandler errorHandler() {
return new SimpleCacheErrorHandler();
}
@Bean
public KeyGenerator customKeyGenerator() {
return new SomeCustomKeyGenerator();
}
@Bean
public CacheManager customCacheManager() {
return CacheTestUtils.createSimpleCacheManager("testCache");
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -177,7 +177,7 @@ public class AnnotatedClassCacheableService implements CacheableService<Object>
}
@Override
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames = "secondary", key = "#p0") })
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames = "secondary", key = "#a0"), @CacheEvict(cacheNames = "primary", key = "#p0 + 'A'") })
public Object multiEvict(Object arg1) {
return counter.getAndIncrement();
}
@@ -189,7 +189,7 @@ public class AnnotatedClassCacheableService implements CacheableService<Object>
}
@Override
@Caching(cacheable = { @Cacheable(cacheNames = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
@Caching(cacheable = { @Cacheable(cacheNames = "primary", condition = "#a0 == 3") }, evict = { @CacheEvict("secondary") })
public Object multiConditionalCacheAndEvict(Object arg1) {
return counter.getAndIncrement();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -185,8 +185,7 @@ public class DefaultCacheableService implements CacheableService<Long> {
}
@Override
//FIXME @Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames = "secondary", key = "#p0"), @CacheEvict(cacheNames = "primary", key = "#p0 + 'A'") })
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames = "secondary", key = "#p0") })
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames = "secondary", key = "#p0"), @CacheEvict(cacheNames = "primary", key = "#p0 + 'A'") })
public Long multiEvict(Object arg1) {
return counter.getAndIncrement();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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,7 +26,7 @@ import org.springframework.cache.interceptor.KeyGenerator;
*
* @author Stephane Nicoll
*/
final class SomeCustomKeyGenerator implements KeyGenerator {
public final class SomeCustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
@@ -31,7 +31,6 @@ import groovy.lang.GroovyObjectSupport;
import groovy.lang.GroovyShell;
import groovy.lang.GroovySystem;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.InvokerHelper;
@@ -337,8 +336,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
if (uri == null) {
throw new IllegalArgumentException("Namespace definition must supply a non-null URI");
}
NamespaceHandler namespaceHandler = this.groovyDslXmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(
uri);
NamespaceHandler namespaceHandler =
this.groovyDslXmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(uri);
if (namespaceHandler == null) {
throw new BeanDefinitionParsingException(new Problem("No namespace handler found for URI: " + uri,
new Location(new DescriptiveResource(("Groovy")))));
@@ -375,7 +374,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
throw new IllegalArgumentException("Argument to ref() is not a valid bean or was not found");
if (args[0] instanceof RuntimeBeanReference) {
refName = ((RuntimeBeanReference)args[0]).getBeanName();
refName = ((RuntimeBeanReference) args[0]).getBeanName();
}
else {
refName = args[0].toString();
@@ -388,7 +387,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
}
return new RuntimeBeanReference(refName, parentRef);
}
else if (this.namespaces.containsKey(name) && args.length > 0 && (args[0] instanceof Closure)) {
else if (this.namespaces.containsKey(name) && args.length > 0 && args[0] instanceof Closure) {
GroovyDynamicElementReader reader = createDynamicElementReader(name);
reader.invokeMethod("doCall", args);
}
@@ -396,7 +395,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
// abstract bean definition
return invokeBeanDefiningMethod(name, args);
}
else if (args.length > 0 && (args[0] instanceof Class || args[0] instanceof RuntimeBeanReference || args[0] instanceof Map)) {
else if (args.length > 0 &&
(args[0] instanceof Class || args[0] instanceof RuntimeBeanReference || args[0] instanceof Map)) {
return invokeBeanDefiningMethod(name, args);
}
else if (args.length > 1 && args[args.length -1] instanceof Closure) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -87,10 +87,10 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
}
}
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
/** The wrapped object */
private Object object;
private Object wrappedObject;
private String nestedPath = "";
@@ -204,23 +204,23 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
Assert.notNull(object, "Target object must not be null");
if (object.getClass() == javaUtilOptionalClass) {
this.object = OptionalUnwrapper.unwrap(object);
this.wrappedObject = OptionalUnwrapper.unwrap(object);
}
else {
this.object = object;
this.wrappedObject = object;
}
this.nestedPath = (nestedPath != null ? nestedPath : "");
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : this.object);
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : this.wrappedObject);
this.nestedPropertyAccessors = null;
this.typeConverterDelegate = new TypeConverterDelegate(this, this.object);
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
}
public final Object getWrappedInstance() {
return this.object;
return this.wrappedObject;
}
public final Class<?> getWrappedClass() {
return (this.object != null ? this.object.getClass() : null);
return (this.wrappedObject != null ? this.wrappedObject.getClass() : null);
}
/**
@@ -303,7 +303,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "'", ex);
"in indexed property path '" + propertyName + "'", ex);
}
// Set value for last key.
String key = tokens.keys[tokens.keys.length - 1];
@@ -318,7 +318,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
else {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
"in indexed property path '" + propertyName + "': returned null");
}
}
if (propValue.getClass().isArray()) {
@@ -367,8 +367,8 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot set element with index " + index + " in List of size " +
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
@@ -405,7 +405,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
}
@@ -451,7 +451,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
ph.setValue(object, valueToApply);
ph.setValue(this.wrappedObject, valueToApply);
}
catch (TypeMismatchException ex) {
throw ex;
@@ -800,7 +800,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
/**
* Recursively navigate to return a property accessor for the nested property path.
* @param propertyPath property property path, which may be nested
* @param propertyPath property path, which may be nested
* @return a property accessor for the target bean
*/
@SuppressWarnings("unchecked") // avoid nested generic
@@ -914,9 +914,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
return BeanUtils.instantiate(type);
}
}
catch (Exception ex) {
// TODO: Root cause exception context is lost here; just exception message preserved.
// Should we throw another exception type that preserves context instead?
catch (Throwable ex) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
}
@@ -942,7 +940,8 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
actualName = propertyName.substring(0, keyStart);
}
String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd);
if ((key.startsWith("'") && key.endsWith("'")) || (key.startsWith("\"") && key.endsWith("\""))) {
if (key.length() > 1 && (key.startsWith("'") && key.endsWith("'")) ||
(key.startsWith("\"") && key.endsWith("\""))) {
key = key.substring(1, key.length() - 1);
}
keys.add(key);
@@ -953,10 +952,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
tokens.actualName = (actualName != null ? actualName : propertyName);
tokens.canonicalName = tokens.actualName;
if (!keys.isEmpty()) {
tokens.canonicalName +=
PROPERTY_KEY_PREFIX +
StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) +
PROPERTY_KEY_SUFFIX;
tokens.canonicalName += PROPERTY_KEY_PREFIX +
StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) +
PROPERTY_KEY_SUFFIX;
tokens.keys = StringUtils.toStringArray(keys);
}
return tokens;
@@ -965,8 +963,8 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
@Override
public String toString() {
StringBuilder sb = new StringBuilder(getClass().getName());
if (this.object != null) {
sb.append(": wrapping object [").append(ObjectUtils.identityToString(this.object)).append("]");
if (this.wrappedObject != null) {
sb.append(": wrapping object [").append(ObjectUtils.identityToString(this.wrappedObject)).append("]");
}
else {
sb.append(": no wrapped object set");
@@ -148,7 +148,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyAccessException if the property was valid but the
* accessor method failed or a type mismatch occured
* accessor method failed or a type mismatch occurred
*/
@Override
public abstract void setPropertyValue(String propertyName, Object value) throws BeansException;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -278,8 +278,12 @@ public abstract class BeanUtils {
targetMethod = method;
numMethodsFoundWithCurrentMinimumArgs = 1;
}
else {
if (targetMethod.getParameterTypes().length == numParams) {
else if (!method.isBridge() && targetMethod.getParameterTypes().length == numParams) {
if (targetMethod.isBridge()) {
// Prefer regular method over bridge...
targetMethod = method;
}
else {
// Additional candidate with same length
numMethodsFoundWithCurrentMinimumArgs++;
}
@@ -289,7 +293,7 @@ public abstract class BeanUtils {
if (numMethodsFoundWithCurrentMinimumArgs > 1) {
throw new IllegalArgumentException("Cannot resolve method '" + methodName +
"' to a unique method. Attempted to resolve to overloaded method with " +
"the least number of parameters, but there were " +
"the least number of parameters but there were " +
numMethodsFoundWithCurrentMinimumArgs + " candidates.");
}
return targetMethod;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -48,6 +48,19 @@ import java.beans.PropertyDescriptor;
*/
public interface BeanWrapper extends ConfigurablePropertyAccessor {
/**
* Specify a limit for array and collection auto-growing.
* <p>Default is unlimited on a plain BeanWrapper.
* @since 4.1
*/
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
/**
* Return the limit for array and collection auto-growing.
* @since 4.1
*/
int getAutoGrowCollectionLimit();
/**
* Return the bean instance wrapped by this object, if any.
* @return the bean instance, or {@code null} if none set
@@ -78,15 +91,4 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
*/
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
/**
* Specify a limit for array and collection auto-growing.
* <p>Default is unlimited on a plain BeanWrapper.
*/
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
/**
* Return the limit for array and collection auto-growing.
*/
int getAutoGrowCollectionLimit();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -136,7 +136,30 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
@Override
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
super.setWrappedInstance(object, nestedPath, rootObject);
setIntrospectionClass(getWrappedInstance().getClass());
setIntrospectionClass(getWrappedClass());
}
/**
* Set the class to introspect.
* Needs to be called when the target object changes.
* @param clazz the class to introspect
*/
protected void setIntrospectionClass(Class<?> clazz) {
if (this.cachedIntrospectionResults != null && this.cachedIntrospectionResults.getBeanClass() != clazz) {
this.cachedIntrospectionResults = null;
}
}
/**
* Obtain a lazily initializted CachedIntrospectionResults instance
* for the wrapped object.
*/
private CachedIntrospectionResults getCachedIntrospectionResults() {
Assert.state(getWrappedInstance() != null, "BeanWrapper does not hold a bean instance");
if (this.cachedIntrospectionResults == null) {
this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass());
}
return this.cachedIntrospectionResults;
}
/**
@@ -155,30 +178,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
return this.acc;
}
/**
* Set the class to introspect.
* Needs to be called when the target object changes.
* @param clazz the class to introspect
*/
protected void setIntrospectionClass(Class<?> clazz) {
if (this.cachedIntrospectionResults != null &&
!clazz.equals(this.cachedIntrospectionResults.getBeanClass())) {
this.cachedIntrospectionResults = null;
}
}
/**
* Obtain a lazily initializted CachedIntrospectionResults instance
* for the wrapped object.
*/
private CachedIntrospectionResults getCachedIntrospectionResults() {
Assert.state(getWrappedInstance() != null, "BeanWrapper does not hold a bean instance");
if (this.cachedIntrospectionResults == null) {
this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass());
}
return this.cachedIntrospectionResults;
}
/**
* Convert the given value for the specified property to the latter's type.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -120,7 +120,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyAccessException if the property was valid but the
* accessor method failed or a type mismatch occured
* accessor method failed or a type mismatch occurred
*/
void setPropertyValue(String propertyName, Object value) throws BeansException;
@@ -130,7 +130,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyAccessException if the property was valid but the
* accessor method failed or a type mismatch occured
* accessor method failed or a type mismatch occurred
*/
void setPropertyValue(PropertyValue pv) throws BeansException;
@@ -144,7 +144,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
*/
@@ -164,7 +164,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
* @see #setPropertyValues(PropertyValues, boolean, boolean)
@@ -185,7 +185,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
* @see #setPropertyValues(PropertyValues, boolean, boolean)
@@ -208,7 +208,7 @@ public interface PropertyAccessor {
* @throws InvalidPropertyException if there is no such property or
* if the property isn't writable
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
* occured for specific properties during the batch update. This exception bundles
* occurred for specific properties during the batch update. This exception bundles
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,8 +45,6 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
private final Object value;
private Object source;
private boolean optional = false;
private boolean converted = false;
@@ -78,12 +76,12 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
Assert.notNull(original, "Original must not be null");
this.name = original.getName();
this.value = original.getValue();
this.source = original.getSource();
this.optional = original.isOptional();
this.converted = original.converted;
this.convertedValue = original.convertedValue;
this.conversionNecessary = original.conversionNecessary;
this.resolvedTokens = original.resolvedTokens;
setSource(original.getSource());
copyAttributesFrom(original);
}
@@ -97,10 +95,10 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
Assert.notNull(original, "Original must not be null");
this.name = original.getName();
this.value = newValue;
this.source = original;
this.optional = original.isOptional();
this.conversionNecessary = original.conversionNecessary;
this.resolvedTokens = original.resolvedTokens;
setSource(original);
copyAttributesFrom(original);
}
@@ -129,16 +127,28 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
*/
public PropertyValue getOriginalPropertyValue() {
PropertyValue original = this;
while (original.source instanceof PropertyValue && original.source != original) {
original = (PropertyValue) original.source;
Object source = getSource();
while (source instanceof PropertyValue && source != original) {
original = (PropertyValue) source;
source = original.getSource();
}
return original;
}
/**
* Set whether this is an optional value, that is, to be ignored
* when no corresponding property exists on the target class.
* @since 3.0
*/
public void setOptional(boolean optional) {
this.optional = optional;
}
/**
* Return whether this is an optional value, that is, to be ignored
* when no corresponding property exists on the target class.
* @since 3.0
*/
public boolean isOptional() {
return this.optional;
}
@@ -180,7 +190,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
PropertyValue otherPv = (PropertyValue) other;
return (this.name.equals(otherPv.name) &&
ObjectUtils.nullSafeEquals(this.value, otherPv.value) &&
ObjectUtils.nullSafeEquals(this.source, otherPv.source));
ObjectUtils.nullSafeEquals(getSource(), otherPv.getSource()));
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -183,9 +183,10 @@ class TypeConverterDelegate {
// Value not of required type?
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) {
if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
convertedValue instanceof String) {
TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
if (elementTypeDesc != null && Enum.class.isAssignableFrom(elementTypeDesc.getType())) {
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
}
}
@@ -265,7 +266,7 @@ class TypeConverterDelegate {
}
else {
// convertedValue == null
if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
convertedValue = javaUtilOptionalEmpty;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -123,7 +123,7 @@ public class BeanCreationException extends FatalBeanException {
/**
* Add a related cause to this bean creation exception,
* not being a direct cause of the failure but having occured
* not being a direct cause of the failure but having occurred
* earlier in the creation of the same bean instance.
* @param ex the related cause to add
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,24 +67,27 @@ import org.springframework.core.ResolvableType;
* 1. BeanNameAware's {@code setBeanName}<br>
* 2. BeanClassLoaderAware's {@code setBeanClassLoader}<br>
* 3. BeanFactoryAware's {@code setBeanFactory}<br>
* 4. ResourceLoaderAware's {@code setResourceLoader}
* 4. EnvironmentAware's {@code setEnvironment}
* 5. EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
* 6. ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)<br>
* 5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* 7. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)<br>
* 6. MessageSourceAware's {@code setMessageSource}
* 8. MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)<br>
* 7. ApplicationContextAware's {@code setApplicationContext}
* 9. ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)<br>
* 8. ServletContextAware's {@code setServletContext}
* 10. ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)<br>
* 9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
* 10. InitializingBean's {@code afterPropertiesSet}<br>
* 11. a custom init-method definition<br>
* 12. {@code postProcessAfterInitialization} methods of BeanPostProcessors
* 11. {@code postProcessBeforeInitialization} methods of BeanPostProcessors<br>
* 12. InitializingBean's {@code afterPropertiesSet}<br>
* 13. a custom init-method definition<br>
* 14. {@code postProcessAfterInitialization} methods of BeanPostProcessors
*
* <p>On shutdown of a bean factory, the following lifecycle methods apply:<br>
* 1. DisposableBean's {@code destroy}<br>
* 2. a custom destroy-method definition
* 1. {@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
* 2. DisposableBean's {@code destroy}<br>
* 3. a custom destroy-method definition
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -153,12 +156,12 @@ public interface BeanFactory {
/**
* Return the bean instance that uniquely matches the given object type, if any.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* @return an instance of the single bean matching the required type
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
@@ -188,12 +191,12 @@ public interface BeanFactory {
* Return an instance, which may be shared or independent, of the specified bean.
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
* overriding the specified default arguments (if any) in the bean definition.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@code null} is disallowed.
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @return an instance of the bean
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -109,6 +109,7 @@ public interface ListableBeanFactory extends BeanFactory {
* @return the names of beans (or objects created by FactoryBeans) matching
* the given object type (including subclasses), or an empty array if none
* @since 4.2
* @see #isTypeMatch(String, ResolvableType)
* @see FactoryBean#getObjectType
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, ResolvableType)
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2016 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,10 +17,10 @@
package org.springframework.beans.factory;
/**
* Counterpart of BeanNameAware. Returns the bean name of an object.
* Counterpart of {@link BeanNameAware}. Returns the bean name of an object.
*
* <p>This interface can be introduced to avoid a brittle dependence
* on bean name in objects used with Spring IoC and Spring AOP.
* <p>This interface can be introduced to avoid a brittle dependence on
* bean name in objects used with Spring IoC and Spring AOP.
*
* @author Rod Johnson
* @since 2.0
@@ -29,7 +29,7 @@ package org.springframework.beans.factory;
public interface NamedBean {
/**
* Return the name of this bean in a Spring bean factory.
* Return the name of this bean in a Spring bean factory, if known.
*/
String getBeanName();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -56,7 +56,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
public UnsatisfiedDependencyException(
String resourceDescription, String beanName, String propertyName, BeansException ex) {
this(resourceDescription, beanName, propertyName, (ex != null ? ": " + ex.getMessage() : ""));
this(resourceDescription, beanName, propertyName, (ex != null ? ex.getMessage() : ""));
initCause(ex);
}
@@ -88,7 +88,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException {
public UnsatisfiedDependencyException(
String resourceDescription, String beanName, int ctorArgIndex, Class<?> ctorArgType, BeansException ex) {
this(resourceDescription, beanName, ctorArgIndex, ctorArgType, (ex != null ? ": " + ex.getMessage() : ""));
this(resourceDescription, beanName, ctorArgIndex, ctorArgType, (ex != null ? ex.getMessage() : ""));
initCause(ex);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -208,7 +208,7 @@ public abstract class AbstractFactoryBean<T>
* <p>Invoked on initialization of this FactoryBean in case of
* a singleton; else, on each {@link #getObject()} call.
* @return the object returned by this factory
* @throws Exception if an exception occured during object creation
* @throws Exception if an exception occurred during object creation
* @see #getObject()
*/
protected abstract T createInstance() throws Exception;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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,8 @@ import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
/**
* Extension of the {@link org.springframework.beans.factory.BeanFactory}
@@ -114,9 +116,9 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
* <p>Performs full initialization of the bean, including all applicable
* {@link BeanPostProcessor BeanPostProcessors}.
* <p>Note: This is intended for creating a fresh instance, populating annotated
* fields and methods as well as applying all standard bean initialiation callbacks.
* fields and methods as well as applying all standard bean initialization callbacks.
* It does <i>not</> imply traditional by-name or by-type autowiring of properties;
* use {@link #createBean(Class, int, boolean)} for that purposes.
* use {@link #createBean(Class, int, boolean)} for those purposes.
* @param beanClass the class of the bean to create
* @return the new bean instance
* @throws BeansException if instantiation or wiring failed
@@ -129,7 +131,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
* <p>Note: This is essentially intended for (re-)populating annotated fields and
* methods, either for new instances or for deserialized instances. It does
* <i>not</i> imply traditional by-name or by-type autowiring of properties;
* use {@link #autowireBeanProperties} for that purposes.
* use {@link #autowireBeanProperties} for those purposes.
* @param existingBean the existing bean instance
* @throws BeansException if wiring failed
*/
@@ -154,15 +156,6 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
*/
Object configureBean(Object existingBean, String beanName) throws BeansException;
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency
* @param beanName the name of the bean which declares the present dependency
* @return the resolved object, or {@code null} if none found
* @throws BeansException in dependency resolution failed
*/
Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
//-------------------------------------------------------------------------
// Specialized methods for fine-grained control over the bean lifecycle
@@ -312,18 +305,39 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
*/
void destroyBean(Object existingBean);
//-------------------------------------------------------------------------
// Delegate methods for resolving injection points
//-------------------------------------------------------------------------
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency
* @param beanName the name of the bean which declares the present dependency
* @param autowiredBeanNames a Set that all names of autowired beans (used for
* resolving the present dependency) are supposed to be added to
* @param typeConverter the TypeConverter to use for populating arrays and
* collections
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
* @return the resolved object, or {@code null} if none found
* @throws BeansException in dependency resolution failed
* @throws NoSuchBeanDefinitionException if no matching bean was found
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
* @throws BeansException if dependency resolution failed for any other reason
* @since 2.5
* @see #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
*/
Object resolveDependency(DependencyDescriptor descriptor, String beanName,
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
* @param autowiredBeanNames a Set that all names of autowired beans (used for
* resolving the given dependency) are supposed to be added to
* @param typeConverter the TypeConverter to use for populating arrays and collections
* @return the resolved object, or {@code null} if none found
* @throws NoSuchBeanDefinitionException if no matching bean was found
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
* @throws BeansException if dependency resolution failed for any other reason
* @since 2.5
* @see DependencyDescriptor
*/
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -196,6 +196,7 @@ public class DependencyDescriptor implements Serializable {
* Optionally set the concrete class that contains this dependency.
* This may differ from the class that declares the parameter/field in that
* it may be a subclass thereof, potentially substituting type variables.
* @since 4.0
*/
public void setContainingClass(Class<?> containingClass) {
this.containingClass = containingClass;
@@ -206,6 +207,7 @@ public class DependencyDescriptor implements Serializable {
/**
* Build a ResolvableType object for the wrapped parameter/field.
* @since 4.0
*/
public ResolvableType getResolvableType() {
return (this.field != null ? ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
@@ -217,6 +219,7 @@ public class DependencyDescriptor implements Serializable {
* <p>This is {@code false} by default but may be overridden to return {@code true} in order
* to suggest to a {@link org.springframework.beans.factory.support.AutowireCandidateResolver}
* that a fallback match is acceptable as well.
* @since 4.0
*/
public boolean fallbackMatchAllowed() {
return false;
@@ -224,6 +227,7 @@ public class DependencyDescriptor implements Serializable {
/**
* Return a variant of this descriptor that is intended for a fallback match.
* @since 4.0
* @see #fallbackMatchAllowed()
*/
public DependencyDescriptor forFallbackMatch() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -204,7 +204,7 @@ public class FieldRetrievingFactoryBean
// instance field
return this.fieldObject.get(this.targetObject);
}
else{
else {
// class field
return this.fieldObject.get(null);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
@@ -95,7 +95,7 @@ public class PropertiesFactoryBean extends PropertiesLoaderSupport
* <p>Invoked on initialization of this FactoryBean in case of a
* shared singleton; else, on each {@link #getObject()} call.
* @return the object returned by this factory
* @throws IOException if an exception occured during properties loading
* @throws IOException if an exception occurred during properties loading
* @see #mergeProperties()
*/
protected Properties createProperties() throws IOException {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -325,8 +325,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException {
return resolveDependency(descriptor, beanName, null, null);
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException {
return resolveDependency(descriptor, requestingBeanName, null, null);
}
@@ -802,10 +802,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (objectType.value != null) {
return objectType.value;
}
else {
// No type found for shortcut FactoryBean instance:
// fall back to full creation of the FactoryBean instance.
return super.getTypeForFactoryBean(beanName, mbd);
}
}
// No type found - fall back to full creation of the FactoryBean instance.
return super.getTypeForFactoryBean(beanName, mbd);
return null;
}
/**
@@ -824,7 +828,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return exposedObject;
return null;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -731,7 +731,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
/**
* Return information about methods to be overridden by the IoC
* container. This will be empty if there are no method overrides.
* Never returns null.
* Never returns {@code null}.
*/
public MethodOverrides getMethodOverrides() {
return this.methodOverrides;
@@ -934,8 +934,11 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
// Check that lookup methods exists.
MethodOverrides methodOverrides = getMethodOverrides();
if (!methodOverrides.isEmpty()) {
for (MethodOverride mo : methodOverrides.getOverrides()) {
prepareMethodOverride(mo);
Set<MethodOverride> overrides = methodOverrides.getOverrides();
synchronized (overrides) {
for (MethodOverride mo : overrides) {
prepareMethodOverride(mo);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -1475,9 +1475,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
logger.debug("Bean currently in creation on FactoryBean type check: " + ex);
}
}
else if (mbd.isLazyInit()) {
if (logger.isDebugEnabled()) {
logger.debug("Bean creation exception on lazy FactoryBean type check: " + ex);
}
}
else {
if (logger.isWarnEnabled()) {
logger.warn("Bean creation exception on FactoryBean type check: " + ex);
logger.warn("Bean creation exception on non-lazy FactoryBean type check: " + ex);
}
}
onSuppressedException(ex);
@@ -1493,11 +1498,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
*/
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
this.alreadyCreated.add(beanName);
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
clearMergedBeanDefinition(beanName);
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);
}
}
}
}
@@ -1506,7 +1514,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @param beanName the name of the bean
*/
protected void cleanupAfterBeanCreationFailure(String beanName) {
this.alreadyCreated.remove(beanName);
synchronized (this.mergedBeanDefinitions) {
this.alreadyCreated.remove(beanName);
}
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -166,6 +166,17 @@ public class BeanDefinitionBuilder {
return this;
}
/**
* Add an indexed constructor arg value. The current index is tracked internally
* and all additions are at the present point.
* @deprecated since Spring 2.5, in favor of {@link #addConstructorArgValue}.
* This variant just remains around for Spring Security 2.x compatibility.
*/
@Deprecated
public BeanDefinitionBuilder addConstructorArg(Object value) {
return addConstructorArgValue(value);
}
/**
* Add an indexed constructor arg value. The current index is tracked internally
* and all additions are at the present point.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -151,7 +151,7 @@ class ConstructorResolver {
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
AutowireUtils.sortConstructors(candidates);
@@ -609,8 +609,8 @@ class ConstructorResolver {
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
@@ -666,8 +666,8 @@ class ConstructorResolver {
boolean autowiring) throws UnsatisfiedDependencyException {
String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
@@ -768,12 +768,13 @@ class ConstructorResolver {
private Object[] resolvePreparedArguments(
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
Object[] resolvedArgs = new Object[argsToResolve.length];
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
Object argValue = argsToResolve[argIndex];
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,7 +32,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -333,44 +332,47 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
@Override
@SuppressWarnings("unchecked")
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
String[] beanNames = getBeanNamesForType(requiredType);
if (beanNames.length > 1) {
ArrayList<String> autowireCandidates = new ArrayList<String>();
for (String beanName : beanNames) {
String[] candidateNames = getBeanNamesForType(requiredType);
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
for (String beanName : candidateNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (autowireCandidates.size() > 0) {
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
}
}
if (beanNames.length == 1) {
return getBean(beanNames[0], requiredType, args);
if (candidateNames.length == 1) {
return getBean(candidateNames[0], requiredType, args);
}
else if (beanNames.length > 1) {
Map<String, Object> candidates = new HashMap<String, Object>();
for (String beanName : beanNames) {
else if (candidateNames.length > 1) {
Map<String, Object> candidates = new LinkedHashMap<String, Object>();
for (String beanName : candidateNames) {
candidates.put(beanName, getBean(beanName, requiredType, args));
}
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return getBean(primaryCandidate, requiredType, args);
return (T) candidates.get(primaryCandidate);
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return getBean(priorityCandidate, requiredType, args);
return (T) candidates.get(priorityCandidate);
}
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
else if (getParentBeanFactory() != null) {
return getParentBeanFactory().getBean(requiredType, args);
}
else {
throw new NoSuchBeanDefinitionException(requiredType);
BeanFactory parent = getParentBeanFactory();
if (parent != null) {
return parent.getBean(requiredType, args);
}
throw new NoSuchBeanDefinitionException(requiredType);
}
@@ -615,10 +617,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue) {
Assert.notNull(dependencyType, "Type must not be null");
Assert.notNull(dependencyType, "Dependency type must not be null");
if (autowiredValue != null) {
Assert.isTrue((autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue)),
"Value [" + autowiredValue + "] does not implement specified type [" + dependencyType.getName() + "]");
if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
throw new IllegalArgumentException("Value [" + autowiredValue +
"] does not implement specified dependency type [" + dependencyType.getName() + "]");
}
this.resolvableDependencies.put(dependencyType, autowiredValue);
}
}
@@ -648,13 +652,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
else if (containsSingleton(beanName)) {
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
}
else if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((DefaultListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor, resolver);
return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
}
else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
else if (parent instanceof ConfigurableListableBeanFactory) {
// If no DefaultListableBeanFactory, can't pass the resolver along.
return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
}
else {
return true;
@@ -995,23 +1001,24 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
//---------------------------------------------------------------------
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType()) {
return new DependencyObjectFactory(descriptor, beanName);
return new DependencyObjectFactory(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
return new DependencyProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
@@ -1316,9 +1323,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (containsBeanDefinition(beanName)) {
return getMergedLocalBeanDefinition(beanName).isPrimary();
}
BeanFactory parentFactory = getParentBeanFactory();
return (parentFactory instanceof DefaultListableBeanFactory &&
((DefaultListableBeanFactory) parentFactory).isPrimary(beanName, beanInstance));
BeanFactory parent = getParentBeanFactory();
return (parent instanceof DefaultListableBeanFactory &&
((DefaultListableBeanFactory) parent).isPrimary(beanName, beanInstance));
}
/**
@@ -1471,7 +1478,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
public DependencyObjectFactory(DependencyDescriptor descriptor, String beanName) {
this.descriptor = new DependencyDescriptor(descriptor);
this.descriptor.increaseNestingLevel();
this.optional = this.descriptor.getDependencyType().equals(javaUtilOptionalClass);
this.optional = (this.descriptor.getDependencyType() == javaUtilOptionalClass);
this.beanName = beanName;
}
@@ -1535,13 +1542,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (beanDefinition == null) {
return null;
}
List<Object> sources = new ArrayList<Object>();
List<Object> sources = new ArrayList<Object>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
}
Class<?> targetType = beanDefinition.getTargetType();
if (targetType != null && !targetType.equals(obj.getClass())) {
if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType);
}
return sources.toArray(new Object[sources.size()]);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -449,10 +449,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
}
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
String canonicalName = canonicalName(beanName);
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -300,7 +300,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
catch (IllegalArgumentException ex) {
throw new BeanDefinitionValidationException("Couldn't find a unique destroy method on bean with name '" +
throw new BeanDefinitionValidationException("Could not find unique destroy method on bean with name '" +
this.beanName + ": " + ex.getMessage());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,7 @@
package org.springframework.beans.factory.support;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -35,7 +35,10 @@ import java.util.Set;
*/
public class MethodOverrides {
private final Set<MethodOverride> overrides = new LinkedHashSet<MethodOverride>(0);
private final Set<MethodOverride> overrides =
Collections.synchronizedSet(new LinkedHashSet<MethodOverride>(0));
private volatile boolean modified = false;
/**
@@ -57,7 +60,8 @@ public class MethodOverrides {
*/
public void addOverrides(MethodOverrides other) {
if (other != null) {
this.overrides.addAll(other.getOverrides());
this.modified = true;
this.overrides.addAll(other.overrides);
}
}
@@ -65,6 +69,7 @@ public class MethodOverrides {
* Add the given method override.
*/
public void addOverride(MethodOverride override) {
this.modified = true;
this.overrides.add(override);
}
@@ -74,6 +79,7 @@ public class MethodOverrides {
* @see MethodOverride
*/
public Set<MethodOverride> getOverrides() {
this.modified = true;
return this.overrides;
}
@@ -81,7 +87,7 @@ public class MethodOverrides {
* Return whether the set of method overrides is empty.
*/
public boolean isEmpty() {
return this.overrides.isEmpty();
return (!this.modified || this.overrides.isEmpty());
}
/**
@@ -90,13 +96,18 @@ public class MethodOverrides {
* @return the method override, or {@code null} if none
*/
public MethodOverride getOverride(Method method) {
MethodOverride match = null;
for (MethodOverride candidate : this.overrides) {
if (candidate.matches(method)) {
match = candidate;
}
if (!this.modified) {
return null;
}
synchronized (this.overrides) {
MethodOverride match = null;
for (MethodOverride candidate : this.overrides) {
if (candidate.matches(method)) {
match = candidate;
}
}
return match;
}
return match;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
@@ -125,7 +125,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
setBeanClass(beanClass);
setAutowireMode(autowireMode);
if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,7 +18,6 @@ package org.springframework.beans.factory.support;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -59,7 +58,7 @@ import org.springframework.util.StringUtils;
public class StaticListableBeanFactory implements ListableBeanFactory {
/** Map from bean name to bean instance */
private final Map<String, Object> beans = new HashMap<String, Object>();
private final Map<String, Object> beans = new LinkedHashMap<String, Object>();
/**
@@ -265,7 +264,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
throws BeansException {
boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type));
Map<String, T> matches = new HashMap<String, T>();
Map<String, T> matches = new LinkedHashMap<String, T>();
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
String beanName = entry.getKey();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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,14 +24,13 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link java.beans.PropertyEditor} implementation for
* {@link java.beans.PropertyEditor} implementation for standard JDK
* {@link java.util.ResourceBundle ResourceBundles}.
*
* <p>Only supports conversion <i>from</i> a String, but not
* <i>to</i> a String.
* <p>Only supports conversion <i>from</i> a String, but not <i>to</i> a String.
*
* Find below some examples of using this class in a
* (properly configured) Spring container using XML-based metadata:
* Find below some examples of using this class in a (properly configured)
* Spring container using XML-based metadata:
*
* <pre class="code"> &lt;bean id="errorDialog" class="..."&gt;
* &lt;!--
@@ -62,19 +61,20 @@ import org.springframework.util.StringUtils;
* &lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* <p>Please note that this {@link java.beans.PropertyEditor} is
* <b>not</b> registered by default with any of the Spring infrastructure.
* <p>Please note that this {@link java.beans.PropertyEditor} is <b>not</b>
* registered by default with any of the Spring infrastructure.
*
* <p>Thanks to David Leal Valmana for the suggestion and initial prototype.
*
* @author Rick Evans
* @author Juergen Hoeller
* @since 2.0
*/
public class ResourceBundleEditor extends PropertyEditorSupport {
/**
* The separator used to distinguish between the base name and the
* locale (if any) when {@link #setAsText(String) converting from a String}.
* The separator used to distinguish between the base name and the locale
* (if any) when {@link #setAsText(String) converting from a String}.
*/
public static final String BASE_NAME_SEPARATOR = "_";
@@ -82,25 +82,23 @@ public class ResourceBundleEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
Assert.hasText(text, "'text' must not be empty");
ResourceBundle bundle;
String rawBaseName = text.trim();
int indexOfBaseNameSeparator = rawBaseName.indexOf(BASE_NAME_SEPARATOR);
if (indexOfBaseNameSeparator == -1) {
bundle = ResourceBundle.getBundle(rawBaseName);
String name = text.trim();
int separator = name.indexOf(BASE_NAME_SEPARATOR);
if (separator == -1) {
setValue(ResourceBundle.getBundle(name));
}
else {
// it potentially has locale information
String baseName = rawBaseName.substring(0, indexOfBaseNameSeparator);
// The name potentially contains locale information
String baseName = name.substring(0, separator);
if (!StringUtils.hasText(baseName)) {
throw new IllegalArgumentException("Bad ResourceBundle name : received '" + text + "' as argument to 'setAsText(String value)'.");
throw new IllegalArgumentException("Invalid ResourceBundle name: '" + text + "'");
}
String localeString = rawBaseName.substring(indexOfBaseNameSeparator + 1);
String localeString = name.substring(separator + 1);
Locale locale = StringUtils.parseLocaleString(localeString);
bundle = (StringUtils.hasText(localeString))
? ResourceBundle.getBundle(baseName, locale)
: ResourceBundle.getBundle(baseName);
setValue((StringUtils.hasText(localeString)) ? ResourceBundle.getBundle(baseName, locale) :
ResourceBundle.getBundle(baseName));
}
setValue(bundle);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -194,6 +194,19 @@ public class BeanWrapperTests extends AbstractPropertyAccessorTests {
assertEquals("x", accessor.getPropertyValue("object.name"));
}
@Test
public void incompletelyQuotedKeyLeadsToPropertyException() {
TestBean target = new TestBean();
try {
BeanWrapper accessor = createAccessor(target);
accessor.setPropertyValue("[']", "foobar");
fail("Should throw exception on invalid property");
}
catch (NotWritablePropertyException ex) {
assertNull(ex.getPossibleMatches());
}
}
@SuppressWarnings("unused")
private static class GetterBean {
@@ -212,6 +225,7 @@ public class BeanWrapperTests extends AbstractPropertyAccessorTests {
}
}
@SuppressWarnings("unused")
private static class IntelliBean {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -2890,7 +2890,13 @@ public class DefaultListableBeanFactoryTests {
}
public static class BeanWithDestroyMethod {
public static abstract class BaseClassWithDestroyMethod {
public abstract BaseClassWithDestroyMethod close();
}
public static class BeanWithDestroyMethod extends BaseClassWithDestroyMethod {
private static int closeCount = 0;
@@ -2900,8 +2906,10 @@ public class DefaultListableBeanFactoryTests {
this.inner = inner;
}
public void close() {
@Override
public BeanWithDestroyMethod close() {
closeCount++;
return this;
}
}
@@ -45,6 +45,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.Order;
import org.springframework.tests.sample.beans.ITestBean;
@@ -1397,6 +1398,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(1, bean.stringRepositoryMap.size());
assertSame(repo, bean.repositoryMap.get("repo"));
assertSame(repo, bean.stringRepositoryMap.get("repo"));
assertArrayEquals(new String[] {"repo"}, bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class)));
}
@Test
@@ -1777,6 +1780,9 @@ public class AutowiredAnnotationBeanPostProcessorTests {
GenericInterface1Impl bean1 = (GenericInterface1Impl) bf.getBean("bean1");
GenericInterface2Impl bean2 = (GenericInterface2Impl) bf.getBean("bean2");
assertSame(bean2, bean1.gi2);
assertArrayEquals(new String[] {"bean1"}, bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(GenericInterface1.class, String.class)));
assertArrayEquals(new String[] {"bean2"}, bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(GenericInterface2.class, String.class)));
}
@Test
@@ -2765,7 +2771,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
public interface GenericInterface1<T> {
public String doSomethingGeneric(T o);
String doSomethingGeneric(T o);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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 ReaderEditorTests {
@Test(expected = IllegalArgumentException.class)
public void testCtorWithNullResourceEditor() throws Exception {
new InputStreamEditor(null);
new ReaderEditor(null);
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2015 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,9 +28,10 @@ import static org.junit.Assert.*;
* @author Rick Evans
* @author Chris Beams
*/
public final class ResourceBundleEditorTests {
public class ResourceBundleEditorTests {
private static final String BASE_NAME = ResourceBundleEditorTests.class.getName();
private static final String MESSAGE_KEY = "punk";
@@ -40,7 +41,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME);
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals(MESSAGE_KEY, string);
@@ -52,7 +54,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "_");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals(MESSAGE_KEY, string);
@@ -64,7 +67,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "Lang" + "_en");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals("yob", string);
@@ -76,7 +80,8 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "LangCountry" + "_en_GB");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals("chav", string);
@@ -88,31 +93,32 @@ public final class ResourceBundleEditorTests {
editor.setAsText(BASE_NAME + "LangCountryDialect" + "_en_GB_GLASGOW");
Object value = editor.getValue();
assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).",
value instanceof ResourceBundle);
ResourceBundle bundle = (ResourceBundle) value;
String string = bundle.getString(MESSAGE_KEY);
assertEquals("ned", string);
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithNull() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText(null);
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithEmptyString() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText("");
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithWhiteSpaceString() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText(" ");
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextWithJustSeparatorString() throws Exception {
ResourceBundleEditor editor = new ResourceBundleEditor();
editor.setAsText("_");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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,20 +36,21 @@ import org.springframework.beans.factory.parsing.ReaderEventListener;
*/
public class CollectingReaderEventListener implements ReaderEventListener {
private final List defaults = new LinkedList();
private final List<DefaultsDefinition> defaults = new LinkedList<>();
private final Map componentDefinitions = new LinkedHashMap<>(8);
private final Map<String, ComponentDefinition> componentDefinitions = new LinkedHashMap<>(8);
private final Map aliasMap = new LinkedHashMap<>(8);
private final Map<String, List<AliasDefinition>> aliasMap = new LinkedHashMap<>(8);
private final List<ImportDefinition> imports = new LinkedList<>();
private final List imports = new LinkedList();
@Override
public void defaultsRegistered(DefaultsDefinition defaultsDefinition) {
this.defaults.add(defaultsDefinition);
}
public List getDefaults() {
public List<DefaultsDefinition> getDefaults() {
return Collections.unmodifiableList(this.defaults);
}
@@ -59,27 +60,27 @@ public class CollectingReaderEventListener implements ReaderEventListener {
}
public ComponentDefinition getComponentDefinition(String name) {
return (ComponentDefinition) this.componentDefinitions.get(name);
return this.componentDefinitions.get(name);
}
public ComponentDefinition[] getComponentDefinitions() {
Collection collection = this.componentDefinitions.values();
return (ComponentDefinition[]) collection.toArray(new ComponentDefinition[collection.size()]);
Collection<ComponentDefinition> collection = this.componentDefinitions.values();
return collection.toArray(new ComponentDefinition[collection.size()]);
}
@Override
public void aliasRegistered(AliasDefinition aliasDefinition) {
List aliases = (List) this.aliasMap.get(aliasDefinition.getBeanName());
if(aliases == null) {
aliases = new ArrayList();
List<AliasDefinition> aliases = this.aliasMap.get(aliasDefinition.getBeanName());
if (aliases == null) {
aliases = new ArrayList<>();
this.aliasMap.put(aliasDefinition.getBeanName(), aliases);
}
aliases.add(aliasDefinition);
}
public List getAliases(String beanName) {
List aliases = (List) this.aliasMap.get(beanName);
return aliases == null ? null : Collections.unmodifiableList(aliases);
public List<AliasDefinition> getAliases(String beanName) {
List<AliasDefinition> aliases = this.aliasMap.get(beanName);
return (aliases != null ? Collections.unmodifiableList(aliases) : null);
}
@Override
@@ -87,7 +88,7 @@ public class CollectingReaderEventListener implements ReaderEventListener {
this.imports.add(importDefinition);
}
public List getImports() {
public List<ImportDefinition> getImports() {
return Collections.unmodifiableList(this.imports);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -223,7 +223,7 @@ public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOt
@Override
public ITestBean[] getSpouses() {
return (spouse != null ? new ITestBean[]{spouse} : null);
return (spouse != null ? new ITestBean[] {spouse} : null);
}
public String getTouchy() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -81,7 +81,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
/**
* Set the name of the EhCache CacheManager (if a specific name is desired).
* @see net.sf.ehcache.CacheManager#setName(String)
* @see net.sf.ehcache.config.Configuration#setName(String)
*/
public void setCacheManagerName(String cacheManagerName) {
this.cacheManagerName = cacheManagerName;
@@ -126,12 +126,17 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void afterPropertiesSet() throws CacheException {
logger.info("Initializing EhCache CacheManager");
if (logger.isInfoEnabled()) {
logger.info("Initializing EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
Configuration configuration = (this.configLocation != null ?
EhCacheManagerUtils.parseConfiguration(this.configLocation) : ConfigurationFactory.parseConfiguration());
if (this.cacheManagerName != null) {
configuration.setName(this.cacheManagerName);
}
if (this.shared) {
// Old-school EhCache singleton sharing...
// No way to find out whether we actually created a new CacheManager
@@ -178,7 +183,10 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void destroy() {
if (this.locallyManaged) {
logger.info("Shutting down EhCache CacheManager");
if (logger.isInfoEnabled()) {
logger.info("Shutting down EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
this.cacheManager.shutdown();
}
}
@@ -7,6 +7,6 @@
* <p>Note: EhCache 3.x lives in a different package namespace
* and is not covered by the traditional support classes here.
* Instead, consider using it through JCache (JSR-107), with
* Spring's support in {@link org.springframework.cache.jcache}.
* Spring's support in {@code org.springframework.cache.jcache}.
*/
package org.springframework.cache.ehcache;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -134,7 +134,7 @@ public class TimerManagerTaskScheduler extends TimerManagerAccessor implements T
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(System.currentTimeMillis() - this.timer.getScheduledExecutionTime(), TimeUnit.MILLISECONDS);
return unit.convert(this.timer.getScheduledExecutionTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -237,7 +237,9 @@ public class CronTriggerFactoryBean implements FactoryBean<CronTrigger>, BeanNam
CronTriggerImpl cti = new CronTriggerImpl();
cti.setName(this.name);
cti.setGroup(this.group);
cti.setJobKey(this.jobDetail.getKey());
if (this.jobDetail != null) {
cti.setJobKey(this.jobDetail.getKey());
}
cti.setJobDataMap(this.jobDataMap);
cti.setStartTime(this.startTime);
cti.setCronExpression(this.cronExpression);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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,6 @@
package org.springframework.scheduling.quartz;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@@ -73,43 +72,50 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
}
@Override
@SuppressWarnings("rawtypes")
public Class loadClass(String name) throws ClassNotFoundException {
public Class<?> loadClass(String name) throws ClassNotFoundException {
return this.resourceLoader.getClassLoader().loadClass(name);
}
@SuppressWarnings("unchecked")
public <T> Class<? extends T> loadClass(String name, Class<T> clazz) throws ClassNotFoundException {
return loadClass(name);
return (Class<? extends T>) loadClass(name);
}
@Override
public URL getResource(String name) {
Resource resource = this.resourceLoader.getResource(name);
try {
return resource.getURL();
if (resource.exists()) {
try {
return resource.getURL();
}
catch (IOException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Could not load " + resource);
}
return null;
}
}
catch (FileNotFoundException ex) {
return null;
}
catch (IOException ex) {
logger.warn("Could not load " + resource);
return null;
else {
return getClassLoader().getResource(name);
}
}
@Override
public InputStream getResourceAsStream(String name) {
Resource resource = this.resourceLoader.getResource(name);
try {
return resource.getInputStream();
if (resource.exists()) {
try {
return resource.getInputStream();
}
catch (IOException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Could not load " + resource);
}
return null;
}
}
catch (FileNotFoundException ex) {
return null;
}
catch (IOException ex) {
logger.warn("Could not load " + resource);
return null;
else {
return getClassLoader().getResourceAsStream(name);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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,7 +228,9 @@ public class SimpleTriggerFactoryBean implements FactoryBean<SimpleTrigger>, Bea
SimpleTriggerImpl sti = new SimpleTriggerImpl();
sti.setName(this.name);
sti.setGroup(this.group);
sti.setJobKey(this.jobDetail.getKey());
if (this.jobDetail != null) {
sti.setJobKey(this.jobDetail.getKey());
}
sti.setJobDataMap(this.jobDataMap);
sti.setStartTime(this.startTime);
sti.setRepeatInterval(this.repeatInterval);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -72,8 +72,8 @@ public class SpringBeanJobFactory extends AdaptableJobFactory implements Schedul
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object job = super.createJobInstance(bundle);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
if (isEligibleForPropertyPopulation(bw.getWrappedInstance())) {
if (isEligibleForPropertyPopulation(job)) {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
MutablePropertyValues pvs = new MutablePropertyValues();
if (this.schedulerContext != null) {
pvs.addPropertyValues(this.schedulerContext);
@@ -0,0 +1,41 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.quartz;
import java.text.ParseException;
import org.junit.Test;
import org.quartz.CronTrigger;
import static org.junit.Assert.*;
/**
* @author Stephane Nicoll
*/
public class CronTriggerFactoryBeanTests {
@Test
public void createWithoutJobDetail() throws ParseException {
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setName("myTrigger");
factory.setCronExpression("0 15 10 ? * *");
factory.afterPropertiesSet();
CronTrigger trigger = factory.getObject();
assertEquals("0 15 10 ? * *", trigger.getCronExpression());
}
}

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