What is causing Spring not to be able to load the configuration class when using AnnotationConfigApplicationContext?
Asked Answered
Q

2

1

I've run across this issue recently and after searching the stackoverflow site, couldn't find a working solution. The error I'm getting is that Spring is having issue loading the configuration class. I'm using annotations and a Spring class to configure, instead of an XML file, to practice configuring Java apps with annotations instead of an XML file.

I've double checked to make sure the needed annotations were there and that the Spring config file was marked with @Configuration and all of the beans inside the config file marked with @Bean. Also, the particular beans were marked with @Component.

After creating a test class, it seems Spring is still having trouble finding the config file. I doubled checked the pom file to see if I was missing any dependencies but as far as I know, it seems the needed dependencies are there. I'm not sure what else I'm missing or why Spring is having trouble finding the config file. Any help would be greatly appreciated.

Here is my pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.spring</groupId>
  <artifactId>Spring_JavaConfig</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>Spring_JavaConfig</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <springframework.version>4.3.6.RELEASE</springframework.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springframework.version}</version>
    </dependency>
  </dependencies>
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.2</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

And here are my Java files:

Dao class (not really accessing database, just practicing configuring with Spring Annotations instead of XML file):

package com.spring;

import org.springframework.stereotype.Component;

@Component
public class Dao {
  public void create() {
    System.out.println("Created");
  }
}

Spring Config class:

package com.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
  @Bean
  public Dao dao() {
    return new Dao();
  }
}

Test class:

package com.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    Dao dao = context.getBean(Dao.class);
    dao.create();
    context.close();
  }
}

Here is the error I'm getting:

Feb 28, 2022 1:39:12 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@39c0f4a: startup date [Mon Feb 28 13:39:12 EST 2022]; root of context hierarchy
Exception in thread "main" java.lang.IllegalStateException: Cannot load configuration class: com.spring.SpringConfig
at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:403)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:249)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:281)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:125)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at com.spring.Test.main(Test.java:9)
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.context.annotation.ConfigurationClassEnhancer.newEnhancer(ConfigurationClassEnhancer.java:119)
at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:107)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:393)
... 7 more
Caused by: java.lang.IllegalStateException: Unable to load cache item
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:79)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.springframework.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:174)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:153)
at org.springframework.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)
... 10 more
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
... 17 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @2f8f5f62
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at org.springframework.cglib.core.ReflectUtils$1.run(ReflectUtils.java:54)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at org.springframework.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:44)
... 25 more
Quadriceps answered 28/2, 2022 at 18:49 Comment(1)
Welcome to SO. I reformatted your question. Please learn some markdown. Code blocks can be created either the old-fashioned way by indentation of by fencing them with triple backticks (on separate lines) plus an optional language hint for syntax highlighting. Just click "edit" and see how I did it, then cancel saving. You tried to apply both methods at the same time, which does not work. Furthermore, C/Java-like single comment "//" double slashes do not belong to the beginning of paragraphs in prose. If you tried to use healine formatting, I don't know, but the syntax for that is different. – Suffragan
S
4

Preface

This question is actually quite similar to the one I answered generically here, where among other things I also described the --add-opens workaround @victoraugustofd mentioned in his answer here.

But because the other answer does not contain an MCVE and this one does, this question is actually better to answer not just in a generic but in a more concrete way, because every reader in the future can see code and a POM in order to reproduce both the problem and the solution. This is the kind of question we want here on Stack Overflow. πŸ™‚

Problem root cause

Like I said in the other answer, the problem is that JEP 396 is limiting access to internal JDK classes since JDK 16.

Solution

So if you want to avoid the workaround of opening up packages, just upgrade to a more recent Spring version embedding a more recent CGLIB version. For 4.3.x, there is no such update, neither is there for 5.0.x. But if you e.g. can upgrade to 5.1.20, 5.2.19 or 5.3.16, your example application works on JDK 16+. There might be slightly older minor-minor releases containing suitable CGLIB versions, but why bother if you upgrade anyway? Just use the latest minor-minor for 5.1, 5.2 or 5.3.

Suffragan answered 1/3, 2022 at 1:13 Comment(3)
I was really stumped on this one but this makes a lot more sense now what the issue is and how to solve it. I'll update my Spring version and rerun the program. Thank you and also to Victor as well! – Quadriceps
FYI, I just updated the answer. I have no idea why before I wrote "ASM" instead of "CGLIB". Maybe because the same problem due to JEP 396 occurs with the embedded ASM in older Groovy versions. Here, it really is about CGLIB. Note to myself: multi-tasking is bad! – Suffragan
Thank you so much for this. Spent hours trying to debug and just came down to the version. – Lorusso
H
0

Since Java 9, Java introduced Modules and some frameworks such as Spring, rely on several Reflection behaviour and because of the modularization, some classes had their attribute not accessible through Reflection. The solution would be change the accessibility of these attributes, but it would take forever to do that.

The real solution is to add this VM option when you run your application: --add-opens java.base/java.lang=ALL-UNNAMED

Please refer to this great answer on another post with a similar problem: Answer to similar question

I changed your application to use Spring Boot, have you consider using it? For Spring applications, it is a very handy solution since it abstract many configurations. Here is a link with a detailed example: Spring Boot Example

Homily answered 28/2, 2022 at 19:30 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.