Compare commits

...

320 Commits

Author SHA1 Message Date
Chris Beams 4f9593da1c Fix typo in reference documentation
Issue: SPR-9321
2012-04-13 20:39:35 +03:00
Chris Beams aac21fdcec Update reference doc copyright year to 2012 2012-04-13 20:35:05 +03:00
Chris Beams dfd75352d3 Ignore spring-build 'docbook' directory 2011-12-22 22:23:45 +01:00
Chris Beams 6316448453 Increment version to 3.0.8.BUILD-SNAPSHOT 2011-12-22 22:23:45 +01:00
Chris Beams 40015e3de3 Release Spring Framework 3.0.7.RELEASE 2011-12-22 22:23:34 +01:00
Chris Beams 5e448af903 Update doc publication urls to static.s2.org 2011-12-22 22:17:56 +01:00
Chris Beams 1f3ce640c9 Add source directories to quell Eclipse errors 2011-12-22 18:15:18 +01:00
Juergen Hoeller cca44f411e added test for correct handling of ParseException from Formatter for String->String case (SPR-8944) 2011-12-22 15:19:59 +01:00
Juergen Hoeller 9b0412f35f fixed NamedParameterJdbcTemplate to use correct maximum type for queryForInt/Long (SPR-8652) 2011-12-22 13:12:22 +01:00
Juergen Hoeller 7eee3b9926 extended test time limits (in order o make the 3.0.x CI build plan happy) 2011-12-22 13:00:15 +01:00
Juergen Hoeller b5a279d2c8 final preparations for 3.0.7 2011-12-22 03:05:56 +01:00
Juergen Hoeller 0862a29066 "file-encoding" attribute value is being applied correctly (SPR-8024) 2011-12-22 03:05:40 +01:00
Juergen Hoeller 8d83f6966e Hibernate synchronization properly unbinds Session even in case of afterCompletion exception (SPR-8757) 2011-12-22 02:58:25 +01:00
Juergen Hoeller ce5117c9ed prepared for 3.0.7 release 2011-12-22 02:29:12 +01:00
Juergen Hoeller 836e3c9253 refined collection element conversion (SPR-8674) 2011-12-22 02:14:55 +01:00
Juergen Hoeller 2006eecb18 IntelliJ IDEA 11 project setup 2011-12-21 22:36:45 +01:00
Chris Beams 91287828f7 Preserve empty src/main/java dirs for ant build
Following the move to git, empty dirs are not tracked. Add .gitignore
files as necessary to keep the ant build happy.
2011-12-19 17:07:40 +01:00
Chris Beams efd2fc7688 Increment version to 3.0.7.BUILD-SNAPSHOT 2011-12-19 15:35:48 +01:00
Juergen Hoeller 74b5487a28 IntelliJ IDEA 11 project setup 2011-12-19 15:35:48 +01:00
Chris Beams 2882ae29b2 Add spring-build 2.5.2
spring-build was previously included via an svn:external. Adding
directly to the source tree under Git to avoid the need for a git
submodule.

In order to build from any earlier commit, it is recommended to
export spring-build or symlink an existing copy into the root
of the spring-framework project and then build normally.

    $ svn export https://src.springsource.org/svn/spring-build/tags/project-build-2.5.2 spring-build
2011-12-19 15:35:48 +01:00
Juergen Hoeller 4a7b96c4ca take element/key/value objects into account for the best possible type descriptor 2011-12-12 00:44:38 +00:00
Juergen Hoeller 7398e0ea97 polishing 2011-12-11 23:07:27 +00:00
Juergen Hoeller beaad20795 DataBinder etc 2011-12-11 22:11:50 +00:00
Juergen Hoeller 1bd84db56e polishing (alignment with 3.1 GA) 2011-12-11 22:06:59 +00:00
Juergen Hoeller 6316a45927 backported fix for SPR-8697 from 3.1 RC2 2011-12-11 22:06:28 +00:00
Juergen Hoeller e298c202af @Transactional qualifiers match against transaction manager definitions in parent contexts as well (SPR-7679) 2011-12-11 13:27:08 +00:00
Juergen Hoeller 288408e89f fixed assertion message 2011-12-09 16:01:30 +00:00
Juergen Hoeller 53a244d408 JmsInvokerClientInterceptor/FactoryBean always uses createConnection/createSession when on JMS 1.1 2011-12-09 12:07:45 +00:00
Juergen Hoeller 8213d0cb50 restored DataBinder's ability to bind to an auto-growing List with unknown element type (SPR-8828) 2011-12-07 21:25:54 +00:00
Juergen Hoeller b9868a498e ConversionService etc 2011-12-07 00:02:16 +00:00
Juergen Hoeller df7bdfa7c6 polishing 2011-12-06 22:50:48 +00:00
Juergen Hoeller f8402e9f82 ResourceHttpRequestHandler sends content without content-type header if no media type found (SPR-7713) 2011-12-06 22:50:33 +00:00
Juergen Hoeller 7eeb654eec ConversionService is able to work with "Collections.emptyList()" as target type (again; SPR-7293) 2011-12-06 21:18:13 +00:00
Juergen Hoeller b558c62953 polishing 2011-12-05 21:21:32 +00:00
Juergen Hoeller d64dd1943f consistent specification of standard meta-annotations 2011-12-03 15:47:29 +00:00
Juergen Hoeller bffa50e31a Portlet session mutex uses global session attribute to be shared among all portlets in the session (SPR-8888) 2011-12-02 12:03:43 +00:00
Juergen Hoeller 143cb50986 ConversionService prevents Converter from trying to convert to a subtype of its actual target type (SPR-8718) 2011-12-02 11:18:31 +00:00
Juergen Hoeller b3ccc438af conversion fixes etc 2011-12-01 18:50:11 +00:00
Juergen Hoeller 94513c1a28 fixed nested element conversion with a DataBinder + ConversionService + PropertyEditor (SPR-8674) 2011-12-01 18:49:53 +00:00
Juergen Hoeller c9607fdaf2 CollectionCollection/MapToMapConverter preserve original Collection/Map if no converted elements (SPR-8714) 2011-12-01 17:49:43 +00:00
Juergen Hoeller 7c108c1e77 updated H2 error codes in sql-error-codes.xml (SPR-8235, SPR-7480) 2011-12-01 14:07:04 +00:00
Juergen Hoeller 77372d7cdb fixed NamedParameterJdbcTemplate to use correct maximum type for queryForInt/Long (SPR-8652) 2011-12-01 13:59:24 +00:00
Juergen Hoeller 173f307ec9 backported header matching fix for correct processing of negated header conditions (SPR-8862) 2011-12-01 13:52:47 +00:00
Juergen Hoeller 2c987b0ffb backported DefaultResponseErrorHandler IOException fix (SPR-8713) 2011-12-01 13:33:51 +00:00
Juergen Hoeller 46a4ac9628 fixed ServletServerHttpRequest to reconstruct from "request.getParameterMap()" for form POST only (SPR-8688) 2011-12-01 13:27:25 +00:00
Juergen Hoeller c2997f4dd9 backported Java 6 visibility bridge method pair (SPR-8660) 2011-12-01 13:12:59 +00:00
Juergen Hoeller 0150000d8b backported TaskExecutorAdapter fix (SPR-8772) 2011-12-01 13:04:55 +00:00
Juergen Hoeller cad5eb836c allow for JDO 3.0 as well (SPR-8655) 2011-12-01 12:59:53 +00:00
Juergen Hoeller c82dab6497 backported public signatures in GenericTypeResolver (SPR-8005) 2011-12-01 12:52:33 +00:00
Juergen Hoeller e6f4e16219 backports from 3.1 RC2 2011-11-28 22:58:06 +00:00
Juergen Hoeller d0032f43c7 AbstractCachingViewResolver allows for caching unresolved view names ("cacheUnresolved"=true; SPR-8524) 2011-11-28 22:35:48 +00:00
Juergen Hoeller 8a43dd172c fixed getAsText javadoc (SPR-7890) 2011-11-28 21:14:47 +00:00
Juergen Hoeller 11aaefffbf refined Resource "exists()" check for HTTP URLs to always return false for 404 status (SPR-7881) 2011-11-28 21:12:08 +00:00
Juergen Hoeller c6b36cc207 JPA EntityManagerFactoryUtils silently ignores IllegalArgumentExceptions from setHint calls (SPR-7947) 2011-11-28 20:54:44 +00:00
Juergen Hoeller 5856db6f72 LinkedCaseInsensitiveMap overrides putAll method as well (for IBM JDK 1.6 compatibility; SPR-7969) 2011-11-28 20:48:10 +00:00
Juergen Hoeller 3c5e02a54a JDO PersistenceManager synchronization performs close attempt after completion (if necessary; SPR-8846) 2011-11-28 19:38:38 +00:00
Juergen Hoeller db0c921313 TransactionSynchronizationManager eagerly cleans up void ResourceHolders on any access (SPR-8844, SPR-8845) 2011-11-28 18:54:20 +00:00
Juergen Hoeller 641bc35a50 fixed setRootObject check in StandardEvaluationContext (SPR-8241) 2011-11-28 17:34:57 +00:00
Juergen Hoeller c166803d41 added "forwarder" property to ConnectorServerFactoryBean, accepting an MBeanServerForwarder (SPR-8820) 2011-11-28 17:17:56 +00:00
Juergen Hoeller 12e1784a99 Servlet/PortletContextResource's getFile prefers "file:" URL resolution over calling getRealPath (SPR-8461) 2011-11-28 16:51:52 +00:00
Juergen Hoeller bfabd58106 fixed "formMultiSelect"/"formCheckboxes" FreeMarker macros to compare against actual field value (SPR-7721) 2011-11-28 14:42:10 +00:00
Juergen Hoeller 540845e613 added getObjectMapper() accessor to MappingJacksonHttpMessageConverter (SPR-8605) 2011-11-28 14:35:08 +00:00
Juergen Hoeller 8e7982397c SimpleJdbcTestUtils executeSqlScript properly closes its LineNumberReader after use (SPR-8872) 2011-11-28 13:33:13 +00:00
Juergen Hoeller 84890ebc0d prepared for 3.0.7 2011-10-20 12:11:36 +00:00
Juergen Hoeller a9f28575b1 optimized DefaultListableBeanFactory's PropertyDescriptor caching for concurrent access (SPR-7863) 2011-10-20 12:06:40 +00:00
Juergen Hoeller a730bf47df LocaleEditor and StringToLocaleConverter do not restrict variant part through validation (SPR-8637) 2011-10-20 11:54:52 +00:00
Juergen Hoeller b5ec65cef6 fixed GenericTypeResolver to consistently return null if not resolvable (SPR-8698) 2011-10-20 11:21:39 +00:00
Juergen Hoeller 965c12b0f8 RmiClientInterceptor detects nested SocketException as connect failure as well (SPR-8628) 2011-10-20 11:10:23 +00:00
Juergen Hoeller 7187029ef6 added proper "contentLength()" implementation to ByteArrayResource (SPR-8709) 2011-10-20 11:03:41 +00:00
Juergen Hoeller 6363bb4b5b fixed Hibernate Validator import range 2011-08-18 23:15:16 +00:00
Juergen Hoeller 58ea5a702d backported autogrow fix: converted Collection differs from original Collection 2011-08-18 20:31:27 +00:00
Chris Beams 97b988ade8 Update pom versions to 3.0.6.BUILD-SNAPSHOT 2011-08-18 19:34:46 +00:00
Chris Beams 227234288f Backport rename JMX tests to avoid jmxremote_optional error
Issue: SPR-8089, SPR-8093, SPR-8458
2011-08-18 19:33:55 +00:00
Juergen Hoeller 05a7b65d43 backported NotificationListenerTests fixes 2011-08-18 19:05:31 +00:00
Juergen Hoeller cee6cb859d added test for month sequence (SPR-7807) 2011-08-17 21:01:39 +00:00
Juergen Hoeller 19c6a4e209 RequiredAnnotationBeanPostProcessor's skip attribute accepts "true" as String value as well (SPR-8617) 2011-08-16 22:41:45 +00:00
Juergen Hoeller b9089a8f9d final preparations for 3.0.6 2011-08-15 21:31:25 +00:00
Juergen Hoeller 7a20ed7d70 fixed timeout assertion 2011-08-15 21:29:15 +00:00
Juergen Hoeller 99588950d2 polishing 2011-08-15 21:24:41 +00:00
Juergen Hoeller a2129a132f consistent "connectTimeout" and "readTimeout" properties (SPR-8615) 2011-08-15 20:57:14 +00:00
Rossen Stoyanchev 0f1c10bc1c SPR-8612 Allow use of explicit status code in HTTP 1.0 compatibility mode 2011-08-15 13:02:48 +00:00
Juergen Hoeller 585745de32 added "connectTimeout" and "readTimeout" properties to SimpleClientHttpRequestFactory (SPR-8614) 2011-08-12 22:59:14 +00:00
Juergen Hoeller 65077d262c overridden @PersistenceContext annotations on subclass methods are being processed correctly (SPR-8594) 2011-08-12 13:54:44 +00:00
Juergen Hoeller da36c2b8b8 polishing 2011-08-12 10:03:28 +00:00
Juergen Hoeller 8f01770f29 backported "formatters" property to FormattingConversionServiceFactoryBean 2011-08-12 10:03:12 +00:00
Juergen Hoeller c51b9a7be2 removed GenericConversionService logging in order to avoid toString side effects (and to avoid isTraceEnabled overhead; SPR-8297) 2011-08-04 17:23:50 +00:00
Juergen Hoeller 3ffc0a2da2 SpringBeanAutowiringSupport is able to process @Value annotations on any given target instance (SPR-8574) 2011-08-03 10:20:04 +00:00
Juergen Hoeller acac25b2eb polishing 2011-08-02 19:19:22 +00:00
Juergen Hoeller cb0c0c503f ContentNegotiatingViewResolver properly handles invalid accept headers (SPR-7712) 2011-08-02 19:15:06 +00:00
Juergen Hoeller 215ccc2e10 final preparations for 3.0.6 2011-07-28 20:45:14 +00:00
Juergen Hoeller d95cbe23ee added support for web.xml context-param "springJspExpressionSupport" (explicit "true"/"false") 2011-07-28 20:26:07 +00:00
Juergen Hoeller ac1ffff9db general polishing (backported from 3.1) 2011-07-28 14:27:08 +00:00
Juergen Hoeller c0257aba9b accepts description subelement within map entry as well (as per the XSD; SPR-8563) 2011-07-28 11:14:26 +00:00
Juergen Hoeller 79aa661dd6 DefaultListableBeanFactory allows for init methods to register further bean definitions (again; SPR-7757) 2011-07-27 22:52:00 +00:00
Juergen Hoeller 18540debf6 backported locking enhancements for @MVC processing (SPR-7703) 2011-07-27 22:38:32 +00:00
Juergen Hoeller 7605707c18 backported @PathVariable matching fix (SPR-8543) 2011-07-27 22:31:17 +00:00
Juergen Hoeller d48c3b5d4f HtmlUtils properly escapes single quotes as well 2011-07-27 21:22:39 +00:00
Juergen Hoeller b122cf87df HtmlUtils properly escapes single quotes as well 2011-07-27 20:36:14 +00:00
Juergen Hoeller 183523d045 updated ResourceHttpRequestHandlerTests 2011-07-26 09:23:57 +00:00
Juergen Hoeller a4f62bb863 moved OpenSessionInViewTests back to orm module 2011-07-26 01:12:01 +00:00
Juergen Hoeller 80def4b695 copy css and js resources as well 2011-07-26 01:08:46 +00:00
Juergen Hoeller 42e18e6c4e fixed OpenEntityManagerInViewTests through the addition of a local copy of our Servlet API mocks; restoredOpenPersistenceManagerInViewTests 2011-07-26 00:52:15 +00:00
Juergen Hoeller d8767774c9 replaced TypeDescriptor synchronization with volatile variables (SPR-8559) 2011-07-25 16:31:46 +00:00
Juergen Hoeller f67e726be7 restored OpenEntityManagerInViewTests 2011-07-25 12:15:47 +00:00
Juergen Hoeller 41b9a461df ResourceHttpRequestHandler detects invalid directory traversal in given path (SPR-8515) 2011-07-25 10:57:39 +00:00
Juergen Hoeller 037497cb4f fixed ignored test 2011-07-21 10:35:05 +00:00
Juergen Hoeller 3ecb6b1a03 refined JBoss 6.0 note 2011-07-21 09:51:34 +00:00
Juergen Hoeller 6b92f66ebd final preparations for 3.0.6 release 2011-07-21 09:09:54 +00:00
Juergen Hoeller 070a723ef2 added "acceptProxyClasses" flag to RemoteInvocationSerializingExporter 2011-07-21 09:05:59 +00:00
Juergen Hoeller d4be29e661 updated javadoc for server-specific LoadTimeWeavers 2011-07-21 08:37:42 +00:00
Juergen Hoeller 3a3f15f144 improved ExposeInvocationInterceptor error message with respect to advice ordering (SPR-8544) 2011-07-21 07:39:11 +00:00
Juergen Hoeller 3edf8566ed fixed @ExceptionHandler exception type matching (ExceptionDepthComparator; SPR-8231) 2011-07-21 07:38:30 +00:00
Juergen Hoeller a2f00f205a collection/array conversion returns original collection if possible (SPR-8538); backported smarter element conversion check from 3.1 2011-07-20 19:57:40 +00:00
Juergen Hoeller 340a8b28f9 ConvertiblePair implements equals and hashCode (SPR-8459) 2011-07-19 15:54:36 +00:00
Juergen Hoeller 83c5753ae1 updated dependencies 2011-07-18 21:46:08 +00:00
Juergen Hoeller 67bb044a6f fixed whitespace 2011-07-18 21:33:45 +00:00
Juergen Hoeller 9ddfb375cb polishing 2011-07-18 20:49:58 +00:00
Juergen Hoeller 6fc6a9e80c fixed @Rule execution order in SpringJUnit4ClassRunner to match standard JUnit 4 behavior (SPR-8537) 2011-07-18 20:49:26 +00:00
Juergen Hoeller f18fa08aa0 ConfigurationClassPostProcessor supports use of same processor instance with several factories (SPR-8527) 2011-07-18 20:45:02 +00:00
Juergen Hoeller aa4ecdb79e fixed AccessControlContext applicability check 2011-07-15 14:43:33 +00:00
Juergen Hoeller 8041f6abdd polishing 2011-07-13 23:03:50 +00:00
Juergen Hoeller 210c77ddb0 SimpleClientHttpRequest uses fixed-length streaming mode (always sets content-length header); partial backport from 3.1 M2 2011-07-13 23:03:35 +00:00
Juergen Hoeller 24cb345b6c backported HttpHeadersTests update 2011-07-13 23:02:08 +00:00
Juergen Hoeller 0fdd7550b8 an EntityManagerFactoryBean is only deserializable through a SerializedEntityManagerFactoryBeanReference 2011-07-11 13:50:59 +00:00
Juergen Hoeller f1fb0e5330 prototype-based TargetSource is only deserializable through a SingletonTargetSource 2011-07-11 13:38:45 +00:00
Juergen Hoeller d4c2f63160 fixed package declaration 2011-07-04 22:05:21 +00:00
Juergen Hoeller b167f3f7a6 added JBoss dependency (SPR-8505); updated WebSphere dependency 2011-07-04 21:38:25 +00:00
Juergen Hoeller 63fe7bdd34 switched from readResolve to readObject 2011-07-04 21:21:56 +00:00
Juergen Hoeller 270db64243 optimized debug logging in case of non-convertible collection (SPR-8499) 2011-07-04 09:59:58 +00:00
Juergen Hoeller 15fd972417 DataBinder etc 2011-07-03 22:38:48 +00:00
Juergen Hoeller 10d9860457 ContextLoader and FrameworkServlet support "contextId" parameter for custom serialization id 2011-07-03 22:38:11 +00:00
Juergen Hoeller 01eab03dca added "autoGrowNestedPaths" property to ConfigurableWebBindingInitializer 2011-07-03 21:25:05 +00:00
Juergen Hoeller eb50eec85b DataBinder uses a default limit of 256 for array/collection auto-growing (SPR-7842) 2011-07-03 20:39:19 +00:00
Juergen Hoeller 4faa5af3f8 backported bridge method detection for class hierarchies with mixed visibilities (SPR-7900) 2011-06-22 21:25:50 +00:00
Juergen Hoeller 218e64cc80 DefaultListableBeanFactory etc 2011-06-22 20:58:23 +00:00
Juergen Hoeller b82edcca04 DefaultListableBeanFactory is only deserializable through a SerializedBeanFactoryReference 2011-06-22 20:55:44 +00:00
Juergen Hoeller d8a4949faf getBean(name, type) attempts type conversion if necessary (SPR-8480) 2011-06-22 20:53:38 +00:00
Costin Leau 22739bebf3 + fix incorrect junit version in ivy.xml 2011-06-17 07:55:57 +00:00
Juergen Hoeller fece2c1125 restored support for String-to-ContextResource conversion (SPR-8383) 2011-06-15 15:46:41 +00:00
Juergen Hoeller 8b55b34d79 consistent dependency on Hibernate Validator 4.1.0.GA 2011-06-14 21:39:41 +00:00
Juergen Hoeller d1e998bedd refined WebLogic RMI descriptor to only mark 'getTargetInterfaceName' method as idempotent (SPR-8369) 2011-06-14 15:10:00 +00:00
Juergen Hoeller 2ddb14ae5b refined EntityManagerFactory proxy exception (SPR-4383) 2011-06-14 15:03:34 +00:00
Juergen Hoeller ae74fbdd4b prepared for 3.0.6 release 2011-06-14 00:13:15 +00:00
Juergen Hoeller 28769e906f ConversionService, CachedConnectionFactory, etc 2011-06-14 00:06:51 +00:00
Juergen Hoeller 47c21bf73b fixed NamedParameterJdbcTemplate's handling of arrays as query parameters (SPR-7699) 2011-06-14 00:03:57 +00:00
Juergen Hoeller 59fda2dbab restored original GenericConversionService behavior with respect to empty collections/maps; restored original FormattingConversionService behavior with respect to the use of subtypes; fixed collection element resolution when using a ConversionService with a DataBinder 2011-06-13 23:57:37 +00:00
Juergen Hoeller 43f8eca91b restored original GenericConversionService behavior with respect to empty collections/maps; restored original FormattingConversionService behavior with respect to the use of subtypes; fixed collection element resolution when using a ConversionService with a DataBinder 2011-06-13 23:40:22 +00:00
Juergen Hoeller 6cb6bd751e revised JMS CachedConnectionFactory to avoid unnecessary rollback calls on Session return (SPR-8437); fixed JMS CachedConnectionFactory to fully synchronize its Session list (SPR-8436) 2011-06-13 22:33:02 +00:00
Juergen Hoeller 58d68cef98 restored original ConversionService behavior with respect to empty collections/maps (SPR-7728) 2011-06-13 22:03:00 +00:00
Juergen Hoeller 5f3f30fdb4 revised JMS CachedConnectionFactory to avoid unnecessary rollback calls on Session return (SPR-8437); fixed JMS CachedConnectionFactory to fully synchronize its Session list (SPR-8436) 2011-06-13 21:43:56 +00:00
Juergen Hoeller 7a6b2cfe1f shortened build properties "org.junit.version" to "junit.version" and "org.testng.version" to "testng.version"; reverted SLF4J version back to 1.5.3 (for Hibernate 3.3.1 compatibility) 2011-06-09 13:51:30 +00:00
Juergen Hoeller a8ab9af002 updated dependencies 2011-06-08 22:50:20 +00:00
Juergen Hoeller ca19b14f13 first bunch of backports from 3.1 M2 to 3.0.6 2011-06-08 22:49:41 +00:00
Juergen Hoeller 175f6d4bc5 2011-06-08 13:25:01 +00:00
Chris Beams 0206845341 Spring 3.0.5 2010-10-20 23:33:02 +00:00
Arjen Poutsma a37a9e8a38 SPR-7667 2010-10-20 13:59:37 +00:00
Juergen Hoeller 577755d580 polishing 2010-10-20 05:51:51 +00:00
Juergen Hoeller 610812949f prepared for 3.0.5 release 2010-10-20 05:48:25 +00:00
Juergen Hoeller 82ec515e59 declared JPA API as optional (SPR-6819) 2010-10-20 05:37:25 +00:00
Juergen Hoeller d418eed56f AbstractJasperReportsView only sets locale model attributes if not present already 2010-10-20 05:22:43 +00:00
Juergen Hoeller 244c96151e added consistent license header 2010-10-20 05:19:17 +00:00
Ramnivas Laddad 92298469bf Fixed configuration of AnnotationAsyncExecutionAspect (was incorrectly under the same name as that for transaction management aspect) 2010-10-17 22:33:30 +00:00
Juergen Hoeller bfd54f4f35 AnnotationAsyncExecutionAspect etc 2010-10-15 21:04:48 +00:00
Juergen Hoeller c5e53ee432 polishing 2010-10-15 20:50:51 +00:00
Juergen Hoeller 8c9b64c948 added mode="proxy"/"aspectj" and proxy-target-class options to task namespace; switched to concise names for async aspects 2010-10-15 20:50:23 +00:00
Thomas Risberg 171f1ee097 added additional parameter name matching using lowercase with Locale.ENGLISH (SPR-7658) 2010-10-15 15:56:59 +00:00
Juergen Hoeller be21358db7 reintroduced getHandler(request, cache) in deprecated form (after removing it in 3.0.4) 2010-10-15 14:05:22 +00:00
Juergen Hoeller 5da5fc6499 polishing 2010-10-15 08:44:03 +00:00
Chris Beams c7aaa85ef6 Add proper default values for 'merge' attributes in collection elements (SPR-7656) 2010-10-15 07:56:02 +00:00
Juergen Hoeller a25e4d794e Hibernate 3.6, etc 2010-10-14 23:10:08 +00:00
Juergen Hoeller 3c067e5db6 optimized AnnotationUtils findAnnotation performance for repeated search on same interfaces (SPR-7630) 2010-10-14 23:06:45 +00:00
Juergen Hoeller 0f924820e8 revised OracleTableMetaDataProvider for reliable Oracle Connection detection; autodetect JdbcTemplate's NativeJdbcExtractor (SPR-7611) 2010-10-14 21:25:14 +00:00
Juergen Hoeller 1f1577e33e fixed @Value injection to correctly cache temporary null results for non-singleton beans (SPR-7614) 2010-10-14 19:49:29 +00:00
Juergen Hoeller e1dbb66798 StringToArray/CollectionConverter trims element values before trying to convert them (SPR-7657) 2010-10-14 19:44:26 +00:00
Juergen Hoeller 1933b648c3 fixed @Value injection to correctly cache temporary null results for non-singleton beans (SPR-7614) 2010-10-14 19:40:36 +00:00
Juergen Hoeller 5cb06f5da2 consistent caching of @Autowired arguments in field and method case (SPR-7635) 2010-10-14 09:34:31 +00:00
Juergen Hoeller ffa4ed093f BeanWrapper etc 2010-10-14 00:30:38 +00:00
Juergen Hoeller 4c73a29f99 polishing 2010-10-14 00:30:07 +00:00
Juergen Hoeller 0195b0da3c BeanWrapper does not attempt to populate Map values on access (just auto-grows Map itself) 2010-10-14 00:14:50 +00:00
Juergen Hoeller 27a10c74d1 resolve dependency outside of synchronized block before subsequently preparing cached arguments (SPR-7635) 2010-10-13 23:22:57 +00:00
Juergen Hoeller 7893b3ebf6 applied synchronization in order to avoid race condition in skipping check (SPR-7635, SPR-7642) 2010-10-13 22:29:28 +00:00
Juergen Hoeller 21d6883139 moved async aspect to aspectj sub-package 2010-10-13 21:06:38 +00:00
Juergen Hoeller a6569a2930 moved async aspect to aspectj sub-package 2010-10-13 20:53:12 +00:00
Arjen Poutsma d9d7fb6f9a Docs 2010-10-13 14:19:48 +00:00
Arjen Poutsma 4108927b28 SPR-5367 - PathVariable mappings are greedy over hard coded mappings 2010-10-13 12:03:26 +00:00
Juergen Hoeller ac5b1bcfab fixed Autowired/CommonAnnotationBeanPostProcessor to prevent race condition in skipping check (SPR-7635, SPR-7642) 2010-10-12 22:56:38 +00:00
Arjen Poutsma c5c1d70aa3 SPR-6291 - UrlPathHelper is too aggressive decoding URLs 2010-10-12 12:09:43 +00:00
Arjen Poutsma 043ec2c8b2 SPR-7636 - XStreamMarshaller - Add support for configuring XStream with aliases by class (type) and also defining multiple attributes for the same class. 2010-10-12 11:55:29 +00:00
Arjen Poutsma 1f296403da SPR-7620 - StaxEventContentHandler does not set Location for StartDocument event 2010-10-12 09:50:39 +00:00
Arjen Poutsma 35da7bdb44 SPR-7621 - AbstractStaxContentHandler sets NamespaceContext on every start/end element 2010-10-12 09:41:23 +00:00
Arjen Poutsma ab21dbad08 SPR-7621 - AbstractStaxContentHandler sets NamespaceContext on every start/end element 2010-10-12 09:35:23 +00:00
Juergen Hoeller c32c0d5674 fixed package declaration 2010-10-11 21:26:32 +00:00
Juergen Hoeller e506ccf4e1 serializer package etc 2010-10-11 21:15:56 +00:00
Juergen Hoeller 0ef971b82b polishing 2010-10-11 21:15:26 +00:00
Juergen Hoeller b062de1133 revised initial cut of serializer package; moved Converter adapters to sub-package 'support' 2010-10-11 21:15:12 +00:00
Juergen Hoeller 3740380a7a polishing 2010-10-11 20:03:40 +00:00
Juergen Hoeller cb434793d5 avoid double flushing of ObjectOutputStream when close is being called right afterwards anyway 2010-10-11 20:00:45 +00:00
Oliver Gierke 9114f80b68 SPR-7641 - Added Principal to listing of supported method parameter types. 2010-10-11 19:59:16 +00:00
Juergen Hoeller ae3cfff380 fixed JodaTimeContextHolder to use a non-inheritable ThreadLocal and expose a reset method (SPR-7441); use of remove() even when being called with a null argument 2010-10-11 18:55:21 +00:00
Mark Fisher c046419acd SPR-7627 added Serializer and Deserializer strategies, Converter adapters, and default implementations 2010-10-11 17:36:18 +00:00
Thomas Risberg bd22bed10a added a SybaseAnywhereMaxValueIncrementer since syntax is slightly different than for Sybase ASE (SPR-7623) 2010-10-11 14:17:09 +00:00
Juergen Hoeller a0fead1880 revised TypedValue toString representation (SPR-7569) 2010-10-10 21:29:18 +00:00
Juergen Hoeller f7cd9865f4 polishing 2010-10-10 21:09:59 +00:00
Juergen Hoeller ebe8052d55 fixed detection of element type in case of nested collections (SPR-7569) 2010-10-10 21:09:43 +00:00
Juergen Hoeller 6b3c299a50 consistent handling of handler methods, init binder methods and model attribute methods (SPR-7355) 2010-10-10 21:01:04 +00:00
Juergen Hoeller 722778c74a SpEL MapAccessor consistently rejects "target.key" style access to Maps if no such key is found (SPR-7614) 2010-10-10 20:22:15 +00:00
Juergen Hoeller 1cd77e2a15 polishing 2010-10-10 20:11:53 +00:00
Juergen Hoeller 5be9473136 initialize cache Maps early, turning them into final fields 2010-10-10 20:11:44 +00:00
Juergen Hoeller 7553b76f15 SpEL method invocations prefer method with fewest parameters (e.g. no-arg over vararg; SPR-7633) 2010-10-10 19:23:01 +00:00
Juergen Hoeller d78eda8aeb polishing 2010-10-10 18:31:43 +00:00
Juergen Hoeller 061063257a optimized @Bean error messages (SPR-7628, SPR-7629) 2010-10-10 18:31:03 +00:00
Juergen Hoeller 4e43ba544b Jdbc4NativeJdbcExtractor etc 2010-10-09 23:08:23 +00:00
Juergen Hoeller ccded10d86 added configurable Connection/Statement/ResultSet target types to Jdbc4NativeJdbcExtractor (SPR-7613); added OracleJdbc4NativeJdbcExtractor with pre-configured Oracle JDBC API types 2010-10-09 23:04:50 +00:00
Juergen Hoeller 2433feab09 fixed embedded database exception test 2010-10-09 13:29:22 +00:00
Juergen Hoeller be04aca037 consistent handling of unwrap/isWrapperFor/isClosed in JDBC proxies 2010-10-09 12:38:37 +00:00
Juergen Hoeller 153680a5e6 polishing 2010-10-09 12:35:38 +00:00
Juergen Hoeller a15d023b45 ResourceDatabasePopulator throws descriptive ScriptStatementFailedException with resource details (SPR-7546) 2010-10-09 12:35:21 +00:00
Thomas Risberg 63b8ae085a added a nativeJdbcExtractor property for the TableMetaDataProvider and a method to specify the one to use for SImpleJdbcInsert (SPR-7611) 2010-10-08 18:28:01 +00:00
Oliver Gierke 1c6e131746 SPR-7604 - Support multiple embedded databases.
Added missing test configuration file.
2010-10-08 12:40:06 +00:00
Ramnivas Laddad 00984781af SPR-7369: @Async support in spring-aspects with AspectJ 2010-10-06 20:13:22 +00:00
Ramnivas Laddad e1fb19f4e1 SPR-7369: @Async support in spring-aspects with AspectJ 2010-10-06 20:12:15 +00:00
Arjen Poutsma 21cca695e5 Polishing 2010-10-06 12:05:11 +00:00
Oliver Gierke ba2bac17de SPR-7604 - Support multiple embedded databases.
Embedded datasources now get their bean ids set as database name to allow multiple databases of the same type in parallel. Refactored tests a little and made BeanDefinitionParser package private to align with the other ones. Adapted changelog accordingly.
2010-10-02 06:30:05 +00:00
Juergen Hoeller 5918e2fa9c preparations for 3.0.5 release 2010-10-02 01:29:35 +00:00
Juergen Hoeller 6d94c92d97 DefaultMessageListenerContainer's skips no-message-received commit on Tibco (avoiding a deadlock; SPR-7558) 2010-10-02 01:25:25 +00:00
Juergen Hoeller 3f0462510e getTestExecutionListeners() returns actual List which allows for iteration as well as modification (SPR-7595) 2010-10-02 01:05:40 +00:00
Juergen Hoeller 40fa8afce4 DispatcherPortlet's default resource serving explicitly prevents access to WEB-INF and META-INF (SPR-7540) 2010-10-02 00:03:09 +00:00
Juergen Hoeller aac2de9221 avoid ConcurrentModificationException when iterating attribute names (SPR-7557) 2010-10-01 22:27:34 +00:00
Juergen Hoeller cbab6fa59f reduced BeanDefinition footprint by initializing Sets and Maps with 0 2010-10-01 22:22:50 +00:00
Juergen Hoeller b7b2a25953 fixed ApplicationContext event processing for repeated invocations to non-singleton listener beans (SPR-7563) 2010-10-01 22:16:21 +00:00
Juergen Hoeller d9b54a524d revised "ClassUtils.isAssignable" semantics to cover primitives vs wrappers in both directions (SPR-7610) 2010-10-01 21:50:25 +00:00
Oliver Gierke 9008e08171 SPR-7651 - Document limitations of @Async.
* documented that @Async can't be used in conjunction with lifecycle callbacks such as @PostConstruct
* provide sample for workaround
* added semantic markup for code
2010-10-01 09:44:55 +00:00
Oliver Gierke eb0990b37e Formatting for scheduling.xml. 2010-10-01 09:44:52 +00:00
Oliver Gierke 1fc6de0403 SPR-7609 - Fixed typos in JMS documentation. 2010-10-01 06:52:08 +00:00
Oliver Gierke b467f2c858 SPR-7602 - Correctly shutdown Derby >= 10.6
The shutdown mechanism for in-memory databases has changed since 10.6. We now have to trigger 'drop' instead of 'shutdown'. Besides that we can skip purging the database manually in newer versions.
2010-09-30 17:56:41 +00:00
Juergen Hoeller e211c09065 fixed exists() check for resources in zipped files (SPR-7559) 2010-09-29 14:45:44 +00:00
Juergen Hoeller f88f69e700 AspectJExpressionPointcut uses bean ClassLoader for initializing the AspectJ pointcut parser (SPR-7570) 2010-09-29 14:31:23 +00:00
Juergen Hoeller eda6268d9d fixed findPlaceholderEndIndex to work with a custom suffix as well (SPR-7574) 2010-09-29 14:01:54 +00:00
Juergen Hoeller 668207d59d fixed Portlet UnavailableException tests (SPR-7542) 2010-09-29 13:45:50 +00:00
Juergen Hoeller 803b336354 fixed Portlet UnavailableException tests (SPR-7542) 2010-09-29 13:31:53 +00:00
Juergen Hoeller 4c154d3cab AnnotationSessionFactoryBean's "postProcessConfiguration" is non-final now (because of Hibernate 3.6; SPR-7581) 2010-09-29 13:22:24 +00:00
Juergen Hoeller 7ad191c912 made ResourceHttpRequestHandlerTests more reliable (SPR-7565) 2010-09-29 13:14:18 +00:00
Arjen Poutsma 70cb81b4b5 SPR-7591 - HttpStatusCodeException should contain response body 2010-09-24 10:06:52 +00:00
Costin Leau 6e516b7281 SPR-6819
+ change jpa Maven dependency from provided to compile
2010-09-21 23:14:22 +00:00
Jeremy Grelle aab05c4da9 Minor correction to doc updates made as part of SPR-7545 - "cache-period" attribute was incorrectly documented as "cache-seconds". 2010-09-17 18:50:01 +00:00
Chris Beams 562747ef41 Review recent documentation and default servlet changes
- Relocate and fix typos in interface-based @RequestMapping tip (SPR-7537)
- Fix typos in constructor-arg 'name' disambiguation section (SPR-7443)
- Polish whitespace in DefaultServletHttpRequestHandler (SPR-7553)
2010-09-15 08:45:21 +00:00
Oliver Gierke c1d2c36f32 SPR-7443 - Mentioned @ConstructorProperties in doc
If you want to reference parameters by name in XML
configuration you can also use @ConstructorProperties
to name the parameters in the class.
2010-09-15 08:13:12 +00:00
Oliver Gierke e8b9c6d5ff SPR-7443 - Constructor arg resolution by name (doc)
Added documentation on constructor argument 
disambiguation by using the argument names.
2010-09-15 06:37:05 +00:00
Thomas Risberg b2b195e2cf changed the access of the "reconcileColumnsToUse" and "reconcileParameters" methods to protected (SPR-7556) 2010-09-14 15:48:03 +00:00
Oliver Gierke 2c559aa8c8 SPR-7537 - Document proxying for MVC controllers
Extended documentation to include hints on what to 
consider when working with proxied controllers.
Explained the necessity of moving @RequestMapping
annotations to the interface or use proxy-target-
class="true".
2010-09-14 11:02:46 +00:00
Juergen Hoeller bf90a2ddb6 DispatcherPortlet throws custom NoHandlerFoundException instead of misleading UnavailableException (SPR-7542) 2010-09-14 06:43:53 +00:00
Juergen Hoeller a3f155220b UriTemplate is serializable now (SPR-7541) 2010-09-14 05:37:30 +00:00
Juergen Hoeller 6d4faa6c52 ApplicationContext registers context-specific ClassArrayEditor for its bean ClassLoader (SPR-1461) 2010-09-14 05:09:08 +00:00
Jeremy Grelle d8ecc76d4c SPR-7545 - Reference documentation now reflects the final state of the ResourceHttpRequestHandler and references the DefaultServletHttpRequestHandler properly. 2010-09-13 23:06:06 +00:00
Chris Beams 05bcc4028d Fix assumption about file-based Resources in PropertiesLoaderSupport (SPR-7547)
When using PropertiesLoaderSupport implementations (principally
PropertyPlaceholderConfigurer), an assumption was made that any
Resource representing a set of properties must be file-based.  SPR-7547
exposed the fact that if a non-file-based Resource implementation such
as ByteArrayResource were passed in, an IllegalStateException would be thrown
from the AbstractResource base class' implementation of getFilename().

This is now patched, and PropertiesLoaderSupport implementations treat
Resource implementations equally, regardless of file-orientation.

See also SPR-7552.
2010-09-13 20:23:26 +00:00
Jeremy Grelle 334a294e2a SPR-7553 - DefaultServletHttpRequestHandler fails on Google App Engine 2010-09-13 19:58:26 +00:00
Chris Beams 99f7142e3f Add @Ignored repro test for SPR-7538 2010-09-10 16:32:20 +00:00
Juergen Hoeller aa54518e2e final preparations for 3.0.5 2010-09-10 09:09:28 +00:00
Juergen Hoeller c2dab9c200 EmbeddedDatabaseFactory shuts down database when failing to populate it in initDatabase (SPR-7536) 2010-09-10 09:07:20 +00:00
Juergen Hoeller 609f91e1b4 final preparations for 3.0.5 2010-09-09 22:14:51 +00:00
Juergen Hoeller 87e7258c9a polishing 2010-09-09 22:14:36 +00:00
Juergen Hoeller 134e79c0fd clearly document behavior with respect to beans of same name at different factory levels (SPR-6117) 2010-09-09 22:12:23 +00:00
Chris Beams 08fb61316d Comment xsd-config-setup doc pending overhaul (SPR-7521) 2010-09-09 10:16:43 +00:00
Chris Beams 4b89069cab Polish whitespace in docs 2010-09-09 10:16:39 +00:00
Juergen Hoeller 5f2d88f74a polishing 2010-09-09 09:04:40 +00:00
Juergen Hoeller 53692a79e2 polishing 2010-09-09 08:13:49 +00:00
Juergen Hoeller b07a7be262 expression parser stuff 2010-09-08 22:53:54 +00:00
Juergen Hoeller 7a42ff16ac polishing 2010-09-08 22:53:39 +00:00
Juergen Hoeller f848e5081d updated version statement in javadoc 2010-09-08 22:48:03 +00:00
Juergen Hoeller 91a53a36ec LocalSessionFactoryBean's "entityCacheStrategies" works with region names on Hibernate 3.6 as well 2010-09-08 22:45:58 +00:00
Thomas Risberg 1247d2085b Polished the support for looking up column values by column label (SPR-7506) 2010-09-08 18:59:28 +00:00
Thomas Risberg 90636f66a8 Added support for looking up column values by column label to support CachedRowSetImpl which doesn't allow for column label use (SPR-7506); added some generics; 2010-09-08 18:46:21 +00:00
Juergen Hoeller c33df5977a pass full TypeDescriptor context through to ConversionService calls (SPR-7519) 2010-09-08 17:26:02 +00:00
Chris Beams 6f69b7b752 Allow class-relative resource loading in GenericXmlApplicationContext (SPR-7530)
Before:

    - new GenericXmlApplicationContext("com/acme/path/to/resource.xml");

    - GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
      ctx.load("com/acme/path/to/resource.xml");
      ctx.refresh();

After:

    - The above remain supported, as well as new class-relative variants

    - import com.acme.path.to.Foo;
      new GenericXmlApplicationContext(Foo.class, "resource.xml");

    - import com.acme.path.to.Foo;
      GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
      ctx.load(Foo.class, "resource.xml");
      ctx.refresh();

These changes are generally aligned with signatures long available in
ClassPathXmlApplicationContext. As GenericXmlApplicationContext is
intended to be a more flexible successor to CPXAC (and FSXAC), it's
important that all the same conveniences are available.
2010-09-08 15:30:48 +00:00
Juergen Hoeller 912d349366 @MVC fixes 2010-09-08 14:48:52 +00:00
Juergen Hoeller 284f98f12a fixed @MVC processing of parameter-level annotations to work with interface-based proxies again (SPR-7483) 2010-09-08 14:45:00 +00:00
Juergen Hoeller 907febd86e revised @RequestParam processing to support CSV-to-array/collection binding with ConversionService (SPR-7479) 2010-09-08 13:56:42 +00:00
Arjen Poutsma af7203b839 Added XMLEventStreamWriter 2010-09-08 12:52:23 +00:00
Juergen Hoeller a251d6a6cc revised @RequestParam processing to support CSV-to-array/collection binding with ConversionService (SPR-7479) 2010-09-08 12:39:57 +00:00
Arjen Poutsma 449337a544 Small Stax fixes. 2010-09-08 09:45:18 +00:00
Arjen Poutsma f92f295055 Small Stax fixes. 2010-09-08 08:42:09 +00:00
Juergen Hoeller 6a4bc3e39f further fixes for 3.0.5 2010-09-06 23:35:14 +00:00
Juergen Hoeller 88e0dcfa06 added MockMultipartFile to web-portlet module 2010-09-06 23:22:03 +00:00
Juergen Hoeller bd05b046d0 reverted shortening of action exception parameter value; fixed multipart test (SPR-7495) 2010-09-06 23:11:11 +00:00
Juergen Hoeller 7e5215b5d4 fixed typo 2010-09-06 22:56:18 +00:00
Juergen Hoeller ba946c08dd copy event parameters to render parameters in case of an action exception as well (SPR-7495) 2010-09-06 22:56:05 +00:00
Juergen Hoeller 3eda5144ae DispatcherPortlet copies all action parameters to render parameters in case of an action exception (SPR-7495); shortened Portlet MVC's action exception render parameter value to "true" 2010-09-06 22:45:31 +00:00
Juergen Hoeller e68f2f0a5f removed unused HandlerExecutionChain caching 2010-09-06 21:44:06 +00:00
Juergen Hoeller 45d9b0cb2d allow for writing the response directly in a Portlet @ExceptionHandler method (like in the Servlet equivalent) 2010-09-06 21:43:26 +00:00
Juergen Hoeller 66b4499973 polishing 2010-09-06 21:20:03 +00:00
Juergen Hoeller e035477e6a extended synchronization for methodResolverCache (SPR-7525) 2010-09-06 20:41:50 +00:00
Juergen Hoeller 479b4c1b84 added bean type to post-processing log statement (SPR-7524) 2010-09-06 20:06:48 +00:00
Juergen Hoeller 05a3f3ad8d avoid failures in case of manually registered null instance (SPR-7523) 2010-09-06 19:47:16 +00:00
Arjen Poutsma b67da6c3f8 Granting Keith's wish 2010-09-03 08:50:45 +00:00
Sam Brannen 0485f15998 Fixed typo 2010-09-01 23:38:51 +00:00
Juergen Hoeller b60a7a2e07 prepared for 3.0.5 2010-09-01 22:24:21 +00:00
Juergen Hoeller e6425ee41f polishing 2010-09-01 22:02:33 +00:00
Juergen Hoeller 0a17e41755 catch invalid arguments early; avoid stack overflow in object-to-collection case (SPR-7488) 2010-09-01 22:02:07 +00:00
Juergen Hoeller 055c343ce0 SpEL supports projection on any kind of Collection (SPR-7493) 2010-09-01 21:55:39 +00:00
Juergen Hoeller 3f68ccadd9 polishing 2010-09-01 18:41:10 +00:00
Juergen Hoeller 4e3227441b DefaultLobHandler's "wrapAsLob" mode works with PostgreSQL's getAsciiStream() requirement (SPR-7487) 2010-09-01 18:09:29 +00:00
Juergen Hoeller e56cfb8173 consistent use of JDK 1.5's ThreadLocal.remove() over ThreadLocal.set(null), preventing leaks (SPR-7441) 2010-09-01 17:17:25 +00:00
Juergen Hoeller 66a5bb7c22 JaxWsPortClientInterceptor does not fall back to annotation-specified name as portName anymore (SPR-7505) 2010-09-01 14:02:32 +00:00
Juergen Hoeller 82bcef037d JDBC bundle uses local ClassLoader as bean ClassLoader for "sql-error-codes.xml" parsing (SPR-7497) 2010-09-01 13:46:57 +00:00
Juergen Hoeller 5ddf8245dd fixed EvalTag's EvaluationContext caching (SPR-7482) 2010-09-01 13:33:45 +00:00
Juergen Hoeller 3e5aca86d5 fixed no-message-received commit case for non-cached Sessions (SPR-7478) 2010-09-01 11:21:40 +00:00
Juergen Hoeller d7e0776148 avoid hanging in case of shutdown errors (SPR-7511) 2010-09-01 11:19:11 +00:00
Arjen Poutsma 416004b1bc Fixing build 2010-08-31 15:48:42 +00:00
Arjen Poutsma 2182287d3e Minor tweaks 2010-08-31 10:46:58 +00:00
Arjen Poutsma e3298061d2 Added createCustomStaxSource/Result, because JAXP 1.4 kills babies in their sleep. 2010-08-31 09:51:59 +00:00
Arjen Poutsma 9aafa1c6b2 Various StAX improvements. 2010-08-27 11:35:27 +00:00
Chris Beams b72cca5403 Fix memory leak in serializable bean factory management (SPR-7502)
GenericApplicationContext and AbstractRefreshableApplicationContext
implementations now call DefaultListableBeanFactory.setSerializationId()
only upon successful refresh() instead of on instantiation of the
context, as was previously the case with GAC.

DLBF.setSerializationId() adds the beanFactory to the *static*
DLBF.serializableFactories map, and while calling close() on the
application context removes entries from that map, it does so only if
the context is currently active (i.e. refresh() has been called).

Also, cancelRefresh() has been overridden in GAC just as it has been
in ARAC to accomodate the possibility of a BeansException being thrown.
In this case, the beanFactory serializationId will be nulled out and
the beanFactory removed from the serializableFactories map.

The SerializableBeanFactoryMemoryLeakTests test case provides full
coverage of these scenarios.
2010-08-27 10:53:20 +00:00
Arjen Poutsma d0f13b5beb SPR-7490 - Reverting RedirectView to it's 3.0.3 version 2010-08-25 09:00:09 +00:00
Arjen Poutsma 4504ab8bc2 SPR-7316 - writeAcceptCharset now also set to false when using mvc namespace. 2010-08-23 14:53:00 +00:00
Ben Hale 7730e76c06 Publishing license and notice files 2010-08-23 13:17:31 +00:00
Arjen Poutsma dbfa049e1e Prepping for 3.0.5 2010-08-19 11:04:04 +00:00
Arjen Poutsma 9f05f28727 Prepping for 3.0.5 2010-08-19 10:55:41 +00:00
Juergen Hoeller a9da123259 temporarily disabled constructor argument caching for converted values (SPR-7423) 2010-08-19 09:30:04 +00:00
Arjen Poutsma 001d676dec SPR-7471 - Regression in redirect URL encoding 2010-08-19 08:54:42 +00:00
Arjen Poutsma 061b2c91a0 SPR-7474 - AbstractXmlStreamReader getAttributeValue(String, String) does not handle null namespaceURI properly 2010-08-19 07:53:48 +00:00
605 changed files with 22038 additions and 7455 deletions
+9 -3
View File
@@ -1,7 +1,13 @@
.springBeans
.DS_Store
target
integration-repo
ivy-cache
spring-build
jmx.log
.springBeans
.DS_Store
jxl.log
jmx.log
org.springframework.jdbc/derby.log
org.springframework.spring-parent/.classpath
org.springframework.spring-parent/.project
org.springframework.test/test-output/
spring-build/lib/docbook
@@ -3,10 +3,10 @@
<!-- Main targets -->
<target name="publish-documentation" depends="publish-documentation.init">
<sshexec host="spring02.managed.contegix.com" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
<sshexec host="static.springsource.org" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
command="mkdir /opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"/>
<scp remoteToDir="${username}@spring02.managed.contegix.com:/opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"
<scp remoteToDir="${username}@static.springsource.org:/opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"
keyfile="${key.file}" passphrase="${passphrase}" sftp="true" verbose="true">
<fileset dir="${package.output.dir}">
<include name="changelog.txt" />
@@ -16,7 +16,7 @@
<fileset dir="${package.docs.dir}" />
</scp>
<sshexec host="spring02.managed.contegix.com" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
<sshexec host="static.springsource.org" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
command="rm /opt/www/domains/springframework.org/www/htdocs/spring/docs/3.0.x ; ln -s /opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version} /opt/www/domains/springframework.org/www/htdocs/spring/docs/3.0.x"/>
</target>
+139 -2
View File
@@ -3,7 +3,144 @@ SPRING FRAMEWORK CHANGELOG
http://www.springsource.org
Changes in version 3.0.4 (2010-08-18)
Changes in version 3.0.7 (2011-12-22)
-------------------------------------
* fixed GenericTypeResolver to consistently return null if not resolvable
* added proper "contentLength()" implementation to ByteArrayResource
* refined Resource "exists()" check for HTTP URLs to always return false for 404 status
* LocaleEditor and StringToLocaleConverter do not restrict variant part through validation
* LinkedCaseInsensitiveMap overrides putAll method as well (for IBM JDK 1.6 compatibility)
* ConversionService prevents Converter from trying to convert to a subtype of its actual target type
* ConversionService is able to work with "Collections.emptyList()" as target type (again)
* CollectionCollection/MapToMapConverter preserve original Collection/Map if no converted elements
* fixed nested element conversion with a DataBinder + ConversionService + PropertyEditor
* restored DataBinder's ability to bind to an auto-growing List with unknown element type
* optimized DefaultListableBeanFactory's PropertyDescriptor caching for concurrent access
* context:property-placeholder's "file-encoding" attribute value is being applied correctly
* SpringValidatorAdapter accepts non-indexed set paths (for Hibernate Validator compatibility)
* fixed AbstractAsyncExecutionAspect's setExecutor method to correctly wrap in a TaskExecutorAdapter
* @Transactional qualifiers match against transaction manager definitions in parent contexts as well
* TransactionSynchronizationManager eagerly cleans up void ResourceHolders on any access
* updated H2 error codes in sql-error-codes.xml
* fixed NamedParameterJdbcTemplate to use correct maximum type for queryForInt/Long
* SimpleJdbcTestUtils executeSqlScript properly closes its LineNumberReader after use
* Hibernate synchronization properly unbinds Session even in case of afterCompletion exception
* JDO PersistenceManager synchronization performs close attempt after completion (if necessary)
* JPA EntityManagerFactoryUtils silently ignores IllegalArgumentExceptions from setHint calls
* added "forwarder" property to ConnectorServerFactoryBean, accepting an MBeanServerForwarder
* JmsInvokerClientInterceptor/FactoryBean always uses createConnection/createSession when on JMS 1.1
* RmiClientInterceptor detects nested SocketException as connect failure as well
* Servlet/PortletContextResource's getFile prefers "file:" URL resolution over calling getRealPath
* Portlet session mutex uses global session attribute to be shared among all portlets in the session
* fixed ServletServerHttpRequest to reconstruct from "request.getParameterMap()" for form POST only
* fixed @RequestMapping header matching to correctly process negated header conditions
* added "getObjectMapper()" accessor to MappingJacksonHttpMessageConverter
* ResourceHttpRequestHandler sends content without content-type header if no media type found
* AbstractCachingViewResolver allows for caching unresolved view names ("cacheUnresolved"=true)
* fixed "formMultiSelect"/"formCheckboxes" FreeMarker macros to compare against actual field value
Changes in version 3.0.6 (2011-08-18)
-------------------------------------
* fixed aspects bundle to declare dependencies for @Async aspect as well
* ProxyCreationContext uses "ThreadLocal.remove()" over "ThreadLocal.set(null)" as well
* DefaultListableBeanFactory is only deserializable through a SerializedBeanFactoryReference
* DefaultListableBeanFactory's getBean(name, type) attempts type conversion if necessary
* DefaultListableBeanFactory allows for init methods to register further bean definitions (again)
* XmlBeanDefinitionReader accepts description subelement within map entry as well (as per the XSD)
* ConfigurationClassPostProcessor supports use of same processor instance with several factories
* fixed potential InjectionMetadata NPE when using SpringBeanAutowiringInterceptor
* SpringBeanAutowiringSupport is able to process @Value annotations on any given target instance
* overridden @PersistenceContext annotations on subclass methods are being processed correctly
* BeanDefinitionVisitor now actually visits factory method names
* restored support for String-to-ContextResource conversion
* restored original GenericConversionService behavior with respect to empty collections/maps
* restored original FormattingConversionService behavior with respect to the use of subtypes
* added "formatters" property to FormattingConversionServiceFactoryBean
* collection/array conversion returns original collection if possible (instead of first element)
* fixed collection element resolution when using a ConversionService with a DataBinder
* DataBinder uses a default limit of 256 for array/collection auto-growing
* added "autoGrowNestedPaths" property to ConfigurableWebBindingInitializer
* Servlet/PortletRequestDataBinder perform unwrapping for MultipartRequest as well
* fixed AbstractBindingResult to avoid NPE in "hashCode()" if target is null
* fixed several HttpHeaders issues (charset handling, quoting/unquoting)
* SimpleClientHttpRequest uses fixed-length streaming mode (always sets content-length header)
* added "connectTimeout" and "readTimeout" properties to Simple/CommonsClientHttpRequestFactory
* explicit status code in RedirectView respected in HTTP 1.0 compatibility mode
* FormHttpMessageConverter correctly processes POST requests
* ResourceHttpRequestHandler does not set Content-Length header for 304 response
* ResourceHttpRequestHandler detects invalid directory traversal in given path
* LocaleChangeInterceptor validates locale values in order to prevent XSS vulnerability
* HtmlUtils properly escapes single quotes as well
* added support for web.xml context-param "springJspExpressionSupport" (explicit "true"/"false")
* ContextLoader and FrameworkServlet support "contextId" parameter for custom serialization id
* RemoteExporter uses an opaque proxy for 'serviceInterface' (no AOP interfaces exposed)
* added "acceptProxyClasses" flag to RemoteInvocationSerializingExporter
* refined WebLogic RMI descriptor to only mark 'getTargetInterfaceName' method as idempotent
* EhCacheManagerFactoryBean properly closes "ehcache.xml" input stream, if any
* revised JMS CachedConnectionFactory to avoid unnecessary rollback calls on Session return
* fixed JMS CachedConnectionFactory to fully synchronize its Session list
* fixed NamedParameterJdbcTemplate's handling of arrays as query parameters
* fixed JPA 2.0 timeout hints to correctly specify milliseconds
* updated Quartz package to support Quartz 1.8 as well (note: not supporting Quartz 2.0 yet)
* fixed @Rule execution order in SpringJUnit4ClassRunner to match standard JUnit 4 behavior
Changes in version 3.0.5 (2010-10-20)
-------------------------------------
* support for Hibernate 3.6 final
* added core serializer abstraction with default implementations using Java Serialization
* consistent use of JDK 1.5's "ThreadLocal.remove()" over "ThreadLocal.set(null)"
* fixed JodaTimeContextHolder to use a non-inheritable ThreadLocal and expose a reset method
* revised "ClassUtils.isAssignable" semantics to cover primitives vs wrappers in both directions
* optimized AnnotationUtils findAnnotation performance for repeated search on same interfaces
* ConversionService protects itself against infinite recursion in ObjectToCollectionConverter
* fixed TypeDescriptor to correctly resolve nested collections and their element types
* BeanWrapper does not attempt to populate Map values on access (just auto-grows Map itself)
* fixed Autowired/CommonAnnotationBeanPostProcessor to prevent race condition in skipping check
* fixed @Value injection to correctly cache temporary null results for non-singleton beans
* ApplicationContext registers context-specific ClassArrayEditor for its bean ClassLoader
* refined ApplicationContext singleton processing to not fail for manually registered null instances
* fixed ApplicationContext event processing for repeated invocations to non-singleton listener beans
* optimized @Bean error messages for static factory methods as well as for argument type mismatches
* modified expression parsing to pass full TypeDescriptor context through to ConversionService calls
* adapted expression parser's Constructor/MethodResolver to accept TypeDescriptors instead of raw types
* SpEL supports projection on any kind of Collection (not just on Lists and arrays)
* SpEL MapAccessor consistently rejects "target.key" style access to Maps if no such key is found
* SpEL method invocations prefer method with fewest parameters (e.g. no-arg over vararg)
* AspectJExpressionPointcut uses bean ClassLoader for initializing the AspectJ pointcut parser
* added AnnotationAsyncExecutionAspect as AspectJ-based variant of @Async processing
* added mode="proxy"/"aspectj" and proxy-target-class options to task:annotation-driven
* JDBC bundle uses local ClassLoader as bean ClassLoader for "sql-error-codes.xml" parsing
* EmbeddedDatabaseFactory shuts down database when failing to populate it in "initDatabase()"
* embedded database support now also works with Derby >= 10.6
* "jdbc:embedded-database" uses id as database name to allow multiple ones in parallel
* ResourceDatabasePopulator throws descriptive ScriptStatementFailedException with resource details
* added configurable Connection/Statement/ResultSet target types to Jdbc4NativeJdbcExtractor
* added OracleJdbc4NativeJdbcExtractor with pre-configured Oracle JDBC API types
* DefaultLobHandler's "wrapAsLob" mode works with PostgreSQL's "getAsciiStream()" requirement
* ResultSetWrappingSqlRowSet (as used by JdbcTemplate's "queryForRowSet") supports column labels now
* LocalSessionFactoryBean's "entityCacheStrategies" works with region names on Hibernate 3.6 as well
* fixed DefaultMessageListenerContainer's no-message-received commit to work without Session caching
* DefaultMessageListenerContainer's skips no-message-received commit on Tibco (avoiding a deadlock)
* JaxWsPortClientInterceptor does not fall back to annotation-specified name as portName anymore
* UriTemplate is serializable now
* fixed AnnotationMethodHandlerAdapter's caching to avoid concurrency issues in RequestMappingInfo
* fixed @MVC processing of parameter-level annotations to work with interface-based proxies again
* revised @RequestParam processing to support CSV-to-array/collection binding with ConversionService
* fixed EvalTag's EvaluationContext caching to properly handle JSP tag caching across requests
* AbstractJasperReportsView only sets locale model attributes if not present already
* DispatcherPortlet throws custom NoHandlerFoundException instead of misleading UnavailableException
* DispatcherPortlet copies all action parameters to render parameters in case of an action exception
* DispatcherPortlet's default resource serving explicitly prevents access to WEB-INF and META-INF
* Portlet @ExceptionHandler methods allow for writing the response directly (like in the Servlet case)
* MockHttpServletRequest/HttpSession/etc returns independent Enumeration from "getAttributeNames()"
Changes in version 3.0.4 (2010-08-19)
-------------------------------------
* support for Hibernate Core 3.6, Hibernate Validator 4.1, EclipseLink 2.1, EHCache 2.2
@@ -17,7 +154,7 @@ Changes in version 3.0.4 (2010-08-18)
* fixed double ConversionFailedException nesting for ObjectToObjectConverter invocations
* BeanWrapper preserves annotation information for individual array/list/map elements
* Spring's constructor resolution consistently finds non-public multi-arg constructors
* revised constructor argument caching for highly concurrent creation scenarios
* revised constructor argument caching, avoiding a race condition for converted argument values
* SpEL passes full collection type context (generics, annotations) to ConversionService
* SpEL 'select last' operator now works consistently with maps
* BeanWrapper/DataBinder's "autoGrowNestedPaths" works for Maps as well
+3 -3
View File
@@ -1,6 +1,6 @@
SPRING FRAMEWORK 3.0.4 (August 2010)
------------------------------------
http://www.springframework.org
SPRING FRAMEWORK 3.0.7 (December 2011)
--------------------------------------
http://www.springsource.org
1. INTRODUCTION
+30 -29
View File
@@ -1,29 +1,30 @@
version=3.0.4
# osgi ranges
spring.osgi.range.nq=${version:[=.=.=, =.=.+1)}
spring.osgi.range="${spring.osgi.range.nq}"
aj.osgi.range="[1.5.4, 2.0.0)"
#
release.type=integration
natural.name=spring-framework
project.name=Spring Framework
project.key=SPR
ivy.cache.dir=${basedir}/../ivy-cache
integration.repo.dir=${basedir}/../integration-repo
javadoc.exclude.package.names=org/springframework/samples/**
javadoc.max.memory=256M
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
compiler.args=-enableJavadoc -warn:none
# For when releasing
#release.type=release
#build.stamp=RELEASE
# For when releasing milestones
#release.type=milestone
#build.stamp=M1
# For development in trunk
#release.type=integration
#build.stamp=BUILD-SNAPSHOT
version=3.0.8
# osgi ranges
spring.osgi.range.nq=${version:[=.=.=, =.=.+1)}
spring.osgi.range="${spring.osgi.range.nq}"
aj.osgi.range="[1.5.4, 2.0.0)"
#
#release.type=integration
natural.name=spring-framework
project.name=Spring Framework
project.key=SPR
ivy.cache.dir=${basedir}/../ivy-cache
integration.repo.dir=${basedir}/../integration-repo
license.dir=${basedir}/../build-spring-framework/resources
javadoc.exclude.package.names=org/springframework/samples/**
javadoc.max.memory=256M
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
compiler.args=-enableJavadoc -warn:none
# For when releasing
#release.type=release
#build.stamp=RELEASE
# For when releasing milestones
#release.type=milestone
#build.stamp=M1
# For development in trunk
release.type=integration
build.stamp=BUILD-SNAPSHOT
+5 -6
View File
@@ -1,6 +1,5 @@
#common dependency versions
aspectj.version=1.6.8.RELEASE
commons.pool.version=1.5.3
slf4j.version=1.5.6
org.testng.version=5.10.0
org.junit.version=4.7.0
#common dependency versions
aspectj.version=1.6.8.RELEASE
slf4j.version=1.5.3
junit.version=4.7.0
testng.version=5.10.0
+4 -2
View File
@@ -21,6 +21,8 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
@@ -28,14 +30,14 @@
<dependency org="net.sourceforge.cglib" name="com.springsource.net.sf.cglib" rev="2.2.0" conf="optional, bytecode-proxy->compile"/>
<dependency org="org.aopalliance" name="com.springsource.org.aopalliance" rev="1.0.0" conf="compile->compile"/>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile, commons-logging->compile"/>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.pool" rev="${commons.pool.version}" conf="optional, pooling->compile"/>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.pool" rev="1.5.3" conf="optional, pooling->compile"/>
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="${aspectj.version}" conf="optional, aspectj->compile"/>
<dependency org="org.springframework" name="org.springframework.beans" rev="latest.integration" conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration" conf="compile->compile"/>
<!-- test dependencies -->
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="test->runtime"/>
</dependencies>
+2 -2
View File
@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<packaging>jar</packaging>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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,6 +54,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -95,12 +96,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
private transient PointcutParser pointcutParser;
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
private Class pointcutDeclarationScope;
private String[] pointcutParameterNames = new String[0];
@@ -109,12 +104,15 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
private BeanFactory beanFactory;
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
/**
* Create a new default AspectJExpressionPointcut.
*/
public AspectJExpressionPointcut() {
initializePointcutParser();
}
/**
@@ -124,7 +122,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* @param paramTypes the parameter types for the pointcut
*/
public AspectJExpressionPointcut(Class declarationScope, String[] paramNames, Class[] paramTypes) {
initializePointcutParser();
this.pointcutDeclarationScope = declarationScope;
if (paramNames.length != paramTypes.length) {
throw new IllegalStateException(
@@ -134,13 +131,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
this.pointcutParameterTypes = paramTypes;
}
private void initializePointcutParser() {
this.pointcutParser =
PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
SUPPORTED_PRIMITIVES);
this.pointcutParser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
}
/**
* Set the declaration scope for the pointcut.
@@ -196,15 +186,30 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* Build the underlying AspectJ pointcut expression.
*/
private PointcutExpression buildPointcutExpression() {
PointcutParser parser = initializePointcutParser();
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
for (int i = 0; i < pointcutParameters.length; i++) {
pointcutParameters[i] = this.pointcutParser.createPointcutParameter(
pointcutParameters[i] = parser.createPointcutParameter(
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
}
return this.pointcutParser.parsePointcutExpression(
return parser.parsePointcutExpression(
replaceBooleanOperators(getExpression()), this.pointcutDeclarationScope, pointcutParameters);
}
/**
* Initialize the underlying AspectJ pointcut parser.
*/
private PointcutParser initializePointcutParser() {
ClassLoader cl = (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
Thread.currentThread().getContextClassLoader());
PointcutParser parser =
PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
SUPPORTED_PRIMITIVES, cl);
parser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
return parser;
}
/**
* If a pointcut expression has been specified in XML, the user cannot
* write <code>and</code> as "&&" (though &amp;&amp; will work).
@@ -218,6 +223,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return result;
}
/**
* Return the underlying AspectJ pointcut expression.
*/
@@ -226,7 +232,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return this.pointcutExpression;
}
public boolean matches(Class targetClass) {
checkReadyToMatch();
try {
@@ -455,7 +460,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
/**
* Matcher class for the BeanNamePointcutDesignatorHandler.
*
* <p>Dynamic match tests for this matcher always return true,
* since the matching decision is made at the proxy creation time.
* For static match tests, this matcher abstains to allow the overall
@@ -535,7 +539,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
ois.defaultReadObject();
// Initialize transient fields.
initializePointcutParser();
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -76,7 +76,12 @@ public abstract class AopContext {
*/
static Object setCurrentProxy(Object proxy) {
Object old = currentProxy.get();
currentProxy.set(proxy);
if (proxy != null) {
currentProxy.set(proxy);
}
else {
currentProxy.remove();
}
return old;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,12 @@ public class ProxyCreationContext {
* @param beanName the name of the bean, or <code>null</code> to reset it
*/
static void setCurrentProxiedBeanName(String beanName) {
currentProxiedBeanName.set(beanName);
if (beanName != null) {
currentProxiedBeanName.set(beanName);
}
else {
currentProxiedBeanName.remove();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,8 +70,9 @@ public class ExposeInvocationInterceptor implements MethodInterceptor, Ordered,
MethodInvocation mi = invocation.get();
if (mi == null)
throw new IllegalStateException(
"No MethodInvocation found: Check that an AOP invocation is in progress, " +
"and that the ExposeInvocationInterceptor is in the interceptor chain.");
"No MethodInvocation found: Check that an AOP invocation is in progress, and that the " +
"ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that " +
"advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor!");
return mi;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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,9 @@
package org.springframework.aop.target;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import org.springframework.beans.BeansException;
@@ -91,6 +93,11 @@ public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFac
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new NotSerializableException("A prototype-based TargetSource itself is not deserializable - " +
"just a disconnected SingletonTargetSource is");
}
/**
* Replaces this object with a SingletonTargetSource on serialization.
* Protected as otherwise it won't be invoked for subclasses.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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.
@@ -106,7 +106,7 @@ public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
this.targetSet.clear();
}
// Clear ThreadLocal, just in case.
this.targetInThread.set(null);
this.targetInThread.remove();
}
+1
View File
@@ -36,6 +36,7 @@
<artifacts pattern="${jar.output.dir}/[artifact].[ext]"/>
<artifacts pattern="${source-jar.output.dir}/[artifact].[ext]"/>
<artifacts pattern="${ivy.output.dir}/[artifact].[ext]"/>
<artifacts pattern="${license.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>
+2
View File
@@ -17,6 +17,8 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
+2 -2
View File
@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-asm</artifactId>
<packaging>jar</packaging>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
+5 -3
View File
@@ -20,6 +20,8 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
@@ -31,9 +33,9 @@
<dependency org="org.springframework" name="org.springframework.test" rev="latest.integration" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.context" rev="latest.integration" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.context.support" rev="latest.integration" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->compile"/>
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="provided->compile"/>
<dependency org="javax.mail" name="com.springsource.javax.mail" rev="1.4.0" conf="test->compile"/>
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="optional, orm->compile"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->compile"/>
<dependency org="javax.mail" name="com.springsource.javax.mail" rev="1.4.0" conf="optional, test->compile"/>
</dependencies>
</ivy-module>
+90 -84
View File
@@ -1,84 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<packaging>jar</packaging>
<version>3.0.4.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.4.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<!-- common logging dependency is in spring-core -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<packaging>jar</packaging>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<!-- commons logging dependency is in spring-core -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
@@ -1,3 +1,19 @@
/*
* Copyright 2002-2010 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.mock.staticmock;
import java.util.Arrays;
@@ -12,7 +28,6 @@ import java.util.List;
*
* @author Rod Johnson
* @author Ramnivas Laddad
*
*/
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
@@ -1,18 +1,33 @@
package org.springframework.mock.staticmock;
/*
* Copyright 2002-2010 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.
*/
import javax.persistence.Entity;
package org.springframework.mock.staticmock;
/**
* Annotation-based aspect to use in test build to enable mocking static methods
* on Entity classes, as used by Roo for finders.
* <br>
* Mocking will occur in the call stack of any method in a class (typically a test class)
* on JPA-annotated <code>@Entity</code> classes, as used by Roo for finders.
*
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
* that is annotated with the @MockStaticEntityMethods annotation.
* <br>
* Also provides static methods to simplify the programming model for
*
* <p>Also provides static methods to simplify the programming model for
* entering playback mode and setting expected return values.
* <br>
* Usage:<ol>
*
* <p>Usage:
* <ol>
* <li>Annotate a test class with @MockStaticEntityMethods.
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
* Invoke static methods on Entity classes, with each recording-mode invocation
@@ -23,11 +38,9 @@ import javax.persistence.Entity;
* occur automatically.
* </ol>
*
* @see MockStaticEntityMethods
*
* @author Rod Johnson
* @author Ramnivas Laddad
*
* @see MockStaticEntityMethods
*/
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
@@ -50,6 +63,6 @@ public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodM
// @MockStatics classes to invoke each other without resetting the mocking environment
protected pointcut mockStaticsTestMethod() : execution(public * (@MockStaticEntityMethods *).*(..));
protected pointcut methodToMock() : execution(public static * (@Entity *).*(..));
protected pointcut methodToMock() : execution(public static * (@javax.persistence.Entity *).*(..));
}
@@ -1,3 +1,18 @@
/*
* Copyright 2002-2010 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.mock.staticmock;
import java.lang.annotation.ElementType;
@@ -8,11 +23,9 @@ import java.lang.annotation.Target;
/**
* Annotation to indicate a test class for whose @Test methods
* static methods on Entity classes should be mocked.
*
* @see AbstractMethodMockingControl
*
* @author Rod Johnson
*
* @author Rod Johnson
* @see AbstractMethodMockingControl
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@@ -0,0 +1,75 @@
/*
* Copyright 2002-2010 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.aspectj;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.support.TaskExecutorAdapter;
/**
* 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.
*
* @author Ramnivas Laddad
* @author Juergen Hoeller
* @since 3.0.5
*/
public abstract aspect AbstractAsyncExecutionAspect {
private AsyncTaskExecutor asyncExecutor;
public void setExecutor(Executor executor) {
if (executor instanceof AsyncTaskExecutor) {
this.asyncExecutor = (AsyncTaskExecutor) executor;
}
else {
this.asyncExecutor = new TaskExecutorAdapter(executor);
}
}
Object around() : asyncMethod() {
if (this.asyncExecutor == null) {
return proceed();
}
Callable<Object> callable = new Callable<Object>() {
public Object call() throws Exception {
Object result = proceed();
if (result instanceof Future) {
return ((Future<?>) result).get();
}
return null;
}};
Future<?> result = this.asyncExecutor.submit(callable);
if (Future.class.isAssignableFrom(((MethodSignature) thisJoinPointStaticPart.getSignature()).getReturnType())) {
return result;
}
else {
return null;
}
}
public abstract pointcut asyncMethod();
}
@@ -0,0 +1,54 @@
/*
* Copyright 2002-2010 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.aspectj;
import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
/**
* Aspect to route methods based on the {@link Async} annotation.
*
* <p>This aspect routes methods marked with the {@link Async} annotation
* as well as methods in classes marked with the same. Any method expected
* to be routed asynchronously must return either void, {@link Future},
* or a subtype of {@link Future}. This aspect, therefore, will produce
* a compile-time error for methods that violate this constraint on the return type.
* If, however, a class marked with <code>&#64;Async</code> contains a method that
* violates this constraint, it produces only a warning.
*
* @author Ramnivas Laddad
* @since 3.0.5
*/
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
private pointcut asyncMarkedMethod()
: execution(@Async (void || Future+) *(..));
private pointcut asyncTypeMarkedMethod()
: execution((void || Future+) (@Async *).*(..));
public pointcut asyncMethod() : asyncMarkedMethod() || asyncTypeMarkedMethod();
declare error:
execution(@Async !(void||Future) *(..)):
"Only methods that return void or Future may have an @Async annotation";
declare warning:
execution(!(void||Future) (@Async *).*(..)):
"Methods in a class marked with @Async that do not return void or Future will be routed synchronously";
}
@@ -1,93 +1,93 @@
/*
* Copyright 2002-2007 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.transaction.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
/**
* Abstract superaspect for AspectJ transaction aspects. Concrete
* subaspects will implement the <code>transactionalMethodExecution()</code>
* pointcut using a strategy such as Java 5 annotations.
*
* <p>Suitable for use inside or outside the Spring IoC container.
* Set the "transactionManager" property appropriately, allowing
* use of any transaction implementation supported by Spring.
*
* <p><b>NB:</b> If a method implements an interface that is itself
* transactionally annotated, the relevant Spring transaction attribute
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
* if proxying an interface (but not when proxying a class). We recommend that
* transaction annotations should be added to classes, rather than business
* interfaces, as they are an implementation detail rather than a contract
* specification validation.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @since 2.0
*/
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
/**
* Construct object using the given transaction metadata retrieval strategy.
* @param tas TransactionAttributeSource implementation, retrieving Spring
* transaction metadata for each joinpoint. Write the subclass to pass in null
* if it's intended to be configured by Setter Injection.
*/
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
setTransactionAttributeSource(tas);
}
@SuppressAjWarnings("adviceDidNotMatch")
before(Object txObject) : transactionalMethodExecution(txObject) {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method method = methodSignature.getMethod();
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
try {
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
}
catch (Throwable t2) {
logger.error("Failed to close transaction after throwing in a transactional method", t2);
}
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) : transactionalMethodExecution(txObject) {
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
}
/**
* Concrete subaspects must implement this pointcut, to identify
* transactional methods. For each selected joinpoint, TransactionMetadata
* will be retrieved using Spring's TransactionAttributeSource interface.
*/
protected abstract pointcut transactionalMethodExecution(Object txObject);
}
/*
* Copyright 2002-2010 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.transaction.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
/**
* Abstract superaspect for AspectJ transaction aspects. Concrete
* subaspects will implement the <code>transactionalMethodExecution()</code>
* pointcut using a strategy such as Java 5 annotations.
*
* <p>Suitable for use inside or outside the Spring IoC container.
* Set the "transactionManager" property appropriately, allowing
* use of any transaction implementation supported by Spring.
*
* <p><b>NB:</b> If a method implements an interface that is itself
* transactionally annotated, the relevant Spring transaction attribute
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
* if proxying an interface (but not when proxying a class). We recommend that
* transaction annotations should be added to classes, rather than business
* interfaces, as they are an implementation detail rather than a contract
* specification validation.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @since 2.0
*/
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
/**
* Construct object using the given transaction metadata retrieval strategy.
* @param tas TransactionAttributeSource implementation, retrieving Spring
* transaction metadata for each joinpoint. Write the subclass to pass in null
* if it's intended to be configured by Setter Injection.
*/
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
setTransactionAttributeSource(tas);
}
@SuppressAjWarnings("adviceDidNotMatch")
before(Object txObject) : transactionalMethodExecution(txObject) {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method method = methodSignature.getMethod();
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
try {
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
}
catch (Throwable t2) {
logger.error("Failed to close transaction after throwing in a transactional method", t2);
}
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) : transactionalMethodExecution(txObject) {
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
}
/**
* Concrete subaspects must implement this pointcut, to identify
* transactional methods. For each selected joinpoint, TransactionMetadata
* will be retrieved using Spring's TransactionAttributeSource interface.
*/
protected abstract pointcut transactionalMethodExecution(Object txObject);
}
@@ -1,76 +1,75 @@
/*
* Copyright 2002-2008 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.transaction.aspectj;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;
/**
* Concrete AspectJ transaction aspect using Spring Transactional annotation
* for JDK 1.5+.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited.
*
* <p>A @Transactional annotation on a class specifies the default transaction
* semantics for the execution of any <b>public</b> operation in the class.
*
* <p>A @Transactional annotation on a method within the class overrides the
* default transaction semantics given by the class annotation (if present).
* Any method may be annotated (regardless of visibility).
* Annotating non-public methods directly is the only way
* to get transaction demarcation for the execution of such operations.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Adrian Colyer
* @since 2.0
* @see org.springframework.transaction.annotation.Transactional
*/
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
public AnnotationTransactionAspect() {
super(new AnnotationTransactionAttributeSource(false));
}
/**
* Matches the execution of any public method in a type with the
* Transactional annotation, or any subtype of a type with the
* Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);
/**
* Matches the execution of any method with the
* Transactional annotation.
*/
private pointcut executionOfTransactionalMethod() :
execution(* *(..)) && @annotation(Transactional);
/**
* Definition of pointcut from super aspect - matched join points
* will have Spring transaction management applied.
*/
protected pointcut transactionalMethodExecution(Object txObject) :
(executionOfAnyPublicMethodInAtTransactionalType()
|| executionOfTransactionalMethod() )
&& this(txObject);
}
/*
* Copyright 2002-2010 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.transaction.aspectj;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;
/**
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited.
*
* <p>A @Transactional annotation on a class specifies the default transaction
* semantics for the execution of any <b>public</b> operation in the class.
*
* <p>A @Transactional annotation on a method within the class overrides the
* default transaction semantics given by the class annotation (if present).
* Any method may be annotated (regardless of visibility).
* Annotating non-public methods directly is the only way
* to get transaction demarcation for the execution of such operations.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Adrian Colyer
* @since 2.0
* @see org.springframework.transaction.annotation.Transactional
*/
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
public AnnotationTransactionAspect() {
super(new AnnotationTransactionAttributeSource(false));
}
/**
* Matches the execution of any public method in a type with the
* Transactional annotation, or any subtype of a type with the
* Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);
/**
* Matches the execution of any method with the
* Transactional annotation.
*/
private pointcut executionOfTransactionalMethod() :
execution(* *(..)) && @annotation(Transactional);
/**
* Definition of pointcut from super aspect - matched join points
* will have Spring transaction management applied.
*/
protected pointcut transactionalMethodExecution(Object txObject) :
(executionOfAnyPublicMethodInAtTransactionalType()
|| executionOfTransactionalMethod() )
&& this(txObject);
}
@@ -1,17 +1,18 @@
<?xml version="1.0"?>
<!--
AspectJ load-time weaving config file to install common Spring aspects.
-->
<aspectj>
<!--
<weaver options="-showWeaveInfo"/>
-->
<aspects>
<aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
<aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect"/>
</aspects>
</aspectj>
<?xml version="1.0"?>
<!--
AspectJ load-time weaving config file to install common Spring aspects.
-->
<aspectj>
<!--
<weaver options="-showWeaveInfo"/>
-->
<aspects>
<aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
<aspect name="org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect"/>
<aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect"/>
</aspects>
</aspectj>
@@ -1,146 +1,146 @@
/*
* Copyright 2009 SpringSource Inc.
*
* 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.mock.staticmock;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
/**
* Test for static entity mocking framework.
* @author Rod Johnson
* @author Ramnivas Laddad
*
*/
@MockStaticEntityMethods
@RunWith(JUnit4.class)
public class AnnotationDrivenStaticEntityMockingControlTest {
@Test
public void testNoArgIntReturn() {
int expectedCount = 13;
Person.countPeople();
expectReturn(expectedCount);
playback();
Assert.assertEquals(expectedCount, Person.countPeople());
}
@Test(expected=PersistenceException.class)
public void testNoArgThrows() {
Person.countPeople();
expectThrow(new PersistenceException());
playback();
Person.countPeople();
}
@Test
public void testArgMethodMatches() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testLongSeriesOfCalls() {
long id1 = 13;
long id2 = 24;
Person found1 = new Person();
Person.findPerson(id1);
expectReturn(found1);
Person found2 = new Person();
Person.findPerson(id2);
expectReturn(found2);
Person.findPerson(id1);
expectReturn(found1);
Person.countPeople();
expectReturn(0);
playback();
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(found2, Person.findPerson(id2));
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(0, Person.countPeople());
}
// Note delegation is used when tests are invalid and should fail, as otherwise
// the failure will occur on the verify() method in the aspect after
// this method returns, failing the test case
@Test
public void testArgMethodNoMatchExpectReturn() {
try {
new Delegate().testArgMethodNoMatchExpectReturn();
Assert.fail();
} catch (IllegalArgumentException expected) {
}
}
@Test(expected=IllegalArgumentException.class)
public void testArgMethodNoMatchExpectThrow() {
new Delegate().testArgMethodNoMatchExpectThrow();
}
private void called(Person found, long id) {
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testReentrant() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
called(found, id);
}
@Test(expected=IllegalStateException.class)
public void testRejectUnexpectedCall() {
new Delegate().rejectUnexpectedCall();
}
@Test(expected=IllegalStateException.class)
public void testFailTooFewCalls() {
new Delegate().failTooFewCalls();
}
@Test
public void testEmpty() {
// Test that verification check doesn't blow up if no replay() call happened
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverReplay() {
new Delegate().doesntEverReplay();
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverSetReturn() {
new Delegate().doesntEverSetReturn();
}
}
/*
* Copyright 2002-2010 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.mock.staticmock;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
/**
* Test for static entity mocking framework.
* @author Rod Johnson
* @author Ramnivas Laddad
*
*/
@MockStaticEntityMethods
@RunWith(JUnit4.class)
public class AnnotationDrivenStaticEntityMockingControlTest {
@Test
public void testNoArgIntReturn() {
int expectedCount = 13;
Person.countPeople();
expectReturn(expectedCount);
playback();
Assert.assertEquals(expectedCount, Person.countPeople());
}
@Test(expected=PersistenceException.class)
public void testNoArgThrows() {
Person.countPeople();
expectThrow(new PersistenceException());
playback();
Person.countPeople();
}
@Test
public void testArgMethodMatches() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testLongSeriesOfCalls() {
long id1 = 13;
long id2 = 24;
Person found1 = new Person();
Person.findPerson(id1);
expectReturn(found1);
Person found2 = new Person();
Person.findPerson(id2);
expectReturn(found2);
Person.findPerson(id1);
expectReturn(found1);
Person.countPeople();
expectReturn(0);
playback();
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(found2, Person.findPerson(id2));
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(0, Person.countPeople());
}
// Note delegation is used when tests are invalid and should fail, as otherwise
// the failure will occur on the verify() method in the aspect after
// this method returns, failing the test case
@Test
public void testArgMethodNoMatchExpectReturn() {
try {
new Delegate().testArgMethodNoMatchExpectReturn();
Assert.fail();
} catch (IllegalArgumentException expected) {
}
}
@Test(expected=IllegalArgumentException.class)
public void testArgMethodNoMatchExpectThrow() {
new Delegate().testArgMethodNoMatchExpectThrow();
}
private void called(Person found, long id) {
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testReentrant() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
called(found, id);
}
@Test(expected=IllegalStateException.class)
public void testRejectUnexpectedCall() {
new Delegate().rejectUnexpectedCall();
}
@Test(expected=IllegalStateException.class)
public void testFailTooFewCalls() {
new Delegate().failTooFewCalls();
}
@Test
public void testEmpty() {
// Test that verification check doesn't blow up if no replay() call happened
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverReplay() {
new Delegate().doesntEverReplay();
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverSetReturn() {
new Delegate().doesntEverSetReturn();
}
}
@@ -1,76 +1,92 @@
package org.springframework.mock.staticmock;
import java.rmi.RemoteException;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
import org.springframework.mock.staticmock.MockStaticEntityMethods;
//Used because verification failures occur after method returns,
//so we can't test for them in the test case itself
@MockStaticEntityMethods
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
public class Delegate {
@Test
public void testArgMethodNoMatchExpectReturn() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void testArgMethodNoMatchExpectThrow() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void failTooFewCalls() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void doesntEverReplay() {
Person.countPeople();
}
@Test
public void doesntEverSetReturn() {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
}
@Test
public void rejectUnexpectedCall() {
AnnotationDrivenStaticEntityMockingControl.playback();
Person.countPeople();
}
@Test(expected=RemoteException.class)
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
// No calls to allow verification failure
throw new RemoteException();
}
}
/*
* Copyright 2002-2010 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.mock.staticmock;
import java.rmi.RemoteException;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
import org.springframework.mock.staticmock.MockStaticEntityMethods;
//Used because verification failures occur after method returns,
//so we can't test for them in the test case itself
@MockStaticEntityMethods
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
public class Delegate {
@Test
public void testArgMethodNoMatchExpectReturn() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void testArgMethodNoMatchExpectThrow() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void failTooFewCalls() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void doesntEverReplay() {
Person.countPeople();
}
@Test
public void doesntEverSetReturn() {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
}
@Test
public void rejectUnexpectedCall() {
AnnotationDrivenStaticEntityMockingControl.playback();
Person.countPeople();
}
@Test(expected=RemoteException.class)
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
// No calls to allow verification failure
throw new RemoteException();
}
}
@@ -1,8 +1,24 @@
package org.springframework.mock.staticmock;
import javax.persistence.Entity;
@Entity
public class Person {
}
/*
* Copyright 2002-2010 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.mock.staticmock;
import javax.persistence.Entity;
@Entity
public class Person {
}
@@ -1,84 +1,100 @@
package org.springframework.mock.staticmock;
privileged aspect Person_Roo_Entity {
@javax.persistence.PersistenceContext
transient javax.persistence.EntityManager Person.entityManager;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
@javax.persistence.Column(name = "id")
private java.lang.Long Person.id;
@javax.persistence.Version
@javax.persistence.Column(name = "version")
private java.lang.Integer Person.version;
public java.lang.Long Person.getId() {
return this.id;
}
public void Person.setId(java.lang.Long id) {
this.id = id;
}
public java.lang.Integer Person.getVersion() {
return this.version;
}
public void Person.setVersion(java.lang.Integer version) {
this.version = version;
}
@org.springframework.transaction.annotation.Transactional
public void Person.persist() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.persist(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.remove() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.remove(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.flush() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.flush();
}
@org.springframework.transaction.annotation.Transactional
public void Person.merge() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
Person merged = this.entityManager.merge(this);
this.entityManager.flush();
this.id = merged.getId();
}
public static long Person.countPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return (Long) em.createQuery("select count(o) from Person o").getSingleResult();
}
public static java.util.List<Person> Person.findAllPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").getResultList();
}
public static Person Person.findPerson(java.lang.Long id) {
if (id == null) throw new IllegalArgumentException("An identifier is required to retrieve an instance of Person");
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.find(Person.class, id);
}
public static java.util.List<Person> Person.findPersonEntries(int firstResult, int maxResults) {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}
}
/*
* Copyright 2002-2010 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.mock.staticmock;
privileged aspect Person_Roo_Entity {
@javax.persistence.PersistenceContext
transient javax.persistence.EntityManager Person.entityManager;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
@javax.persistence.Column(name = "id")
private java.lang.Long Person.id;
@javax.persistence.Version
@javax.persistence.Column(name = "version")
private java.lang.Integer Person.version;
public java.lang.Long Person.getId() {
return this.id;
}
public void Person.setId(java.lang.Long id) {
this.id = id;
}
public java.lang.Integer Person.getVersion() {
return this.version;
}
public void Person.setVersion(java.lang.Integer version) {
this.version = version;
}
@org.springframework.transaction.annotation.Transactional
public void Person.persist() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.persist(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.remove() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.remove(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.flush() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.flush();
}
@org.springframework.transaction.annotation.Transactional
public void Person.merge() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
Person merged = this.entityManager.merge(this);
this.entityManager.flush();
this.id = merged.getId();
}
public static long Person.countPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return (Long) em.createQuery("select count(o) from Person o").getSingleResult();
}
public static java.util.List<Person> Person.findAllPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").getResultList();
}
public static Person Person.findPerson(java.lang.Long id) {
if (id == null) throw new IllegalArgumentException("An identifier is required to retrieve an instance of Person");
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.find(Person.class, id);
}
public static java.util.List<Person> Person.findPersonEntries(int firstResult, int maxResults) {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}
}
@@ -0,0 +1,178 @@
/*
* Copyright 2002-2010 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.aspectj;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import junit.framework.Assert;
import static junit.framework.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
/**
* @author Ramnivas Laddad
*/
public class AnnotationAsyncExecutionAspectTests {
private static final long WAIT_TIME = 1000; //milli seconds
private CountingExecutor executor;
@Before
public void setUp() {
executor = new CountingExecutor();
AnnotationAsyncExecutionAspect.aspectOf().setExecutor(executor);
}
@Test
public void asyncMethodGetsRoutedAsynchronously() {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
obj.incrementAsync();
executor.waitForCompletion();
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
Future<Integer> future = obj.incrementReturningAFuture();
// No need to executor.waitForCompletion() as future.get() will have the same effect
assertEquals(5, future.get().intValue());
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void syncMethodGetsRoutedSynchronously() {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
obj.increment();
assertEquals(1, obj.counter);
assertEquals(0, executor.submitStartCounter);
assertEquals(0, executor.submitCompleteCounter);
}
@Test
public void voidMethodInAsyncClassGetsRoutedAsynchronously() {
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
obj.increment();
executor.waitForCompletion();
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
Future<Integer> future = obj.incrementReturningAFuture();
assertEquals(5, future.get().intValue());
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() {
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
int returnValue = obj.return5();
assertEquals(5, returnValue);
assertEquals(0, executor.submitStartCounter);
assertEquals(0, executor.submitCompleteCounter);
}
@SuppressWarnings("serial")
private static class CountingExecutor extends SimpleAsyncTaskExecutor {
int submitStartCounter;
int submitCompleteCounter;
@Override
public <T> Future<T> submit(Callable<T> task) {
submitStartCounter++;
Future<T> future = super.submit(task);
submitCompleteCounter++;
synchronized (this) {
notifyAll();
}
return future;
}
public synchronized void waitForCompletion() {
try {
wait(WAIT_TIME);
} catch (InterruptedException e) {
Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds");
}
}
}
static class ClassWithoutAsyncAnnotation {
int counter;
@Async public void incrementAsync() {
counter++;
}
public void increment() {
counter++;
}
@Async public Future<Integer> incrementReturningAFuture() {
counter++;
return new AsyncResult<Integer>(5);
}
// It should be an error to attach @Async to a method that returns a non-void
// or non-Future.
// We need to keep this commented out, otherwise there will be a compile-time error.
// Please uncomment and re-comment this periodically to check that the compiler
// produces an error message due to the 'declare error' statement
// in AnnotationAsyncExecutionAspect
// @Async public int getInt() {
// return 0;
// }
}
@Async
static class ClassWithAsyncAnnotation {
int counter;
public void increment() {
counter++;
}
// Manually check that there is a warning from the 'declare warning' statement in AnnotationAsynchExecutionAspect
public int return5() {
return 5;
}
public Future<Integer> incrementReturningAFuture() {
counter++;
return new AsyncResult<Integer>(5);
}
}
}
+1
View File
@@ -7,6 +7,7 @@ Import-Template:
org.aspectj.*;version=${aj.osgi.range};resolution:=optional,
org.springframework.beans.*;version=${spring.osgi.range},
org.springframework.transaction.*;version=${spring.osgi.range};resolution:=optional,
org.springframework.core.task.*;version=${spring.osgi.range};resolution:=optional,
org.springframework.orm.jpa.*;version=${spring.osgi.range};resolution:=optional,
org.springframework.dao.*;version=${spring.osgi.range};resolution:=optional
Ignored-Existing-Headers:
+3 -1
View File
@@ -18,6 +18,8 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
@@ -28,7 +30,7 @@
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration" conf="compile->compile"/>
<!-- test dependencies -->
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="compile->compile"/>
</dependencies>
+2 -2
View File
@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<packaging>jar</packaging>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -92,4 +92,15 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
*/
boolean isAutoGrowNestedPaths();
/**
* 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-2010 the original author or authors.
* Copyright 2002-2011 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,6 +120,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
private boolean autoGrowNestedPaths = false;
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
/**
* Create new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
@@ -184,6 +186,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
setWrappedInstance(object, nestedPath, superBw.getWrappedInstance());
setExtractOldValueForEditor(superBw.isExtractOldValueForEditor());
setAutoGrowNestedPaths(superBw.isAutoGrowNestedPaths());
setAutoGrowCollectionLimit(superBw.getAutoGrowCollectionLimit());
setConversionService(superBw.getConversionService());
setSecurityContext(superBw.acc);
}
@@ -251,22 +254,38 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
/**
* If this BeanWrapper should "auto grow" nested paths.
* When true, auto growth is triggered on nested paths when null values are encountered.
* When true, auto growth is triggered on collection properties when out of bounds indexes are accessed.
* Default is false.
* Set whether this BeanWrapper should attempt to "auto-grow" a nested path that contains a null value.
* <p>If "true", a null path location will be populated with a default object value and traversed
* instead of resulting in a {@link NullValueInNestedPathException}. Turning this flag on also
* enables auto-growth of collection elements when accessing an out-of-bounds index.
* <p>Default is "false" on a plain BeanWrapper.
*/
public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) {
this.autoGrowNestedPaths = autoGrowNestedPaths;
}
/**
* If this BeanWrapper should "auto grow" nested paths.
* Return whether "auto-growing" of nested paths has been activated.
*/
public boolean isAutoGrowNestedPaths() {
return this.autoGrowNestedPaths;
}
/**
* Specify a limit for array and collection auto-growing.
* <p>Default is unlimited on a plain BeanWrapper.
*/
public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
this.autoGrowCollectionLimit = autoGrowCollectionLimit;
}
/**
* Return the limit for array and collection auto-growing.
*/
public int getAutoGrowCollectionLimit() {
return this.autoGrowCollectionLimit;
}
/**
* Set the security context used during the invocation of the wrapped instance methods.
* Can be null.
@@ -586,21 +605,25 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
PropertyTokenHolder tokens = new PropertyTokenHolder();
tokens.actualName = propertyName;
tokens.canonicalName = propertyName;
setPropertyValue(tokens, createDefaultPropertyValue(tokens));
return getPropertyValue(tokens);
return setDefaultValue(tokens);
}
private Object setDefaultValue(PropertyTokenHolder tokens) {
setPropertyValue(tokens, createDefaultPropertyValue(tokens));
PropertyValue pv = createDefaultPropertyValue(tokens);
setPropertyValue(tokens, pv);
return getPropertyValue(tokens);
}
private PropertyValue createDefaultPropertyValue(PropertyTokenHolder tokens) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(tokens.actualName);
Object defaultValue = newValue(pd.getPropertyType(), tokens.canonicalName);
Class type = getPropertyType(tokens.canonicalName);
if (type == null) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Could not determine property type for auto-growing a default value");
}
Object defaultValue = newValue(type, tokens.canonicalName);
return new PropertyValue(tokens.canonicalName, defaultValue);
}
private Object newValue(Class<?> type, String name) {
try {
if (type.isArray()) {
@@ -630,7 +653,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
}
}
/**
* Create a new nested BeanWrapper instance.
* <p>Default implementation creates a BeanWrapperImpl instance.
@@ -791,9 +814,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
// must not kick in for map keys but rather only for map values.
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));
// Pass full property name and old value in here, since we want full
// conversion ability for map values.
growMapIfNecessary(map, convertedMapKey, indexedPropertyName, pd, i + 1);
value = map.get(convertedMapKey);
}
else {
@@ -833,15 +853,16 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
return array;
}
int length = Array.getLength(array);
if (index >= length) {
if (index >= length && index < this.autoGrowCollectionLimit) {
Class<?> componentType = array.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, index + 1);
System.arraycopy(array, 0, newArray, 0, length);
for (int i = length; i < Array.getLength(newArray); i++) {
Array.set(newArray, i, newValue(componentType, name));
}
// TODO this is not efficient because conversion may create a copy ... set directly because we know it is assignable.
setPropertyValue(name, newArray);
return newArray;
return getPropertyValue(name);
}
else {
return array;
@@ -855,7 +876,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
if (!this.autoGrowNestedPaths) {
return;
}
if (index >= collection.size()) {
int size = collection.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
Class elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);
if (elementType != null) {
for (int i = collection.size(); i < index + 1; i++) {
@@ -865,21 +887,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
@SuppressWarnings("unchecked")
private void growMapIfNecessary(
Map map, Object key, String name, PropertyDescriptor pd, int nestingLevel) {
if (!this.autoGrowNestedPaths) {
return;
}
if (!map.containsKey(key)) {
Class valueType = GenericCollectionTypeResolver.getMapValueReturnType(pd.getReadMethod(), nestingLevel);
if (valueType != null) {
map.put(key, newValue(valueType, name));
}
}
}
@Override
public void setPropertyValue(String propertyName, Object value) throws BeansException {
BeanWrapperImpl nestedBw;
@@ -946,13 +953,13 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
}
else if (propValue.getClass().isArray()) {
if (propValue.getClass().isArray()) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
Class requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
if (isExtractOldValueForEditor()) {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
@@ -976,23 +983,30 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
if (index < list.size()) {
list.set(index, convertedValue);
}
else if (index >= list.size()) {
for (int i = list.size(); i < index; i++) {
int size = list.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
for (int i = size; i < index; i++) {
try {
list.add(null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot set element with index " + index + " in List of size " +
list.size() + ", accessed using property path '" + propertyName +
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
else {
try {
list.set(index, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid list index in property path '" + propertyName + "'", ex);
}
}
}
else if (propValue instanceof Map) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
@@ -50,7 +50,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
* @see #add(String, Object)
*/
public MutablePropertyValues() {
this.propertyValueList = new ArrayList<PropertyValue>();
this.propertyValueList = new ArrayList<PropertyValue>(0);
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import java.beans.PropertyEditor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -136,7 +137,10 @@ class TypeConverterDelegate {
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
if (editor == null && conversionService != null && convertedValue != null) {
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue);
TypeDescriptor targetTypeDesc = typeDescriptor.forElementType(requiredType);
TypeDescriptor targetTypeDesc = typeDescriptor;
if (requiredType != null && !requiredType.isAssignableFrom(typeDescriptor.getType())) {
targetTypeDesc = typeDescriptor.forElementType(requiredType);
}
if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
}
@@ -223,7 +227,8 @@ class TypeConverterDelegate {
}
if (editor != null) {
msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
"] returned inappropriate value");
"] returned inappropriate value of type [").append(
ClassUtils.getDescriptiveType(convertedValue)).append("]");
throw new IllegalArgumentException(msg.toString());
}
else {
@@ -459,11 +464,20 @@ class TypeConverterDelegate {
protected Collection convertToTypedCollection(
Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
boolean originalAllowed = requiredType.isInstance(original);
if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) {
if (!Collection.class.isAssignableFrom(requiredType)) {
return original;
}
boolean approximable = CollectionFactory.isApproximableCollectionType(requiredType);
if (!approximable && !canCreateCopy(requiredType)) {
if (logger.isDebugEnabled()) {
logger.debug("Custom Collection type [" + original.getClass().getName() +
"] does not allow for creating a copy - injecting original Collection as-is");
}
return original;
}
boolean originalAllowed = requiredType.isInstance(original);
MethodParameter methodParam = typeDescriptor.getMethodParameter();
Class elementType = null;
if (methodParam != null) {
@@ -488,14 +502,14 @@ class TypeConverterDelegate {
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot access Collection of type [" + original.getClass().getName() +
"] - injecting original Collection as-is", ex);
"] - injecting original Collection as-is: " + ex);
}
return original;
}
Collection convertedCopy;
try {
if (CollectionFactory.isApproximableCollectionType(requiredType)) {
if (approximable) {
convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
}
else {
@@ -505,7 +519,7 @@ class TypeConverterDelegate {
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot create copy of Collection type [" + original.getClass().getName() +
"] - injecting original Collection as-is", ex);
"] - injecting original Collection as-is: " + ex);
}
return original;
}
@@ -528,7 +542,7 @@ class TypeConverterDelegate {
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Collection type [" + original.getClass().getName() +
"] seems to be read-only - injecting original Collection as-is", ex);
"] seems to be read-only - injecting original Collection as-is: " + ex);
}
return original;
}
@@ -541,11 +555,20 @@ class TypeConverterDelegate {
protected Map convertToTypedMap(
Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
boolean originalAllowed = requiredType.isInstance(original);
if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) {
if (!Map.class.isAssignableFrom(requiredType)) {
return original;
}
boolean approximable = CollectionFactory.isApproximableMapType(requiredType);
if (!approximable && !canCreateCopy(requiredType)) {
if (logger.isDebugEnabled()) {
logger.debug("Custom Map type [" + original.getClass().getName() +
"] does not allow for creating a copy - injecting original Map as-is");
}
return original;
}
boolean originalAllowed = requiredType.isInstance(original);
Class keyType = null;
Class valueType = null;
MethodParameter methodParam = typeDescriptor.getMethodParameter();
@@ -572,14 +595,14 @@ class TypeConverterDelegate {
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot access Map of type [" + original.getClass().getName() +
"] - injecting original Map as-is", ex);
"] - injecting original Map as-is: " + ex);
}
return original;
}
Map convertedCopy;
try {
if (CollectionFactory.isApproximableMapType(requiredType)) {
if (approximable) {
convertedCopy = CollectionFactory.createApproximateMap(original, original.size());
}
else {
@@ -589,7 +612,7 @@ class TypeConverterDelegate {
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot create copy of Map type [" + original.getClass().getName() +
"] - injecting original Map as-is", ex);
"] - injecting original Map as-is: " + ex);
}
return original;
}
@@ -617,7 +640,7 @@ class TypeConverterDelegate {
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Map type [" + original.getClass().getName() +
"] seems to be read-only - injecting original Map as-is", ex);
"] seems to be read-only - injecting original Map as-is: " + ex);
}
return original;
}
@@ -638,4 +661,9 @@ class TypeConverterDelegate {
null);
}
private boolean canCreateCopy(Class requiredType) {
return (!requiredType.isInterface() && !Modifier.isAbstract(requiredType.getModifiers()) &&
Modifier.isPublic(requiredType.getModifiers()) && ClassUtils.hasConstructor(requiredType));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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,6 +208,11 @@ public abstract class BeanFactoryUtils {
* <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
* will get initialized. If the object created by the FactoryBean doesn't match,
* the raw FactoryBean itself will be matched against the type.
* <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
* i.e. such beans will be returned from the lowest factory that they are being found in,
* hiding corresponding beans in ancestor factories.</b> This feature allows for
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
* @param type type of bean to match
* @return the Map of matching bean instances, or an empty Map if none
@@ -239,12 +244,16 @@ public abstract class BeanFactoryUtils {
* Return all beans of the given type or subtypes, also picking up beans defined in
* ancestor bean factories if the current bean factory is a HierarchicalBeanFactory.
* The returned Map will only contain beans of this type.
* <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
* flag is set, which means that FactoryBeans will get initialized. If the
* object created by the FactoryBean doesn't match, the raw FactoryBean itself
* will be matched against the type. If "allowEagerInit" is not set,
* only raw FactoryBeans will be checked (which doesn't require initialization
* of each FactoryBean).
* <p>Does consider objects created by FactoryBeans if the "allowEagerInit" flag is set,
* which means that FactoryBeans will get initialized. If the object created by the
* FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
* type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
* (which doesn't require initialization of each FactoryBean).
* <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
* i.e. such beans will be returned from the lowest factory that they are being found in,
* hiding corresponding beans in ancestor factories.</b> This feature allows for
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
* @param type type of bean to match
* @param includeNonSingletons whether to include prototype or scoped beans too
@@ -291,6 +300,11 @@ public abstract class BeanFactoryUtils {
* the raw FactoryBean itself will be matched against the type.
* <p>This version of <code>beanOfTypeIncludingAncestors</code> automatically includes
* prototypes and FactoryBeans.
* <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
* i.e. such beans will be returned from the lowest factory that they are being found in,
* hiding corresponding beans in ancestor factories.</b> This feature allows for
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
* @param type type of bean to match
* @return the matching bean instance
@@ -315,12 +329,16 @@ public abstract class BeanFactoryUtils {
* defined in ancestor bean factories if the current bean factory is a
* HierarchicalBeanFactory. Useful convenience method when we expect a
* single bean and don't care about the bean name.
* <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
* flag is set, which means that FactoryBeans will get initialized. If the
* object created by the FactoryBean doesn't match, the raw FactoryBean itself
* will be matched against the type. If "allowEagerInit" is not set,
* only raw FactoryBeans will be checked (which doesn't require initialization
* of each FactoryBean).
* <p>Does consider objects created by FactoryBeans if the "allowEagerInit" flag is set,
* which means that FactoryBeans will get initialized. If the object created by the
* FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
* type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
* (which doesn't require initialization of each FactoryBean).
* <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
* i.e. such beans will be returned from the lowest factory that they are being found in,
* hiding corresponding beans in ancestor factories.</b> This feature allows for
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
* @param type type of bean to match
* @param includeNonSingletons whether to include prototype or scoped beans too
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2011 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,6 +16,7 @@
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -46,16 +47,25 @@ import java.lang.annotation.Target;
* declared value type. In case of a Map, the keys must be declared as
* type String and will be resolved to the corresponding bean names.
*
* <p>Please do consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
* <p>Note that actual injection is performed through a
* {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} which in turn means that you <em>cannot</em>
* use {@code @Autowired} to inject references into
* {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} or {@link BeanFactoryPostProcessor} types. Please
* consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
* class (which, by default, checks for the presence of this annotation).
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -38,7 +38,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
@@ -51,6 +50,7 @@ import org.springframework.beans.factory.config.InstantiationAwareBeanPostProces
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
@@ -62,8 +62,11 @@ import org.springframework.util.ReflectionUtils;
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
* that autowires annotated fields, setter methods and arbitrary config methods.
* Such members to be injected are detected through a Java 5 annotation:
* by default, Spring's {@link Autowired} annotation.
* Such members to be injected are detected through a Java 5 annotation: by default,
* Spring's {@link Autowired @Autowired} and {@link Value @Value} annotations.
*
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available, as a direct alternative to Spring's own <code>@Autowired</code>.
*
* <p>Only one constructor (at max) of any given bean class may carry this
* annotation with the 'required' parameter set to <code>true</code>,
@@ -78,27 +81,25 @@ import org.springframework.util.ReflectionUtils;
* <p>Fields are injected right after construction of a bean, before any
* config methods are invoked. Such a config field does not have to be public.
*
* <p>Config methods may have an arbitrary name and any number of arguments;
* each of those arguments will be autowired with a matching bean in the
* Spring container. Bean property setter methods are effectively just
* a special case of such a general config method. Such config methods
* do not have to be public.
*
* <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.
* <p>Config methods may have an arbitrary name and any number of arguments; each of
* those arguments will be autowired with a matching bean in the Spring container.
* Bean property setter methods are effectively just a special case of such a
* general config method. Config methods do not have to be public.
*
* <p>Note: A default AutowiredAnnotationBeanPostProcessor will be registered
* by the "context:annotation-config" and "context:component-scan" XML tags.
* Remove or turn off the default annotation configuration there if you intend
* to specify a custom AutowiredAnnotationBeanPostProcessor bean definition.
* <p><b>NOTE:</b> Annotation injection will be performed <i>before</i> XML injection; thus
* the latter configuration will override the former for properties wired through
* both approaches.
*
* <p><b>NOTE:</b> Annotation injection will be performed <i>before</i> XML injection;
* thus the latter configuration will override the former for properties wired through
* both approaches.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 2.5
* @see #setAutowiredAnnotationType
* @see Autowired
* @see Value
*/
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
@@ -116,8 +117,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
private ConfigurableListableBeanFactory beanFactory;
private final Map<Class<?>, Constructor[]> candidateConstructorsCache =
new ConcurrentHashMap<Class<?>, Constructor[]>();
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache =
new ConcurrentHashMap<Class<?>, Constructor<?>[]>();
private final Map<Class<?>, InjectionMetadata> injectionMetadataCache =
new ConcurrentHashMap<Class<?>, InjectionMetadata>();
@@ -306,7 +307,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
private InjectionMetadata findAutowiringMetadata(Class clazz) {
private InjectionMetadata findAutowiringMetadata(Class<?> clazz) {
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
if (metadata == null) {
@@ -321,7 +322,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(Class clazz) {
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
Class<?> targetClass = clazz;
@@ -341,7 +342,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
}
for (Method method : targetClass.getDeclaredMethods()) {
Annotation annotation = findAutowiredAnnotation(method);
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
Annotation annotation = BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod) ?
findAutowiredAnnotation(bridgedMethod) : findAutowiredAnnotation(method);
if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
@@ -469,14 +472,14 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required);
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
value = beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
synchronized (this) {
if (!this.cached) {
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required);
this.cachedFieldValue = descriptor;
value = beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
if (value != null) {
if (value != null || this.required) {
this.cachedFieldValue = descriptor;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
@@ -492,10 +495,6 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
this.cached = true;
}
else {
// Already cached in the meantime...
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
}
}
if (value != null) {
@@ -528,11 +527,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
if (this.skip == null && this.pd != null && pvs != null && pvs.contains(this.pd.getName())) {
// Explicit value provided as part of the bean definition.
this.skip = Boolean.TRUE;
}
if (this.skip != null && this.skip) {
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
@@ -543,26 +538,29 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
arguments = resolveCachedArguments(beanName);
}
else {
Class<?>[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
GenericTypeResolver.resolveParameterType(methodParam, bean.getClass());
descriptors[i] = new DependencyDescriptor(methodParam, this.required);
arguments[i] = beanFactory.resolveDependency(
descriptors[i], beanName, autowiredBeanNames, typeConverter);
if (arguments[i] == null && !this.required) {
arguments = null;
break;
}
}
synchronized (this) {
if (!this.cached) {
Class[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
Set<String> autowiredBeanNames = new LinkedHashSet<String>(arguments.length);
TypeConverter typeConverter = beanFactory.getTypeConverter();
this.cachedMethodArguments = new Object[arguments.length];
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
GenericTypeResolver.resolveParameterType(methodParam, bean.getClass());
DependencyDescriptor descriptor = new DependencyDescriptor(methodParam, this.required);
this.cachedMethodArguments[i] = descriptor;
arguments[i] = beanFactory.resolveDependency(
descriptor, beanName, autowiredBeanNames, typeConverter);
if (arguments[i] == null) {
arguments = null;
break;
}
}
if (arguments != null) {
this.cachedMethodArguments = new Object[arguments.length];
for (int i = 0; i < arguments.length; i++) {
this.cachedMethodArguments[i] = descriptors[i];
}
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == paramTypes.length) {
Iterator<String> it = autowiredBeanNames.iterator();
@@ -573,9 +571,6 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
}
}
else {
this.cachedMethodArguments[i] = arguments[i];
}
}
}
}
@@ -584,18 +579,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
this.cached = true;
}
else {
// Already cached in the meantime...
arguments = resolveCachedArguments(beanName);
}
}
}
if (this.skip == null) {
if (this.pd != null && pvs instanceof MutablePropertyValues) {
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
}
this.skip = Boolean.FALSE;
}
if (arguments != null) {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2011 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,10 +34,10 @@ import java.lang.annotation.Target;
* @author Ramnivas Laddad
* @since 2.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Configurable {
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -147,10 +147,7 @@ public class InjectionMetadata {
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (this.skip == null) {
this.skip = checkPropertySkipping(pvs);
}
if (this.skip) {
if (checkPropertySkipping(pvs)) {
return;
}
try {
@@ -170,16 +167,26 @@ public class InjectionMetadata {
* affected property as processed for other processors to ignore it.
*/
protected boolean checkPropertySkipping(PropertyValues pvs) {
if (this.pd != null && pvs != null) {
if (pvs.contains(this.pd.getName())) {
// Explicit value provided as part of the bean definition.
return true;
}
else if (pvs instanceof MutablePropertyValues) {
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
if (this.skip == null) {
if (pvs != null) {
synchronized (pvs) {
if (this.skip == null) {
if (this.pd != null) {
if (pvs.contains(this.pd.getName())) {
// Explicit value provided as part of the bean definition.
this.skip = true;
return true;
}
else if (pvs instanceof MutablePropertyValues) {
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
}
}
}
}
}
this.skip = false;
}
return false;
return this.skip;
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2011 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,10 @@ import java.lang.annotation.Target;
* @author Mark Fisher
* @author Juergen Hoeller
* @since 2.5
* @see Autowired
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -164,8 +164,11 @@ public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanP
* @return <code>true</code> to skip the bean; <code>false</code> to process it
*/
protected boolean shouldSkip(ConfigurableListableBeanFactory beanFactory, String beanName) {
return (beanFactory != null && beanFactory.containsBeanDefinition(beanName) &&
Boolean.TRUE.equals(beanFactory.getBeanDefinition(beanName).getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE)));
if (beanFactory == null || !beanFactory.containsBeanDefinition(beanName)) {
return false;
}
Object value = beanFactory.getBeanDefinition(beanName).getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE);
return (value != null && (Boolean.TRUE.equals(value) || Boolean.valueOf(value.toString())));
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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,6 +16,7 @@
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -31,13 +32,25 @@ import java.lang.annotation.Target;
* <p>A common use case is to assign default field values using
* "#{systemProperties.myProp}" style expressions.
*
* <p>Note that actual processing of the {@code @Value} annotation is performed
* by a {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} which in turn means that you <em>cannot</em> use
* {@code @Value} within
* {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} or {@link BeanFactoryPostProcessor} types. Please
* consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
* class (which, by default, checks for the presence of this annotation).
*
* @author Juergen Hoeller
* @since 3.0
* @see AutowiredAnnotationBeanPostProcessor
* @see Autowired
* @see org.springframework.beans.factory.config.BeanExpressionResolver
* @see org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -115,7 +115,7 @@ public class BeanDefinitionVisitor {
}
protected void visitFactoryMethodName(BeanDefinition beanDefinition) {
String factoryMethodName = beanDefinition.getFactoryBeanName();
String factoryMethodName = beanDefinition.getFactoryMethodName();
if (factoryMethodName != null) {
String resolvedName = resolveStringValue(factoryMethodName);
if (!factoryMethodName.equals(resolvedName)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -173,7 +173,7 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
* @param requiredType type of the property
* @param propertyEditorClass the {@link PropertyEditor} class to register
*/
void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass);
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
/**
* Initialize the given PropertyEditorRegistry with the custom editors
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ import org.springframework.util.ObjectUtils;
*/
public class ConstructorArgumentValues {
private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<Integer, ValueHolder>();
private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<Integer, ValueHolder>(0);
private final List<ValueHolder> genericArgumentValues = new LinkedList<ValueHolder>();
@@ -28,7 +28,6 @@ import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -144,7 +143,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
/** Cache of filtered PropertyDescriptors: bean Class -> PropertyDescriptor array */
private final Map<Class, PropertyDescriptor[]> filteredPropertyDescriptorsCache =
new HashMap<Class, PropertyDescriptor[]>();
new ConcurrentHashMap<Class, PropertyDescriptor[]>();
/**
@@ -567,7 +566,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
@Override
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
Class beanClass;
if (mbd.getFactoryMethodName() != null) {
beanClass = getTypeForFactoryMethod(beanName, mbd, typesToMatch);
@@ -1201,22 +1200,25 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @see #isExcludedFromDependencyCheck
*/
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
synchronized (this.filteredPropertyDescriptorsCache) {
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
List<PropertyDescriptor> pds =
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
PropertyDescriptor pd = it.next();
if (isExcludedFromDependencyCheck(pd)) {
it.remove();
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
synchronized (this.filteredPropertyDescriptorsCache) {
filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
List<PropertyDescriptor> pds =
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
PropertyDescriptor pd = it.next();
if (isExcludedFromDependencyCheck(pd)) {
it.remove();
}
}
filtered = pds.toArray(new PropertyDescriptor[pds.size()]);
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
}
filtered = pds.toArray(new PropertyDescriptor[pds.size()]);
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
}
return filtered;
}
return filtered;
}
/**
@@ -147,7 +147,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
private boolean primary = false;
private final Map<String, AutowireCandidateQualifier> qualifiers =
new LinkedHashMap<String, AutowireCandidateQualifier>();
new LinkedHashMap<String, AutowireCandidateQualifier>(0);
private boolean nonPublicAccessAllowed = true;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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,6 +42,7 @@ import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyEditorRegistrySupport;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
@@ -166,6 +167,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<Object>("Prototype beans currently in creation");
/**
* Create a new AbstractBeanFactory.
*/
@@ -189,7 +191,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@@ -346,7 +348,16 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
@@ -373,6 +384,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return !BeanFactoryUtils.isFactoryDereference(name);
}
}
else if (containsSingleton(beanName)) {
return true;
}
else {
// No singleton instance found -> check bean definition.
@@ -465,6 +479,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
typeToMatch.isAssignableFrom(beanInstance.getClass());
}
}
else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
// null instance registered
return false;
}
else {
// No singleton instance found -> check bean definition.
@@ -524,6 +542,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return beanInstance.getClass();
}
}
else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
// null instance registered
return null;
}
else {
// No singleton instance found -> check bean definition.
@@ -671,7 +693,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.propertyEditorRegistrars;
}
public void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
Assert.notNull(requiredType, "Required type must not be null");
Assert.isAssignable(PropertyEditor.class, propertyEditorClass);
this.customEditors.put(requiredType, propertyEditorClass);
@@ -860,6 +882,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
}
else if (containsSingleton(beanName)) {
// null instance registered
return false;
}
// No singleton instance found -> check bean definition.
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
@@ -904,13 +930,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
protected void afterPrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal instanceof String) {
this.prototypesCurrentlyInCreation.set(null);
this.prototypesCurrentlyInCreation.remove();
}
else if (curVal instanceof Set) {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.remove(beanName);
if (beanNameSet.isEmpty()) {
this.prototypesCurrentlyInCreation.set(null);
this.prototypesCurrentlyInCreation.remove();
}
}
}
@@ -1238,7 +1264,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException {
if (!ObjectUtils.isEmpty(typesToMatch)) {
ClassLoader tempClassLoader = getTempClassLoader();
@@ -44,7 +44,6 @@ import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
@@ -467,7 +466,7 @@ class ConstructorResolver {
this.beanFactory.logger.trace("Ignoring factory method [" + candidate +
"] of bean '" + beanName + "': " + ex);
}
if (i == candidates.length - 1 && factoryMethodToUse == null) {
if (i == candidates.length - 1 && argsHolderToUse == null) {
if (causes != null) {
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
@@ -515,13 +514,13 @@ class ConstructorResolver {
}
if (factoryMethodToUse == null) {
boolean hasArgs = resolvedValues.getArgumentCount() > 0;
boolean hasArgs = (resolvedValues.getArgumentCount() > 0);
String argDesc = "";
if (hasArgs) {
List<String> argTypes = new ArrayList<String>();
for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) {
String argType = value.getType() != null ?
ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName();
String argType = (value.getType() != null ?
ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName());
argTypes.add(argType);
}
argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
@@ -548,7 +547,7 @@ class ConstructorResolver {
ambiguousFactoryMethods);
}
if (explicitArgs == null) {
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
@@ -686,15 +685,18 @@ class ConstructorResolver {
try {
convertedValue = converter.convertIfNecessary(originalValue, paramType,
MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex));
// TODO re-enable once race condition has been found (SPR-7423)
/*
if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {
// Either a converted value or still the original one: store converted value.
sourceHolder.setConvertedValue(convertedValue);
args.preparedArguments[paramIndex] = convertedValue;
}
else {
*/
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
// }
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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,9 @@
package org.springframework.beans.factory.support;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
@@ -541,7 +543,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
/**
* Considers all beans as eligible for metdata caching
* Considers all beans as eligible for metadata caching
* if the factory's configuration has been marked as frozen.
* @see #freezeConfiguration()
*/
@@ -554,9 +556,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
synchronized (this.beanDefinitionMap) {
for (String beanName : this.beanDefinitionNames) {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
@@ -570,7 +574,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}, getAccessControlContext());
}
else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
@@ -664,8 +669,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
destroySingleton(beanName);
}
// Reset all bean definitions that have the given bean as parent
// (recursively).
// Reset all bean definitions that have the given bean as parent (recursively).
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
@@ -711,7 +715,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
@@ -944,6 +948,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new NotSerializableException("DefaultListableBeanFactory itself is not deserializable - " +
"just a SerializedBeanFactoryReference is");
}
protected Object writeReplace() throws ObjectStreamException {
if (this.serializationId != null) {
return new SerializedBeanFactoryReference(this.serializationId);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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 @@ import java.util.Set;
*/
public class MethodOverrides {
private final Set<MethodOverride> overrides = new HashSet<MethodOverride>();
private final Set<MethodOverride> overrides = new HashSet<MethodOverride>(0);
/**
@@ -48,11 +48,11 @@ import org.springframework.util.Assert;
*/
public class RootBeanDefinition extends AbstractBeanDefinition {
private final Set<Member> externallyManagedConfigMembers = Collections.synchronizedSet(new HashSet<Member>());
private final Set<Member> externallyManagedConfigMembers = Collections.synchronizedSet(new HashSet<Member>(0));
private final Set<String> externallyManagedInitMethods = Collections.synchronizedSet(new HashSet<String>());
private final Set<String> externallyManagedInitMethods = Collections.synchronizedSet(new HashSet<String>(0));
private final Set<String> externallyManagedDestroyMethods = Collections.synchronizedSet(new HashSet<String>());
private final Set<String> externallyManagedDestroyMethods = Collections.synchronizedSet(new HashSet<String>(0));
private BeanDefinitionHolder decoratedDefinition;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -1176,7 +1176,10 @@ public class BeanDefinitionParserDelegate {
}
else {
// Child element is what we're looking for.
if (valueEle != null) {
if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) {
// the element is a <description> -> ignore it
}
else if (valueEle != null) {
error("<entry> element must not contain more than one value sub-element", entryEle);
}
else {
@@ -1422,7 +1425,7 @@ public class BeanDefinitionParserDelegate {
/**
* Determine whether the name of the supplied node is equal to the supplied name.
* <p>The default implementation checks the supplied desired name against both
* {@link Node#getNodeName()) and {@link Node#getLocalName()}.
* {@link Node#getNodeName()} and {@link Node#getLocalName()}.
* <p>Subclasses may override the default implementation to provide a different
* mechanism for comparing node names.
* @param node the node to compare
@@ -344,7 +344,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.set(null);
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.beans.propertyeditors;
import java.beans.PropertyEditorSupport;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -30,6 +31,7 @@ import org.springframework.util.StringUtils;
* to the standard {@link Class#forName(String)} method.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 2.0
*/
public class ClassArrayEditor extends PropertyEditorSupport {
@@ -52,8 +54,7 @@ public class ClassArrayEditor extends PropertyEditorSupport {
* (or pass <code>null</code> for the thread context <code>ClassLoader</code>)
*/
public ClassArrayEditor(ClassLoader classLoader) {
this.classLoader = classLoader != null
? classLoader : ClassUtils.getDefaultClassLoader();
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}
@@ -76,14 +77,9 @@ public class ClassArrayEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
Class[] classes = (Class[]) getValue();
if (classes == null || classes.length == 0) {
if (ObjectUtils.isEmpty(classes)) {
return "";
}
return toCommaDelimitedString(classes);
}
private static String toCommaDelimitedString(Class[] classes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < classes.length; ++i) {
if (i > 0) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2010 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,8 +53,7 @@ public class ClassEditor extends PropertyEditorSupport {
* (or <code>null</code> for the thread context ClassLoader)
*/
public ClassEditor(ClassLoader classLoader) {
this.classLoader =
(classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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,10 +34,6 @@ public class CurrencyEditor extends PropertyEditorSupport {
setValue(Currency.getInstance(text));
}
/**
* This implementation returns <code>null</code> to indicate that
* there is no appropriate text representation.
*/
@Override
public String getAsText() {
Currency value = (Currency) getValue();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2011 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,7 +77,10 @@ public class CustomDateEditor extends PropertyEditorSupport {
* thrown if the String does not exactly match the length specified. This is useful
* because SimpleDateFormat does not enforce strict parsing of the year part,
* not even with <code>setLenient(false)</code>. Without an "exactDateLength"
* specified, the "01/01/05" would get parsed to "01/01/0005".
* specified, the "01/01/05" would get parsed to "01/01/0005". However, even
* with an "exactDateLength" specified, prepended zeros in the day or month
* part may still allow for a shorter year part, so consider this as just
* one more assertion that gets you closer to the intended date format.
* @param dateFormat DateFormat to use for parsing and rendering
* @param allowEmpty if empty strings should be allowed
* @param exactDateLength the exact expected length of the date String
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,12 +27,14 @@ import org.xml.sax.InputSource;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyEditorRegistrySupport;
import org.springframework.beans.propertyeditors.ClassArrayEditor;
import org.springframework.beans.propertyeditors.ClassEditor;
import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.URIEditor;
import org.springframework.beans.propertyeditors.URLEditor;
import org.springframework.core.io.ContextResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
@@ -83,14 +85,16 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader);
doRegisterEditor(registry, Resource.class, baseEditor);
doRegisterEditor(registry, ContextResource.class, baseEditor);
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
ClassLoader classLoader = this.resourceLoader.getClassLoader();
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));
if (this.resourceLoader instanceof ResourcePatternResolver) {
doRegisterEditor(registry, Resource[].class,
@@ -864,7 +864,7 @@
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="listOrSetType">
<xsd:attribute name="merge" type="defaultable-boolean">
<xsd:attribute name="merge" default="default" type="defaultable-boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Enables/disables merging for collections when using parent/child beans.
@@ -887,7 +887,7 @@
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="listOrSetType">
<xsd:attribute name="merge" type="defaultable-boolean">
<xsd:attribute name="merge" default="default" type="defaultable-boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Enables/disables merging for collections when using parent/child beans.
@@ -908,7 +908,7 @@
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="listOrSetType">
<xsd:attribute name="merge" type="defaultable-boolean">
<xsd:attribute name="merge" default="default" type="defaultable-boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Enables/disables merging for collections when using parent/child beans.
@@ -929,7 +929,7 @@
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="mapType">
<xsd:attribute name="merge" type="defaultable-boolean">
<xsd:attribute name="merge" default="default" type="defaultable-boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Enables/disables merging for collections when using parent/child beans.
@@ -960,7 +960,7 @@
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="propsType">
<xsd:attribute name="merge" type="defaultable-boolean">
<xsd:attribute name="merge" default="default" type="defaultable-boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Enables/disables merging for collections when using parent/child beans.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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,10 +19,11 @@ package org.springframework.beans;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Keith Donald
* @author Juergen Hoeller
@@ -117,6 +118,19 @@ public class BeanWrapperAutoGrowingTests {
assertNotNull(wrapper.getPropertyValue("list[3]"));
}
@Test
public void getPropertyValueAutoGrowListFailsAgainstLimit() {
wrapper.setAutoGrowCollectionLimit(2);
try {
assertNotNull(wrapper.getPropertyValue("list[4]"));
fail("Should have thrown InvalidPropertyException");
}
catch (InvalidPropertyException ex) {
// expected
assertTrue(ex.getRootCause() instanceof IndexOutOfBoundsException);
}
}
@Test
public void getPropertyValueAutoGrowMultiDimensionalList() {
assertNotNull(wrapper.getPropertyValue("multiList[0][0]"));
@@ -129,17 +143,10 @@ public class BeanWrapperAutoGrowingTests {
wrapper.getPropertyValue("listNotParameterized[0]");
}
@Test
public void getPropertyValueAutoGrowMap() {
assertNotNull(wrapper.getPropertyValue("map[A]"));
assertEquals(1, bean.getMap().size());
assertTrue(bean.getMap().get("A") instanceof Bean);
}
@Test
public void setPropertyValueAutoGrowMap() {
wrapper.setPropertyValue("map[A].prop", "test");
assertEquals("test", bean.getMap().get("A").getProp());
wrapper.setPropertyValue("map[A]", new Bean());
assertTrue(bean.getMap().get("A") instanceof Bean);
}
@@ -36,6 +36,7 @@ import javax.security.auth.Subject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Test;
import test.beans.DerivedTestBean;
import test.beans.DummyFactory;
@@ -1752,6 +1753,7 @@ public class DefaultListableBeanFactoryTests {
*/
@Test
@Ignore // TODO re-enable when ConstructorResolver TODO sorted out
public void testPrototypeCreationWithConstructorArgumentsIsFastEnough() {
if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
// Skip this test: Trace logging blows the time limit.
@@ -0,0 +1,44 @@
package org.springframework.beans.factory.config;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ByteArrayResource;
import test.beans.TestBean;
/**
* Tests cornering SPR-7547.
*
* @author Chris Beams
*/
public class PropertyPlaceholderConfigurerTests {
/**
* Prior to the fix for SPR-7547, the following would throw
* IllegalStateException because the PropertiesLoaderSupport base class
* assumed ByteArrayResource implements Resource.getFilename(). It does
* not, and AbstractResource.getFilename() is called instead, raising the
* exception. The following now works, as getFilename() is called in a
* try/catch to check whether the resource is actually file-based or not.
*
* See SPR-7552, which suggests paths to address the root issue rather than
* just patching the problem.
*/
@Test
public void repro() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",
rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}").getBeanDefinition());
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocation(new ByteArrayResource("my.name=Inigo Montoya".getBytes()));
ppc.postProcessBeanFactory(bf);
TestBean testBean = bf.getBean(TestBean.class);
assertThat(testBean.getName(), equalTo("Inigo Montoya"));
}
}
@@ -155,6 +155,18 @@
</property>
</bean>
<!-- The <description> element below caused parsing exception prior to resolution of SPR-8563 -->
<bean id="mapWithDescriptionInEntry" class="org.springframework.beans.factory.xml.HasMap">
<property name="map">
<map>
<entry key="e1">
<description>A map entry with a description</description>
<value>v1</value>
</entry>
</map>
</property>
</bean>
<bean id="fooKey" class="java.lang.String">
<constructor-arg value="foo"/>
</bean>
+3 -1
View File
@@ -26,6 +26,8 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
@@ -49,7 +51,7 @@
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="test->runtime"/>
<dependency org="org.apache.poi" name="com.springsource.org.apache.poi" rev="3.0.2.FINAL" conf="test->compile"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
</dependencies>
</ivy-module>
+2 -2
View File
@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<packaging>jar</packaging>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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,6 +17,7 @@
package org.springframework.cache.ehcache;
import java.io.IOException;
import java.io.InputStream;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
@@ -97,23 +98,17 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
public void afterPropertiesSet() throws IOException, CacheException {
logger.info("Initializing EHCache CacheManager");
if (this.shared) {
// Shared CacheManager singleton at the VM level.
if (this.configLocation != null) {
this.cacheManager = CacheManager.create(this.configLocation.getInputStream());
if (this.configLocation != null) {
InputStream is = this.configLocation.getInputStream();
try {
this.cacheManager = (this.shared ? CacheManager.create(is) : new CacheManager(is));
}
else {
this.cacheManager = CacheManager.create();
finally {
is.close();
}
}
else {
// Independent CacheManager instance (the default).
if (this.configLocation != null) {
this.cacheManager = new CacheManager(this.configLocation.getInputStream());
}
else {
this.cacheManager = new CacheManager();
}
this.cacheManager = (this.shared ? CacheManager.create() : new CacheManager());
}
if (this.cacheManagerName != null) {
this.cacheManager.setName(this.cacheManagerName);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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,13 @@ public class LocalTaskExecutorThreadPool implements ThreadPool {
private Executor taskExecutor;
public void setInstanceId(String schedInstId) {
}
public void setInstanceName(String schedName) {
}
public void initialize() throws SchedulerConfigException {
// Absolutely needs thread-bound TaskExecutor to initialize.
this.taskExecutor = SchedulerFactoryBean.getConfigTimeTaskExecutor();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2011 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,6 +16,7 @@
package org.springframework.scheduling.quartz;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@@ -34,7 +35,6 @@ import org.quartz.SchedulerListener;
import org.quartz.Trigger;
import org.quartz.TriggerListener;
import org.quartz.spi.ClassLoadHelper;
import org.quartz.xml.JobSchedulingDataProcessor;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
@@ -240,9 +240,25 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
if (this.jobSchedulingDataLocations != null) {
ClassLoadHelper clh = new ResourceLoaderClassLoadHelper(this.resourceLoader);
clh.initialize();
JobSchedulingDataProcessor dataProcessor = new JobSchedulingDataProcessor(clh, true, true);
for (String location : this.jobSchedulingDataLocations) {
dataProcessor.processFileAndScheduleJobs(location, getScheduler(), this.overwriteExistingJobs);
try {
// Quartz 1.8 or higher?
Class dataProcessorClass = getClass().getClassLoader().loadClass("org.quartz.xml.XMLSchedulingDataProcessor");
logger.debug("Using Quartz 1.8 XMLSchedulingDataProcessor");
Object dataProcessor = dataProcessorClass.getConstructor(ClassLoadHelper.class).newInstance(clh);
Method processFileAndScheduleJobs = dataProcessorClass.getMethod("processFileAndScheduleJobs", String.class, Scheduler.class);
for (String location : this.jobSchedulingDataLocations) {
processFileAndScheduleJobs.invoke(dataProcessor, location, getScheduler());
}
}
catch (ClassNotFoundException ex) {
// Quartz 1.6
Class dataProcessorClass = getClass().getClassLoader().loadClass("org.quartz.xml.JobSchedulingDataProcessor");
logger.debug("Using Quartz 1.6 JobSchedulingDataProcessor");
Object dataProcessor = dataProcessorClass.getConstructor(ClassLoadHelper.class, boolean.class, boolean.class).newInstance(clh, true, true);
Method processFileAndScheduleJobs = dataProcessorClass.getMethod("processFileAndScheduleJobs", String.class, Scheduler.class, boolean.class);
for (String location : this.jobSchedulingDataLocations) {
processFileAndScheduleJobs.invoke(dataProcessor, location, getScheduler(), this.overwriteExistingJobs);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,9 +74,9 @@ import org.springframework.util.CollectionUtils;
* automatically apply to Scheduler operations performed within those scopes.
* Alternatively, you may add transactional advice for the Scheduler itself.
*
* <p><b>Note:</b> This version of Spring's SchedulerFactoryBean requires
* Quartz 1.5.x or 1.6.x. The "jobSchedulingDataLocation" feature requires
* Quartz 1.6.1 or higher (as of Spring 2.5.5).
* <p><b>Note:</b> This version of Spring's SchedulerFactoryBean supports Quartz 1.x,
* more specifically Quartz 1.5 or higher. The "jobSchedulingDataLocation" feature
* requires Quartz 1.6.1 or higher (as of Spring 2.5.5).
*
* @author Juergen Hoeller
* @since 18.02.2004
@@ -496,16 +496,16 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
finally {
if (this.resourceLoader != null) {
configTimeResourceLoaderHolder.set(null);
configTimeResourceLoaderHolder.remove();
}
if (this.taskExecutor != null) {
configTimeTaskExecutorHolder.set(null);
configTimeTaskExecutorHolder.remove();
}
if (this.dataSource != null) {
configTimeDataSourceHolder.set(null);
configTimeDataSourceHolder.remove();
}
if (this.nonTransactionalDataSource != null) {
configTimeNonTransactionalDataSourceHolder.set(null);
configTimeNonTransactionalDataSourceHolder.remove();
}
}
+3 -1
View File
@@ -29,6 +29,8 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
@@ -63,7 +65,7 @@
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.dbcp" rev="1.2.2.osgi" conf="test->runtime"/>
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
<dependency org="org.slf4j" name="com.springsource.slf4j.jcl" rev="${slf4j.version}" conf="test->runtime"/>
</dependencies>
+2 -2
View File
@@ -6,12 +6,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<packaging>jar</packaging>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.4.BUILD-SNAPSHOT</version>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -49,7 +49,7 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #add} calls and then manually {@link #refresh refreshed}.
* through {@link #register} calls and then manually {@link #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -58,6 +58,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.jndi.support.SimpleJndiBeanFactory;
@@ -303,7 +304,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
}
private InjectionMetadata findResourceMetadata(final Class clazz) {
private InjectionMetadata findResourceMetadata(final Class<?> clazz) {
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
if (metadata == null) {
@@ -338,40 +339,41 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
}
}
for (Method method : targetClass.getDeclaredMethods()) {
if (webServiceRefClass != null && method.isAnnotationPresent(webServiceRefClass) &&
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterTypes().length != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
currElements.add(new WebServiceRefElement(method, pd));
}
else if (ejbRefClass != null && method.isAnnotationPresent(ejbRefClass) &&
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterTypes().length != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
currElements.add(new EjbRefElement(method, pd));
}
else if (method.isAnnotationPresent(Resource.class) &&
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!ignoredResourceTypes.contains(paramTypes[0].getName())) {
method = BridgeMethodResolver.findBridgedMethod(method);
Method mostSpecificMethod = BridgeMethodResolver.findBridgedMethod(ClassUtils.getMostSpecificMethod(method, clazz));
if (method.equals(mostSpecificMethod)) {
if (webServiceRefClass != null && method.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterTypes().length != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
currElements.add(new ResourceElement(method, pd));
currElements.add(new WebServiceRefElement(method, pd));
}
else if (ejbRefClass != null && method.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterTypes().length != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
currElements.add(new EjbRefElement(method, pd));
}
else if (method.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
currElements.add(new ResourceElement(method, pd));
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -107,8 +107,7 @@ final class ConfigurationClass {
public void validate(ProblemReporter problemReporter) {
// a @Bean method may only be overloaded through inheritance. No single
// An @Bean method may only be overloaded through inheritance. No single
// @Configuration class may declare two @Bean methods with the same name.
final char hashDelim = '#';
Map<String, Integer> methodNameCounts = new HashMap<String, Integer>();
@@ -134,9 +133,10 @@ final class ConfigurationClass {
if (getMetadata().isFinal()) {
problemReporter.error(new FinalConfigurationProblem());
}
for (ConfigurationClassMethod method : this.methods) {
method.validate(problemReporter);
}
}
for (ConfigurationClassMethod method : this.methods) {
method.validate(problemReporter);
}
}
@@ -152,7 +152,10 @@ final class ConfigurationClass {
return getMetadata().getClassName().hashCode();
}
/** Configuration classes must be non-final to accommodate CGLIB subclassing. */
/**
* Configuration classes must be non-final to accommodate CGLIB subclassing.
*/
private class FinalConfigurationProblem extends Problem {
public FinalConfigurationProblem() {
@@ -161,7 +164,10 @@ final class ConfigurationClass {
}
}
/** Bean methods on configuration classes may only be overloaded through inheritance. */
/**
* Bean methods on configuration classes may only be overloaded through inheritance.
*/
private class BeanMethodOverloadingProblem extends Problem {
public BeanMethodOverloadingProblem(String methodName, int count) {
@@ -171,5 +177,4 @@ final class ConfigurationClass {
}
}
}
@@ -118,11 +118,9 @@ class ConfigurationClassBeanDefinitionReader {
*/
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass) {
doLoadBeanDefinitionForConfigurationClassIfNecessary(configClass);
for (ConfigurationClassMethod method : configClass.getMethods()) {
loadBeanDefinitionsForModelMethod(method);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
}
@@ -139,7 +137,7 @@ class ConfigurationClassBeanDefinitionReader {
GenericBeanDefinition configBeanDef = new GenericBeanDefinition();
String className = configClass.getMetadata().getClassName();
configBeanDef.setBeanClassName(className);
if(checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
if (checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
String configBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(configBeanDef, this.registry);
configClass.setBeanName(configBeanName);
if (logger.isDebugEnabled()) {
@@ -160,8 +158,8 @@ class ConfigurationClassBeanDefinitionReader {
}
/**
* Reads a particular {@link ConfigurationClassMethod}, registering bean definitions with
* the BeanDefinitionRegistry based on its contents.
* Reads a particular {@link ConfigurationClassMethod}, registering bean definitions
* with the BeanDefinitionRegistry based on its contents.
*/
private void loadBeanDefinitionsForModelMethod(ConfigurationClassMethod method) {
ConfigurationClass configClass = method.getConfigurationClass();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,6 @@
package org.springframework.context.annotation;
import static java.lang.String.format;
import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter;
@@ -54,18 +52,25 @@ final class ConfigurationClassMethod {
}
public Location getResourceLocation() {
return new Location(this.configurationClass.getResource(), metadata);
return new Location(this.configurationClass.getResource(), this.metadata);
}
public void validate(ProblemReporter problemReporter) {
if (this.configurationClass.getMetadata().isAnnotated(Configuration.class.getName()) && !getMetadata().isOverridable()) {
problemReporter.error(new NonOverridableMethodError());
if (this.configurationClass.getMetadata().isAnnotated(Configuration.class.getName())) {
if (!getMetadata().isOverridable()) {
problemReporter.error(new NonOverridableMethodError());
}
}
else {
if (getMetadata().isStatic()) {
problemReporter.error(new StaticMethodError());
}
}
}
@Override
public String toString() {
return format("[%s:name=%s,declaringClass=%s]",
return String.format("[%s:name=%s,declaringClass=%s]",
this.getClass().getSimpleName(), this.getMetadata().getMethodName(), this.getMetadata().getDeclaringClassName());
}
@@ -82,4 +87,15 @@ final class ConfigurationClassMethod {
}
/**
* {@link Bean} methods must at least not be static in the non-CGLIB case.
*/
private class StaticMethodError extends Problem {
public StaticMethodError() {
super(String.format("Method '%s' must not be static; remove the method's static modifier to continue",
getMetadata().getMethodName()), getResourceLocation());
}
}
}
@@ -139,8 +139,8 @@ class ConfigurationClassParser {
}
}
Set<MethodMetadata> beanMethods = metadata.getAnnotatedMethods(Bean.class.getName());
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addMethod(new ConfigurationClassMethod(methodMetadata, configClass));
for (MethodMetadata beanMethod : beanMethods) {
configClass.addMethod(new ConfigurationClassMethod(beanMethod, configClass));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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,6 +17,7 @@
package org.springframework.context.annotation;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -80,9 +81,9 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
private boolean setMetadataReaderFactoryCalled = false;
private boolean postProcessBeanDefinitionRegistryCalled = false;
private final Set<Integer> registriesPostProcessed = new HashSet<Integer>();
private boolean postProcessBeanFactoryCalled = false;
private final Set<Integer> factoriesPostProcessed = new HashSet<Integer>();
/**
@@ -130,15 +131,16 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
* Derive further bean definitions from the configuration classes in the registry.
*/
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.postProcessBeanDefinitionRegistryCalled) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called for this post-processor");
"postProcessBeanDefinitionRegistry already called for this post-processor against " + registry);
}
if (this.postProcessBeanFactoryCalled) {
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called for this post-processor");
"postProcessBeanFactory already called for this post-processor against " + registry);
}
this.postProcessBeanDefinitionRegistryCalled = true;
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
@@ -147,12 +149,13 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
* by replacing them with CGLIB-enhanced subclasses.
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
if (this.postProcessBeanFactoryCalled) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called for this post-processor");
"postProcessBeanFactory already called for this post-processor against " + beanFactory);
}
this.postProcessBeanFactoryCalled = true;
if (!this.postProcessBeanDefinitionRegistryCalled) {
this.factoriesPostProcessed.add((factoryId));
if (!this.registriesPostProcessed.contains((factoryId))) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigBeanDefinitions lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ abstract class AbstractPropertyLoadingBeanDefinitionParser extends AbstractSingl
String fileEncoding = element.getAttribute("file-encoding");
if (StringUtils.hasLength(fileEncoding)) {
builder.addPropertyReference("fileEncoding", fileEncoding);
builder.addPropertyValue("fileEncoding", fileEncoding);
}
String order = element.getAttribute("order");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2011 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.
@@ -38,12 +38,9 @@ class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBea
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
super.doParse(element, builder);
builder.addPropertyValue("ignoreUnresolvablePlaceholders",
Boolean.valueOf(element.getAttribute("ignore-unresolvable")));
String systemPropertiesModeName = element.getAttribute("system-properties-mode");
if (StringUtils.hasLength(systemPropertiesModeName)) {
builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName);
@@ -238,7 +238,7 @@ public abstract class AbstractApplicationEventMulticaster implements Application
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : this.applicationListenerBeans) {
ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!this.preFiltered && !allListeners.contains(listener)) {
if (this.preFiltered || !allListeners.contains(listener)) {
allListeners.add(listener);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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,11 +34,17 @@ import org.springframework.expression.TypedValue;
public class MapAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
return (((Map) target).containsKey(name));
Map map = (Map) target;
return map.containsKey(name);
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(((Map) target).get(name));
Map map = (Map) target;
Object value = map.get(name);
if (value == null && !map.containsKey(name)) {
throw new MapAccessException(name);
}
return new TypedValue(value);
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
@@ -47,11 +53,32 @@ public class MapAccessor implements PropertyAccessor {
@SuppressWarnings("unchecked")
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
((Map) target).put(name, newValue);
Map map = (Map) target;
map.put(name, newValue);
}
public Class[] getSpecificTargetClasses() {
return new Class[] { Map.class };
return new Class[] {Map.class};
}
/**
* Exception thrown from <code>read</code> in order to reset a cached
* PropertyAccessor, allowing other accessors to have a try.
*/
private static class MapAccessException extends AccessException {
private final String key;
public MapAccessException(String key) {
super(null);
this.key = key;
}
@Override
public String getMessage() {
return "Map does not contain a value for key '" + this.key + "'";
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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,7 +24,8 @@ import org.springframework.core.NamedThreadLocal;
/**
* Simple holder class that associates a LocaleContext instance
* with the current thread. The LocaleContext will be inherited
* by any child threads spawned by the current thread.
* by any child threads spawned by the current thread if the
* <code>inheritable<code> flag is set to <code>true</code>.
*
* <p>Used as a central holder for the current Locale in Spring,
* wherever necessary: for example, in MessageSourceAccessor.
@@ -51,15 +52,14 @@ public abstract class LocaleContextHolder {
* Reset the LocaleContext for the current thread.
*/
public static void resetLocaleContext() {
localeContextHolder.set(null);
inheritableLocaleContextHolder.set(null);
localeContextHolder.remove();
inheritableLocaleContextHolder.remove();
}
/**
* Associate the given LocaleContext with the current thread,
* <i>not</i> exposing it as inheritable for child threads.
* @param localeContext the current LocaleContext, or <code>null</code> to reset
* the thread-bound context
* @param localeContext the current LocaleContext
*/
public static void setLocaleContext(LocaleContext localeContext) {
setLocaleContext(localeContext, false);
@@ -67,19 +67,24 @@ public abstract class LocaleContextHolder {
/**
* Associate the given LocaleContext with the current thread.
* @param localeContext the current LocaleContext, or <code>null</code> to reset
* the thread-bound context
* @param localeContext the current LocaleContext,
* or <code>null</code> to reset the thread-bound context
* @param inheritable whether to expose the LocaleContext as inheritable
* for child threads (using an {@link java.lang.InheritableThreadLocal})
*/
public static void setLocaleContext(LocaleContext localeContext, boolean inheritable) {
if (inheritable) {
inheritableLocaleContextHolder.set(localeContext);
localeContextHolder.set(null);
if (localeContext == null) {
resetLocaleContext();
}
else {
localeContextHolder.set(localeContext);
inheritableLocaleContextHolder.set(null);
if (inheritable) {
inheritableLocaleContextHolder.set(localeContext);
localeContextHolder.remove();
}
else {
localeContextHolder.set(localeContext);
inheritableLocaleContextHolder.remove();
}
}
}
@@ -1326,11 +1326,12 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (!(bean instanceof BeanPostProcessor) &&
if (bean != null && !(bean instanceof BeanPostProcessor) &&
this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
if (logger.isInfoEnabled()) {
logger.info("Bean '" + beanName + "' is not eligible for getting processed by all " +
"BeanPostProcessors (for example: not eligible for auto-proxying)");
logger.info("Bean '" + beanName + "' of type [" + bean.getClass() +
"] is not eligible for getting processed by all BeanPostProcessors " +
"(for example: not eligible for auto-proxying)");
}
}
return bean;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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,10 +34,11 @@ import org.springframework.util.StringValueResolver;
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
* implementation that passes the ApplicationContext to beans that
* implement the {@link ResourceLoaderAware}, {@link MessageSourceAware},
* {@link ApplicationEventPublisherAware} and/or
* implement the {@link EmbeddedValueResolverAware}, {@link ResourceLoaderAware},
* {@link MessageSourceAware}, {@link ApplicationEventPublisherAware} and/or
* {@link ApplicationContextAware} interfaces.
* If all of them are implemented, they are satisfied in the given order.
*
* <p>Implemented interfaces are satisfied in order of their mention above.
*
* <p>Application contexts will automatically register this with their
* underlying bean factory. Applications do not use this directly.
@@ -45,6 +46,7 @@ import org.springframework.util.StringValueResolver;
* @author Juergen Hoeller
* @author Costin Leau
* @since 10.10.2003
* @see org.springframework.context.EmbeddedValueResolverAware
* @see org.springframework.context.ResourceLoaderAware
* @see org.springframework.context.MessageSourceAware
* @see org.springframework.context.ApplicationEventPublisherAware
@@ -68,7 +70,8 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
(bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
@@ -18,6 +18,7 @@ package org.springframework.context.support;
import java.io.IOException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
@@ -99,7 +100,6 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
this.beanFactory.setSerializationId(getId());
this.beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
this.beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
}
@@ -153,7 +153,6 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
@Override
public void setId(String id) {
super.setId(id);
this.beanFactory.setSerializationId(id);
}
/**
@@ -243,9 +242,16 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
this.refreshed = true;
}
@Override
protected void cancelRefresh(BeansException ex) {
this.beanFactory.setSerializationId(null);
super.cancelRefresh(ex);
}
/**
* Not much to do: We hold a single internal BeanFactory that will never
* get released.
@@ -17,6 +17,7 @@
package org.springframework.context.support;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
@@ -30,6 +31,7 @@ import org.springframework.core.io.Resource;
* deliberately override certain bean definitions via an extra configuration file.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0
* @see #load
* @see XmlBeanDefinitionReader
@@ -67,6 +69,17 @@ public class GenericXmlApplicationContext extends GenericApplicationContext {
refresh();
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resource locations and automatically refreshing the context.
* @param relativeClass class whose package will be used as a prefix when
* loading each specified resource name
* @param resourceNames relatively-qualified names of resources to load
*/
public GenericXmlApplicationContext(Class<?> relativeClass, String... resourceNames) {
load(relativeClass, resourceNames);
refresh();
}
/**
* Set whether to use XML validation. Default is <code>true</code>.
@@ -92,4 +105,18 @@ public class GenericXmlApplicationContext extends GenericApplicationContext {
this.reader.loadBeanDefinitions(resourceLocations);
}
/**
* Load bean definitions from the given XML resources.
* @param relativeClass class whose package will be used as a prefix when
* loading each specified resource name
* @param resourceNames relatively-qualified names of resources to load
*/
public void load(Class<?> relativeClass, String... resourceNames) {
Resource[] resources = new Resource[resourceNames.length];
for (int i = 0; i < resourceNames.length; i++) {
resources[i] = new ClassPathResource(resourceNames[i], relativeClass);
}
this.load(resources);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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,13 +40,14 @@ import org.springframework.instrument.classloading.weblogic.WebLogicLoadTimeWeav
* "<code>loadTimeWeaver</code>"; the most convenient way to achieve this is
* Spring's <code>&lt;context:load-time-weaver&gt;</code> XML tag.
*
* <p>This class implements a runtime environment check for obtaining the
* appropriate weaver implementation: As of Spring 2.5, it detects Sun's
* GlassFish, Oracle's OC4J, BEA's WebLogic 10,
* <p>This class implements a runtime environment check for obtaining
* the appropriate weaver implementation: As of Spring 3.0, it detects
* Oracle WebLogic 10, Oracle OC4J 10, GlassFish 3, JBoss AS 5 and 6,
* {@link InstrumentationSavingAgent Spring's VM agent} and any
* {@link ClassLoader} supported by Spring's {@link ReflectiveLoadTimeWeaver}
* (for example the
* {@link org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader}).
* {@link org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader}
* for Tomcat 5, 6 and 7).
*
* @author Juergen Hoeller
* @author Ramnivas Laddad
@@ -20,27 +20,40 @@ import java.util.Locale;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.core.NamedInheritableThreadLocal;
import org.springframework.core.NamedThreadLocal;
/**
* A holder for a thread-local user {@link JodaTimeContext}.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
public final class JodaTimeContextHolder {
private static final ThreadLocal<JodaTimeContext> jodaTimeContextHolder =
new NamedInheritableThreadLocal<JodaTimeContext>("JodaTime Context");
new NamedThreadLocal<JodaTimeContext>("JodaTime Context");
/**
* Associate the given JodaTimeContext with the current thread.
* @param context the current JodaTimeContext, or <code>null</code> to clear
* the thread-bound context
* Reset the JodaTimeContext for the current thread.
*/
public static void setJodaTimeContext(JodaTimeContext context) {
jodaTimeContextHolder.set(context);
public static void resetJodaTimeContext() {
jodaTimeContextHolder.remove();
}
/**
* Associate the given JodaTimeContext with the current thread.
* @param jodaTimeContext the current JodaTimeContext,
* or <code>null</code> to reset the thread-bound context
*/
public static void setJodaTimeContext(JodaTimeContext jodaTimeContext) {
if (jodaTimeContext == null) {
resetJodaTimeContext();
}
else {
jodaTimeContextHolder.set(jodaTimeContext);
}
}
/**

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