Gradle-generated poms thoroughly tested against 3.1.1 versions, with an
eye toward making as many spring-* dependencies optional as possible.
All spring-* modules now declare a Gradle dependency on any other
spring-* module where there is a direct compile-time usage of the
sources in that module. Previously, dependency declarations were
minimal, letting transitive resolution do most of the work. However,
this creates less than ideal poms and is generally not very
informative.
So for example, spring-jdbc uses spring-core, spring-beans and
spring-tx classes directly. Therefore it has the following declarations:
compile project(":spring-core")
compile project(":spring-beans")
compile project(":spring-tx")
spring-core depends on spring-asm, but spring-jdbc does not use
spring-asm classes directly. Therefore spring-jdbc does not declare a
dependency on spring-asm. Transitive resolution is fine in such a case.
As for optional dependencies, it is a matter of degrees what
constitutes optional. A rule of thumb is whether there are legitimate
and likely use cases in which the module can be used without needing
the dependency. spring-jdbc has only one compile-time dependency on
spring-context classes, and that's in JndiDataSourceLookup. It is
certainly reasonable to imagine using spring-jdbc without JNDI,
therefore the spring-context dependency is declared optional as
follows:
compile(project(":spring-context"), optional) // for JndiDataSourceLookup
In Spring 3.1 the spring-test Maven artifact did not have a required
dependency on spring-core, but there is practically no part of
spring-test that can be used without spring-core. Most test utilities
that are intended to be stand-alone utilities in fact use utility
classes from spring-core (e.g., ReflectionTestUtils). Even some of the
web mocks/stubs use spring-core (e.g., DelegatingServletInputStream).
In addition, the current Gradle build configuration for the spring-test
module is very simplistic -- in that it does not explicitly list any
optional dependencies such as the Servlet and Portlet APIs -- and it
defines a 'compile' dependency on spring-webmvc-portlet.
The resulting Maven dependencies in the generated POM are therefore not
what a typical consumer of the spring-test artifact would reasonably
expect.
To address these issues, the Gradle build configuration for the
spring-test module now explicitly defines the following 'compile'
dependencies:
- spring-core
- spring-webmvc, optional
- spring-webmvc-portlet, optional
- junit, optional
- testng, optional
- servlet-api, optional
- jsp-api, optional
- portlet-api, optional
- activation, provided
The only required dependency is now spring-core; all other dependencies
are 'optional'.
Issue: SPR-8861
Before this change JibxMarshallerTests would fail on Windows with an
error message explaining that JiBX compiler generated classes are not
found on the classpath for binding with name 'binding'. Tests would
execute well on Linux and OS X.
Actual root cause of this bug is found to be in JiBX 1.1.5 release that
is used to build Spring. The binding name can be explicitly specified in
JiBX binding file. If omitted, when generating classes the JiBX compiler
as fall-back mechanism tries to derive the binding name from the binding
file name. That logic had a bug which gets manifested when configured
binding file path has mixed Windows and *nix style file separators, as
in case of JibxMarshallerTests being executed on a Windows platform.
This commit resolves this issue by upgrading Spring's build from JiBX
1.1.5 to 1.2.3, as the bug mentioned was fixed in JiBX 1.2. See JIBX-441
for more details.
Issue: SPR-8360
The Spring TestContext Framework (TCF) currently builds against TestNG
5.10. Thus in order to ensure that the TCF builds against the latest
release of TestNG without issues and in order to investigate the
possibility of integrating with newer TestNG features, we are upgrading to
version 6.5.2.
Note, however, that the Gradle build currently does not execute any TestNG
tests; this will be addressed in SPR-9398.
Issue: SPR-8221
Spring currently builds against JUnit 4.9; however, in order to ensure
that the Spring TestContext Framework builds and runs against JUnit 4.10
without issues and in order to investigate the possibility of integrating
with newer JUnit features, we are upgrading to JUnit 4.10.
Issue: SPR-9277
Jackson 2 uses completely new package names and new maven artifact ids.
This change adds Jackson 2 as an optional dependency and also provides
MappingJackson2HttpMessageConverter and MappingJackson2JsonView for use
with the new version.
The MVC namespace and the MVC Java config detect and use
MappingJackson2HttpMessageConverter if Jackson 2 is present.
Otherwise if Jackson 1.x is present,
then MappingJacksonHttpMessageConverter is used.
Issue: SPR-9302
Previously depending on 1.5.10 in certain locations, which caused
NoClassDefFoundErrors in EhCacheCacheTests and other tests due to
mismatches between slf4j -api and -log4j12 versions.
With the exception of one transitive dependency via Hibernate 3.3.1.GA,
all slf4j dependencies are now pegged at 1.6.1 (and all tests pass).
Before this change, IDE settings generated via import-into-eclipse.sh
created a classpath dependency on slf4j-api version 1.6.1 and
slf4j-log4j12 version 1.5.10. As a result running tests inside the IDE
resulted in a NoSuchMethodException.
build.gradle sets the variable slf4jLog4jVersion to '1.5.10'. However,
the hibernate-validator dependency in spring-context pulls in
slf4j-api version 1.6.1. The change ensures the version specified in
the build script variable is used consistently. Whether it should be
1.5.10 or 1.6.1 is a separate concern.
- Spring remains compatible against AJ version 1.6.8, but is now
compiling and testing against 1.6.12
- Encountered what appears to be an AJ bug introduced in 1.6.10: an
assertion in org.aspectj.weaver.UnresolvedType causes a false
negative failure when encountering org.springframework.io.Resource
arrays, e.g. "[org.springframework.io.Resource@xxx". This problem
has been reported to the AJ team and in the meantime, the recommended
workaround is to disable assertions either completely, or at least
selectively with
-disableassertions:org.aspectj.weaver.UnresolvedType
Issue: SPR-7989, SPR-9272
- Fix deprecation warnings about dynamic properties; favor use of
"extra properties extensions" per [1]
- Certain such deprecations are still issued due to violations within
the docbook-reference plugin. These will be fixed in an upcoming
revision of the plugin, at which point spring-framework will upgrade
to depend on it and these warnings will be eliminated
[1] http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
Issue: SPR-9327
- Rename customized .wrapper to default gradle/wrapper directory for
out of the box compatibility with STS Gradle tooling
- Add .settings/gradle directory to capture defaults when using STS
Gradle tooling to import projects
The build script should work against http anyway; use of https here was
an oversight. Changing it now is in response to the following build
failure experienced by a user on his initial attempt to build from
source (with --info output):
09:02:09.437 [ERROR] [org.gradle.BuildExceptionReporter] Caused
by: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
...
Cause: Could not GET
https://repo.springsource.org/plugins-snapshot/org/springframework/
build/gradle/docbook-reference-plugin/0.1.2-SNAPSHOT/maven-metadata.xml
The actual cause is unknown at this time, but worth noting that upon
switching the url to http, the following log message was issued:
Forcing close on abandoned resource: Http GET Resource:
http://repo.springsource.org/plugins-snapshot/org/springframework/
build/gradle/docbook-reference-plugin/0.1.2-SNAPSHOT/maven-metadata.xml
Previously, the build script was configured to add ajbuilder to the set
of Eclipse/STS build commands, meaning that both javabuilder and
ajbuilder would be present for spring-aspects. This causes unpredictable
behavior, as these two builders compete with each other. As ajbuilder is
a functional superset of javabuilder, this commit ensures that only the
former is present for spring-aspects' .project file.
Also removed warning language in import-into-eclipse.sh about
spring-aspects failing after adding Git support, as this intermittent
problem was almost certainly an artifact of the situation described
above.
- Fix compileTestJava issue in which test classes were not being
compiled or run
- Use built-in eclipse.project DSL instead of withXml closure
to add AspectJ nature and builder
- Rename {aspectJ=>aspects}.gradle and format source
e.g.:
Implementation-Title: spring-core
Implementation-Version: 3.2.0.BUILD-SNAPSHOT
Setting these values is good as a general practice, but required in
order to support the functionality in spring-core's SpringVersion class.
Understanding Gradle pom generation
-------------------------------------------
All spring-* subprojects have had Gradle's 'maven' plugin applied to
them. This means that one can run `gradle install`, and POMs will be
generated according to the metadata in the build.gradle file.
The 'customizePom' routine added by this commit hooks into this
generation process in order to add elements to the pom required for
entry into Maven Central via oss.sonatype.org[1].
This pom generation happens on-the-fly during `gradle install` and
the generated poms exist only in your local .m2 cache. Therefore,
you will not see the poms on the source tree after this command.
Handling optional and provided dependencies
-------------------------------------------
Note particularly the handling of 'optional' and 'provided'
dependencies. Gradle does not have a first class notion for these
concepts, nor are they significant to the actual Gradle build process,
but they are important when publishing POMs for consumption via Maven
Central and other Maven-compatible repositories.
<optional>true</optional> indicates that a dependency need not be
downloaded when resolving artifacts. e.g. spring-context has an
compile-time dependency on cglib, but when a Spring user resolves
spring-context from Maven Central, cglib should *not* automatically
be downloaded at the same time. This is because the core functionality
within spring-context can operate just fine without cglib on the
classpath; it is only if the user chooses explicitly to use certain
functionality, e.g. @Configuration classes, which do require cglib,
that the user must declare an explicit dependency in their own build
script on cglib.
Marking these kinds of dependencies as 'optional' provides a kind of
built in 'documentation' about which version of cglib the user should
declare if in fact he wishes to.
Spring has a great many compile-time dependencies, but in fact very
few mandatory runtime dependencies. Therefore, *most* of Spring's
dependencies are optional.
<scope>provided</scope> is similar to 'optional', in that dependencies
so marked should not be automatically downloaded during dependency
resolution, but indicates rather that they are expected to have been
provided by the user application runtime environment. For example, the
Servlet API is in fact a required runtime dependency for spring-webmvc,
but it is expected that it will be available via the user's servlet
container classpath. Again, it serves here as a kind of 'documentation'
that spring-webmvc does in fact expect the servlet api to be available,
and furthermore which (minimum) version.
This commit adds two closures named 'optional' and 'provided' as well as
two arrays (optionalDeps, providedDeps) for tracking which dependencies
are optional or provided. An optional dependency is declared as follows:
compile("group:artifact:version", optional)
Here, the optional closure accepts the dependency argument implicitly,
and appends it to the 'optionalDeps' array. Then, during pom generation
(again, the customizePom routine), these arrays are interrogated, and
pom <dependency> elements are updated with <optional>true</optional> or
<scope>provided</scope> as appropriate. Thanks to the Spock framework
for inspiration on this approach[2].
[1] http://bit.ly/wauOqP (Sonatype's central sync requirements)
[2] https://github.com/spockframework/spock/blob/groovy-1.7/gradle/publishMaven.gradle#L63
Only a select few EBR dependencies now remain, because these
dependencies cannot be found elsewhere e.g. atinject-tck, or in the case
of Hibernate 3.3.1.GA, to avoid Gradle classpath confusion with
Hibernate 4.0.x (because they have different artifactIds).
Future efforts will be made to fully eliminate these dependencies in
order to ensure we're decoupled completely from EBR.
Important note: these remaining EBR dependencies do not constitute a
problem when publishing artifacts into Maven Central via
oss.sonatype.org, because they are each 'optional' dependencies. It
appears that OSO's restriction around transitive dependencies being
'self-contained' within Maven Central only applies to mandatory
dependencies (which is a good thing for cases just such as this).
Add explicit /ebr-maven-external entry to repositories, as EBR
dependencies are not available via /libs-release.
- Apply custom-built Gradle 'bundlor' plugin
This plugin wraps the existing bundlor ant task. Sources available
at https://github.com/SpringSource/gradle-plugins.
- Use existing template.mf files
The bundlor plugin allows for 'inlining' bundlor templates directly
within build.gradle using the 'importTemplate' property, but opting
for now to keep the template.mf files separate.
- Exclude spring-aspects from bundlor processing
It appears that the bundlor plugin somehow interferes with iajc
compilation of aspects, resulting in compiler errors. Bundlor
has been disabled for this project for the time being.
- Fail the build on any bundlor warning
The gradle bundlor plugin defaults to failing the build if there are
any warnings when processing template.mf files. This helps to ensure
that template.mf files don't drift too far from actual dependency
declarations. This behavior can be modified by setting
bundlor {
failOnWarnings = false
}
in the build script.
- Generate castor test classes with genCastor task
- Generate xmlbeans test classes with genXmlbeans task
- Generate JAXB2 test classes with genJaxb task
- Generate JiBX bindings by extending existing compileTestJava task
Test classes are written into their own dedicated output folders and
tied into the spring-oxm classpath using the files(...).builtBy(...)
directive.
Incremental build works as expected across all of these customizations.
`gradle eclipse` and `gradle idea` generate correct .project / .iml
metadata respectively, i.e., these special cases do not cause a problem
in the IDE (as they used to prior to the move to Gradle).
Each spring-* subproject now has sourcesJar and javadocJar tasks
- Ignore subproject overview.html files for now (not all have one)
- Ensure @author attribution occurs
- Javadoc 'header' is project description
spring-asm is a special case
- source jar is created, but empty (to comply with entry rules for
Maven Central)
- add package-info.java explaining the nature of spring-asm
this is nice, because it shows up in the public API docs now.
- add SpringAsmInfo in the org.springframework.asm package as a
placeholder allowing the generation of javadocs (see link to bug)
- add explicit 'repackageAsm' Gradle task allowing for easy testing
and merging of jar containing bundlor manifest as well as jar
containing repackaged ASM classes.
- Add 'api' gradle task to generate project-wide API Javadoc
results in <root>/build/api
- Add docsZip task including api and reference documentation
suitable for publication to
http://static.springframework.org/docs/spring-framework
- Add schemaZip task including all spring-* XSD files
suitable for publication to http://static.springframework.org/schema
- Add distZip task to include all libs, docs and schema
- filter src/dist/*.txt for ${copyright} and ${version}
- copy legal (notice, license) dynamically into individual jar files
- copy legal and readme files into root of distribution zip
- Refactor location of 'wrapper' task
Each of the zip tasks (docsZip, schemaZip, distZip) have been added to
the 'archives' configuration, meaning that (a) they will be built
automatically with `gradle build` and (b) will be published
automatically to artifactory when using the Artifactory Gradle plugin
and/or Artifactory Bamboo integration.
Prior to this change, license.txt and notice.txt files were duplicated
across every subproject in their respective src/main/resources/META-INF
directories.
This commit centralizes these files under the root project at src/dist,
along with the changelog and readme files. The definition of the 'jar'
task has been been extended to include the license and notice files in
module jars as they are created.
The directory is named src/dist because these files are all related to
distribution - the readme is different than the one you see at the root
of the source tree - the intended audience is for users who download
the spring-framework distribution zip. A task to create that
distribution zip will be added in subsequent commits.
The docbook-gradle-plugin has been custom-developed specifically to
handle Spring projects. It is highly opinionated, and not terribly
configurable in its current form. Sources and documentation are
available via the 'gradle-plugins' github repository at
https://github.com/cbeams/gradle-plugins
Note that this repository may soon move locations to the SpringSource
GitHub organization, in which case the url will be
https://github.com/SpringSource/gradle-plugins
In any case, the build plans for these plugins can be found at
https://build.springsource.org/browse/GRADLEPLUGINS
This commit eliminates the 'integration-tests' subproject in favor of
managing these sources under the root project's own 'src' directory.
This helps to avoid special-case handling for integration-tests in the
Gradle build, e.g. avoiding publication of jars to Artifactory /
Maven Central.
It is also semantically more correct. This is not a Spring Framework
subproject so much as it is a collection of integration tests that
span functionality across many subprojects. In this way, it makes
sense to place them directly under the root project.
Issue: SPR-8116
- Use recent Gradle 1.0-milestone-8 snapshot
- Add initial cut of build.gradle able to compile/test all modules
- Update .gitignore
- Generate Gradle wrapper scripts
- Remove all Eclipse metadata files
- Temporarily @Ignore tests that do not pass under Gradle