Greetings lovely people!

I create this issue after following up on https://github.com/spring-projects/spring-framework/issues/26884.

To briefly summarize: spring-context uses dependencies that are part of the java.desktop module. This means that any custom runtime necessary to run applications using spring-context require the presence of java.desktop despite not using GUI based functionality.

An analysis with jdeps command reveals these classes that rely on classes from java.desktop:

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor                        ->  java.beans.PropertyDescriptor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$EjbRefElement          ->  java.beans.PropertyDescriptor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$LegacyResourceElement  ->  java.beans.PropertyDescriptor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$LookupElement          ->  java.beans.PropertyDescriptor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement        ->  java.beans.PropertyDescriptor
org.springframework.ejb.config.LocalStatelessSessionBeanDefinitionParser                        ->  java.beans.PropertyDescriptor
org.springframework.ejb.config.RemoteStatelessSessionBeanDefinitionParser                       ->  java.beans.PropertyDescriptor
org.springframework.format.support.FormatterPropertyEditorAdapter                               ->  java.beans.PropertyEditorSupport
org.springframework.jmx.access.MBeanClientInterceptor                                           ->  java.beans.PropertyDescriptor
org.springframework.jmx.export.assembler.AbstractReflectiveMBeanInfoAssembler                   ->  java.beans.PropertyDescriptor
org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler                             ->  java.beans.PropertyDescriptor
org.springframework.jmx.support.JmxUtils                                                        ->  java.beans.PropertyDescriptor
org.springframework.jndi.JndiTemplateEditor                                                     ->  java.beans.PropertyEditorSupport
org.springframework.validation.AbstractBindingResult                                            ->  java.beans.PropertyEditor
org.springframework.validation.AbstractPropertyBindingResult                                    ->  java.beans.PropertyEditor
org.springframework.validation.BindException                                                    ->  java.beans.PropertyEditor
org.springframework.validation.BindingResult                                                    ->  java.beans.PropertyEditor
org.springframework.validation.DataBinder                                                       ->  java.beans.PropertyEditor
org.springframework.validation.SimpleErrors                                                     ->  java.beans.PropertyDescriptor

Only three classes come up: java.beans.PropertyDescriptor, java.beans.PropertyEditor, and java.beans.PropertyEditorSupport. Further analysis on these three classes to see which other classes they depend in a dependency tree reveals the following:

java.beans.PropertyDescriptor
- com.sun.beans.introspect.PropertyInfo
- - com.sun.beans.finder.ClassFinder (static import for 'findClass' method)
- - - (no further dependencies)

java.beans.PropertyEditor
- (no further dependencies)

java.beans.PropertyEditorSupport
- (no further dependencies)

The number of required classes from java.desktop to ensure the functionality of all of spring-context is quite minimal. I propose we shade the required classes within spring-context itself, perhaps within a package named org.springframework.javadesktopclasses (as an example) and include the classes as so:

Image

We would modify the imports to point to the classes within org.springframework.javadesktopclasses. In the end, we will be absolved of any dependency to java.desktop, ensuring JREs without java.desktop can run the spring-context`. This will drastically cut down on the minimum size of JREs need in docker containers, improving performance and security.

Does this approach seem sound?

(P.S. I use the term "class" to refer to both classes and interfaces in this post)

(P.P.S for the sake of posterity, the dependency analysis has been performed for spring-context version 6.2.12)

Comment From: PrittSpadeLord

At the time of writing this pull request, I nearly forgot that spring-context depends on spring-aop, spring-beans, spring-core, spring-expression, and spring-jcl. Those packages would also need to be free of classes from java.desktop as well for spring-context to be shed off its dependency from java.desktop. I will post another comment with dependency analysis for those as well.

However, I must mention that within spring-beans, the dependency tree with java.awt package goes incredibly deep, and sorting through all of that would take a lot of time. It is tempting to simply throw the entirety of java.awt in there, but doing so would also bulk the spring jars too much for little benefit.

Comment From: PrittSpadeLord

After further analysis, it seems like shading the necessary classes from JDK is not a feasible solution, since far too many dependencies would need to be copied over in such case. Furthermore, internal classes such as from com.sun.*, sun.* and jdk.* are involved in the process