I am creating java jar library (maven) which will contain common configuration & util classes used in many services. My project is not multi-modules, so creating a new maven project. The configuration class I am not able to use in my project. Found out there are 2 approach for this from below mentioned references.
Adding entry in resoruces/META-INF/spring.factories in the library project (auto-configure). It is giving error of class not found. Also added package of library in scanPackage attribute of Spring Boot Application. Src code is there after all the text.
Error: The project which uses the library is not able to find class of ouath of spring related which is a dependency in the library class
For the full error stacktrace, please see the following collapsed snippet:
12:41:07.826 [main] ERROR org.springframework.boot.SpringApplication - Application run failed org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.satishch.microspace.nri.security.ReferenceSecurityConfig]; nested exception is java.lang.IllegalArgumentException: Unresolvable class definition for class [com.satishch.microspace.nri.security.ReferenceSecurityConfig] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:610) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:311) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:600) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.access$800(ConfigurationClassParser.java:111) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.lambda$processGroupImports$1(ConfigurationClassParser.java:812) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at java.util.ArrayList.forEach(ArrayList.java:1257) ~[?:1.8.0_191] at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:809) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:780) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:193) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) [spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405) [spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at com.satish.NriAssetMgmtServiceApplication.main(NriAssetMgmtServiceApplication.java:28) [classes/:?] Caused by: java.lang.IllegalArgumentException: Unresolvable class definition for class [com.satishch.microspace.nri.security.ReferenceSecurityConfig] at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:331) ~[spring-core-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecuritySelector.selectImports(GlobalMethodSecuritySelector.java:51) ~[spring-security-config-5.3.6.RELEASE.jar:5.3.6.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:581) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] ... 21 more Caused by: java.lang.NoClassDefFoundError: org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_191] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_191] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_191] at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) ~[?:1.8.0_191] at java.net.URLClassLoader.access$100(URLClassLoader.java:74) ~[?:1.8.0_191] at java.net.URLClassLoader$1.run(URLClassLoader.java:369) ~[?:1.8.0_191] at java.net.URLClassLoader$1.run(URLClassLoader.java:363) ~[?:1.8.0_191] at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_191] at java.net.URLClassLoader.findClass(URLClassLoader.java:362) ~[?:1.8.0_191] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_191] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[?:1.8.0_191] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_191] at java.lang.Class.forName0(Native Method) ~[?:1.8.0_191] at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_191] at org.springframework.util.ClassUtils.forName(ClassUtils.java:284) ~[spring-core-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:324) ~[spring-core-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecuritySelector.selectImports(GlobalMethodSecuritySelector.java:51) ~[spring-security-config-5.3.6.RELEASE.jar:5.3.6.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:581) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] ... 21 more Caused by: java.lang.ClassNotFoundException: org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[?:1.8.0_191] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_191] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[?:1.8.0_191] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_191] at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_191] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_191] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_191] at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) ~[?:1.8.0_191] at java.net.URLClassLoader.access$100(URLClassLoader.java:74) ~[?:1.8.0_191] at java.net.URLClassLoader$1.run(URLClassLoader.java:369) ~[?:1.8.0_191] at java.net.URLClassLoader$1.run(URLClassLoader.java:363) ~[?:1.8.0_191] at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_191] at java.net.URLClassLoader.findClass(URLClassLoader.java:362) ~[?:1.8.0_191] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_191] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[?:1.8.0_191] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_191] at java.lang.Class.forName0(Native Method) ~[?:1.8.0_191] at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_191] at org.springframework.util.ClassUtils.forName(ClassUtils.java:284) ~[spring-core-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:324) ~[spring-core-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.security.config.annotation.method.configuration.GlobalMethodSecuritySelector.selectImports(GlobalMethodSecuritySelector.java:51) ~[spring-security-config-5.3.6.RELEASE.jar:5.3.6.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:581) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] ... 21 more
For the full error stacktrace, please see the following collapsed snippet:
12:34:17.903 [main] ERROR org.springframework.boot.SpringApplication - Application run failed org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean. at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) [spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405) [spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at com.satish.AssetMgmtServiceApplication.main(AssetMgmtServiceApplication.java:31) [classes/:?] Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean. at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:205) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:177) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:158) ~[spring-boot-2.3.8.RELEASE.jar:2.3.8.RELEASE] ... 7 more
Source code:
resoruces/META-INF/spring.factories (1st Approach)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.satish.security.ReferenceSecurityConfig
Config inside the library
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableResourceServer
@EnableWebSecurity
@Configuration
@ConfigurationProperties(prefix = "security")
@Data
@EqualsAndHashCode(callSuper=false)
public class ReferenceSecurityConfig extends ResourceServerConfigurerAdapter {
private boolean bypass;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable();
if (bypass) {
http.authorizeRequests().antMatchers("/**").permitAll();
} else {
http.authorizeRequests()
.antMatchers("/swagger-ui/**").permitAll()
.antMatchers("/management").permitAll()
.antMatchers("/management/**").permitAll()
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/v2/api-docs/**").permitAll()
.antMatchers("/webjars/**").permi tAll()
.antMatchers("/v3/api-docs/**").permitAll()
.antMatchers("/swagger-ui/**").permitAll()
.antMatchers("/**").authenticated();
}
}
}
Annotation to use in the main project (2nd approach)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(ReferenceSecurityConfig.class)
public @interface EnableCustomSecurityConfig {
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.satish</groupId>
<artifactId>core-lib</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>core-lib</name>
<description>Storing common implementation</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
<relativePath />
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<log4j2.version>2.17.1</log4j2.version>
<log4j2Version>2.7</log4j2Version>
<slf4jVersion>1.7.21</slf4jVersion>
</properties>
<repositories>
<repository>
<id>confluent</id>
<url>https://packages.confluent.io/maven/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- security dependencies -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-core</artifactId>
<version>5.1.7.RELEASE</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${springSecurityVersion}</version>
</dependency>
<!-- spring-boot-starter-security -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<optional>true</optional>
</dependency>
<!-- Not sure why Lombok is not working -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- Provided Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Implementation-Vendor>Satish's Companies Inc.</Implementation-Vendor>
<Implementation-Title>TITLE</Implementation-Title>
<Implementation-Version>2.2</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<!--plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration> <fork>true</fork> <mainClass>${start-class}</mainClass> </configuration>
<executions> <execution> <goals> <goal>repackage</goal> </goals> </execution>
</executions> </plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
First, I believe I already did a lib achieving what you're trying to do. A lot is configurable from properties (CORS, authorities mapping and more) and it is published on maven-central.
Spring-boot starters have changed since 2.7.
Auto-configured components should now be:
@AutoConfiguration
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Minimal sample here with this resource
com.c4_soft.springaddons.starter.webclient.SpringBootAutoConfiguration
and that loaded file
package com.c4_soft.springaddons.starter.webclient;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Import;
@AutoConfiguration
@Import({ C4ProxySettings.class, C4WebClientBuilderFactoryService.class })
public class SpringBootAutoConfiguration {
}