Our Spring Boot application allows to be extended by users who add their own jars (and dependencies) to the classpath. If an outdated library is added (e.g. GSON 2.3.1), server startup fails with a BeanCreationException.

Since we do not know which libraries users are going to add, we cannot exclude the auto-configuration in advance.

It would be nice if the BeanFactory could be configured in a way that those error are only logged and the server is able to start anyway.

Comment From: snicoll

BeanCreationException is a fatal exception that should lead the ApplicationContext to fail. Adding outdated/incompatible libraries to the classpath is likely to cause issues.

If you have a concrete example where the auto-configuration can be improved, we can look at it but ignoring such low-level exception is not a good idea.

Comment From: windmueller

It is not my intention to ignore any BeanCreationException but only those thrown in DefaultListableBeanFactory#preInstantiateSingletons when the bean definition has both the ConditionalOnClass and Configuration annotation.

Comment From: snicoll

Thanks for the feedback. BeanCreationException is a fatal exception, no matter how it is thrown unless you found a specific case where it is thrown and it shouldn't be. This is the reason why I am asking for a concrete example.

only those thrown in DefaultListableBeanFactory#preInstantiateSingletons when the bean definition has both the ConditionalOnClass and Configuration annotation.

Sorry but that is way too generic for us to consider adding an option to ignore that.

Can we please take a step back? While I find the addition of incompatible libraries on the classpath a problem on its own, I'd like to better understand what the actual exception is. Please share a small sample we can run that reproduces the problem.

Comment From: windmueller

I agree with you that using outdated libraries (that particular GSON version is from 2014!) is bad practice. However, we cannot control which libraries users add to the system but we want to make sure it works as expected. Auto-Configuration is not needed in this case because their code using the libraries is not part of the component scan.

The exception message is

Error creating bean with name 'gsonBuilder' defined in class path resource
[org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.class]:
Bean instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to instantiate
[com.google.gson.GsonBuilder]: Factory method 'gsonBuilder' threw exception;
nested exception is java.lang.NoSuchMethodError: 'com.google.gson.GsonBuilder
com.google.gson.GsonBuilder.setLenient()'`

In order to replicate the problem, please see this repository based on Spring Initializr.

It is not exactly the same environment because we deploy a WAR with SpringBootServletInitializer into an application container, but the exception should be the same.

Comment From: wilkinsona

We have a few places in our auto-configuration and in our web server support where we back off if an older version is on the classpath (via @ConditionalOnClass) or where we catch NoSuchMethodError to tolerate older versions. I think we should do one of those two things for our GSON auto-configuration.

Comment From: windmueller

This would fix the issue with the outdated GSON library, but the global issue remains.

Right now we "fixed" this by disabling auto-configuration and enabling those we require ourselves manually.

Comment From: wilkinsona

One of auto-configuration's key features is to enable functionality based on what's available on the classpath. I would recommend encouraging your users to make use of Spring Boot's dependency management to influence the version of any additional dependencies that they are adding. If you are in a situation where you need to give your users free rein to add anything to the classpath, auto-configuration may not be a good fit for your use case.

Setting that aside for now, I do not think that it would be possible to distinguish with 100% accuracy between a failure that should only be logged and one that should stop the application from starting up. I expect that an attempt to implement this would add a significant amount of complexity and would be a source of a lot of bugs as cases that are handled incorrectly are identified.

I think our best option here is to identify and fix problems on a case-by-case basis. That will allow us to consider each case individually and decide if it's better for a particular piece of auto-configuration to back off when an older version of a library is present or if we should tolerate some incompatibilities via catching NoSuchMethodError and the like. I propose that we use this issue to consider what to do for Gson. Please feel free to raise additional issues for other similar problems as you encounter them.

Comment From: wilkinsona

We've discussed this one today and concluded that a point solution isn't really viable. We'd have to decide at which version to cut off older versions of Gson and to revisit this decision every time we upgraded to a new major or minor version of Gson. That would add significantly to our maintenance burden. Furthermore, a new minor or major version of Gson may not add or remove and classes so it would have hard for us to distinguish it from earlier versions.

Instead of pursuing the problem on a case-by-case basis, we'd prefer to take a step back and consider a feature that allows a snapshot of the classpath to be taken somehow and used for conditional on class checks by the auto-configuration. Anything on the classpath that isn't in the snapshot would be ignored for the purposes of auto-configuration.