Removing Joda from Spring Boot
The problem
We recently migrated a medium-sized Java project to Spring Boot 2 from version 1. One of the challenges was migrating to the JDK date-time library from Joda. It turns out that Spring Boot 2 has excellent native support for JDK date-times, as does Jackson (JSON) and Hibernate (database), the default technologies offered by Spring Boot 2 for these features.
The migration itself went smoothly, which is unsurprising given the fantastic work of Stephen Colebourne in designing JDK date-time support based on his authorship of Joda.
So we looked at disabling Joda completely in our Gradle build. The most concise approach we found was:
configurations {
    compile.exclude group: 'joda-time'
}
        This removed Joda completely from configurations (classpaths) related to Java. However, this had unintended side effects:
- During tests, we needed Joda in the runtime classpath for a 3rd-party library, OpenSAML
- During boot run (running the app), we needed Joda in the classpath for another 3rd-party library, SpringFox
We easily found a workaround for SpringFox, but not for OpenSAML.
(If you're curious, yes, we do intent to migrate from OpenSAML 2
            (desupported in 2016) to OpenSAML 3; however, we would like
            spring-security-saml2-core support first.)
A solution in progress
The exclusion in the compile configuration does
            exactly what we need: Joda disappears! But what to do
            about SpringFox and OpenSAML?
For the Spring Boot runtime classpath, there is another concise solution, though finding it was rather troublesome, and it is not well-documented by Pivotal or in Stack Overflow.
First, we setup another classpath of our own making named bootRuntime:
configurations {
    // Other parts of "configurations", including the Joda exclusion from above
    bootRuntime // Synthetic configuration for deps needed *only* to launch app
}
        Then we added Joda to that synthetic classpath relying on Spring Boot plugin's definition for the version of Joda to use:
dependencies {
    // Other parts of "dependencies"
    bootRuntime 'joda-time:joda-time'
}
        
        Lastly, we taught Spring Boot to include this synthetic classpath when launching our app (this was the trickiest part):
bootJar {
    bootInf {
        from configurations.bootRuntime
        into 'lib'
    }
}
bootRun {
    classpath += configurations.bootRuntime
}
        This adds Joda to the runtime classpath for both the single "fat
            jar" built by Spring (bootJar), and when launching
            the app on the command line with gradle (bootRun).
Unless you are a heavy Gradle user, from ... into ...
            syntax may be unfamiliar: this copies the jars in the synthetic
            configuration into the fat jar at the location Boot expects to find
            them. The "'lib'" is literally a directory location within the
            jar. Useful magic, but a bit obtuse. The outcome:
$ jar tf build/libs/the-project.jar | grep joda-time BOOT-INF/lib/joda-time-2.9.9.jar
As a matter of fact, Joda is the very last file in the boot jar,
            a suggestion that it was added by our bootInf section
            after the Boot plugin built the jar.
(Our workaround is intentionally small. If we're unable to make
            it work, we'll switch to brute-force library exclusions in our
            dependencies lists. The goal is to prevent accidental import
            from Joda, for example, of LocalDate.)
Remaining work
For running the boot app, this solution is great: it is small, readable, easy to maintain, and it works. However, for tests which exercise our user authentication with OpenSAML, it fails. Joda is not in the test classpath, and we cannot use or mock OpenSAML methods which use Joda types.
Barring another magical solution like bootRuntime,
            we'll fall back on manually excluding Joda from each dependency,
            and adding it back in to the test classpath. A pity given how
            pithy the solution is with exclusion from the
            compile configuration.
 
