I'm new to junit and was writing some test cases to test my springboot controller. Inside my controller there is a helper class using which I'm trying to call a validateToken method and I'm expecting a custom exception from this method. But for some reason, it is just skipping that line and returning me 200 Ok response as in case of a successful execution. I'm expecting a 400 bad request but getting a 200 Ok response.
The validateToken is a void method.
Test class
#SpringBootTest
#RunWith(MockitoJUnitRunner.class)
#AutoConfigureMockMvc
class GetUserAddressControllerTest {
#Mock
private CustomerAddressService customerAddressService;
#Mock
private TokenValidator tokenValidator;
#InjectMocks
private GetUserAddressController getUserAddressController;
#Autowired
private MockMvc mockMvc;
#BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(getUserAddressController).build();
}
#Test
void getAllAddressesFailureTest() throws Exception {
doThrow(new AddressBookException(RestResultCode.BAD_REQUEST, ErrorType.UNAUTHORIZED_ERROR.getStatus(), "Access is denied"))
.when(tokenValidator)
.validateUser(header, userId);
MvcResult mvcResult = mockMvc.perform(get(getAddressUrl)
.param("userId", userId)
.header("Authorization", header))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().is4xxClientError())
.andReturn();
verify(customerAddressService).getAllAddresses(any());
}
Controller class
#ApiOperation(value = "This API will fetch all address for a user")
#GetMapping(value = "/addresses", produces = MediaType.APPLICATION_JSON_VALUE)
CustomerAddressResponse getAllAddresses(#RequestHeader(value = "Authorization", required = true) String authToken,
#RequestParam("userId") String userId) {
tokenValidator.validateUser(authToken, userId); //----> want exception
return customerAddressService.getAllAddresses(userId);
}
TokenValidator class
public void validateUser(String authToken, String uuid) {
if (StringUtils.isEmpty(authToken)) {
throw new AddressBookException(RestResultCode.UNAUTHORIZED, ErrorType.ACCESS_DENIED_ERROR.getStatus(), "Access is denied");
}
// some logic here
}
}
Earlier I was using the when().thenThrow() syntax, but came to know for void methods we have to use a different syntax. So I changed it. Then I tried somethings with different annotations, but could not get it working.
I'm expecting the exception to be thrown, but getting 200.
stacktrace
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.1.RELEASE)
Hibernate:
select
applicatio0_.id as id1_2_,
applicatio0_.active as active2_2_,
applicatio0_.created_ts as created_3_2_,
applicatio0_.updated_by as updated_4_2_,
applicatio0_.updated_ts as updated_5_2_,
applicatio0_.config_key as config_k6_2_,
applicatio0_.config_value as config_v7_2_
from
application_configuration applicatio0_
where
(
applicatio0_.active= true
)
MockHttpServletRequest:
HTTP Method = GET
Request URI = /addressservice/v1/addresses
Parameters = {userId=[be6cefe2-04ed-4d89-bd25-7342b400272c]}
Headers = {Authorization=[Bearer 279db47b-a419-40f7-81f3-a8bf755a9dcb]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.addressbook.service.controller.GetUserAddressController
Method = com.addressbook.service.response.CustomerAddressResponse
com.addressbook.service.controller.GetUserAddressController.getAllAddresses(java.lang.String,java.lang.String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Range for response status value 200 expected:<CLIENT_ERROR> but was:<SUCCESSFUL>
Expected :CLIENT_ERROR
Actual :SUCCESSFUL
<Click to see difference>
java.lang.AssertionError: Range for response status value 200 expected:<CLIENT_ERROR> but was:<SUCCESSFUL>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:55)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:82)
at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$is4xxClientError$5(StatusResultMatchers.java:94)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:195)
at com.addressbook.service.controller.GetUserAddressControllerTest.getAllAddressesFailureTest(GetUserAddressControllerTest.java:150)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:108)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:102)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy5.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:829)
com.addressbook.service.controller.GetUserAddressControllerTest > getAllAddressesFailureTest() FAILED
java.lang.AssertionError at GetUserAddressControllerTest.java:150
Disconnected from the target VM, address: 'localhost:53204', transport: 'socket'
#Autowired If you want TokenValidator work as a service. e.g.
#Autowired
private TokenValidator tokenValidator;
if you want to mock TokenValidator as a bean, to throw exception manually, mock it using #Mockbean. e.g.
#MockBean
private TokenValidator tokenValidator;
...
doThrow(new Exception()).when(tokenValidator).validateUser(authToken, userId);
Related
Small question regarding the new Spring Boot 3 with AOT/native/GraalVM please
Lately, many talks regarding the new Spring Boot 3 are about the AOT/native/GraalVM.
I went to try migrating a project which was building without GraalVM, to this new paradigm so many are talking about.
Here is the straightforward code of the project:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
#RestController
public class ElasticController {
private final ElasticRepository elasticRepository;
#Autowired
public ElasticController(ElasticRepository elasticRepository) {
this.elasticRepository = elasticRepository;
}
#PostMapping(path = "/save", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<String> save(#RequestBody ElasticPojo elasticPojo) {
return elasticRepository.save(elasticPojo).map(__ -> "with graalVM, is is not working");
}
}
package com.example.demo;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface ElasticRepository extends ReactiveCrudRepository<ElasticPojo, String> {
}
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration;
import java.time.Duration;
#Configuration
public class ElasticConfiguration extends ReactiveElasticsearchConfiguration {
#Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder().connectedTo("localhost:9200").withConnectTimeout(Duration.ofMinutes(2L)).withSocketTimeout(Duration.ofMinutes(2L)).build();
}
}
package com.example.demo;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
#Document(indexName = "question")
public class ElasticPojo {
#Id
private String id;
private String link;
public ElasticPojo(String id, String link) {
this.id = id;
this.link = link;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
#Override
public String toString() {
return "ElasticPojo{" +
"id='" + id + '\'' +
", link='" + link + '\'' +
'}';
}
}
<?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="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The GraalVM version is: graalvm-ce-java17-22.3.0
While running mvnw.cmd -Pnative native:compile the project builds fine, running the native image always yields this error:
target\demo.exe
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.1)
2023-01-02T20:42:09.935+08:00 INFO 2860 --- [ main] com.example.demo.DemoApplication : Starting AOT-processed DemoApplication using Java 17.0.5 with PID 2860 (C:\Users\...\demo\target\demo.exe started by xxxin ...\demo)
2023-01-02T20:42:09.935+08:00 INFO 2860 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default"
2023-01-02T20:42:09.991+08:00 WARN 2860 --- [ main] .r.c.ReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elasticController': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'elasticRepository': Cannot resolve reference to bean 'reactiveElasticsearchTemplate' while setting bean property 'reactiveElasticsearchOperations'
2023-01-02T20:42:10.005+08:00 ERROR 2860 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elasticController': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'elasticRepository': Cannot resolve reference to bean 'reactiveElasticsearchTemplate' while setting bean property 'reactiveElasticsearchOperations'
at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:351) ~[na:na]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:271) ~[na:na]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:206) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961) ~[demo.exe:6.0.3]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915) ~[demo.exe:6.0.3]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[demo.exe:6.0.3]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[demo.exe:3.0.1]
at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[demo.exe:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticRepository': Cannot resolve reference to bean 'reactiveElasticsearchTemplate' while setting bean property 'reactiveElasticsearchOperations'
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:377) ~[na:na]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:135) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1663) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1412) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:334) ~[na:na]
... 21 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reactiveElasticsearchOperations': Instantiation of supplied bean failed
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1236) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:365) ~[na:na]
... 34 common frames omitted
Caused by: java.lang.ExceptionInInitializerError: null
at org.springframework.data.elasticsearch.core.AbstractReactiveElasticsearchTemplate.<init>(AbstractReactiveElasticsearchTemplate.java:93) ~[demo.exe:5.0.0]
at org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchTemplate.<init>(ReactiveElasticsearchTemplate.java:84) ~[na:na]
at org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration.reactiveElasticsearchOperations(ReactiveElasticsearchConfiguration.java:84) ~[demo.exe:5.0.0]
at com.example.demo.ElasticConfiguration$$SpringCGLIB$$0.CGLIB$reactiveElasticsearchOperations$3(<generated>) ~[demo.exe:na]
at com.example.demo.ElasticConfiguration$$SpringCGLIB$$1.invoke(<generated>) ~[demo.exe:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[demo.exe:6.0.3]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[na:na]
at com.example.demo.ElasticConfiguration$$SpringCGLIB$$0.reactiveElasticsearchOperations(<generated>) ~[demo.exe:na]
at org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration__BeanDefinitions.lambda$getReactiveElasticsearchOperationsInstanceSupplier$2(ReactiveElasticsearchConfiguration__BeanDefinitions.java:61) ~[na:na]
at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:68) ~[demo.exe:6.0.3]
at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:54) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$get$2(BeanInstanceSupplier.java:208) ~[na:na]
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:59) ~[demo.exe:6.0.3]
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:47) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.invokeBeanSupplier(BeanInstanceSupplier.java:220) ~[na:na]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:208) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[demo.exe:6.0.3]
... 43 common frames omitted
Caused by: java.lang.IllegalStateException: Resource not found
at org.springframework.data.elasticsearch.support.VersionInfo.loadVersionProperties(VersionInfo.java:108) ~[na:na]
at org.springframework.data.elasticsearch.support.VersionInfo.<clinit>(VersionInfo.java:51) ~[na:na]
... 60 common frames omitted
To avoid confusion, I am building and running fine the same code with openJDK, and any other JDK. Actually, even with GraalVM, but not using the native, it compiles and runs fine.
Only when compiling native, and running native, the issue occurs, 100% of the time.
May I ask what am I doing wrong please?
Thank you
In the non-native variant we'll get an IOException when the resource is missing and ignore that. But the native application throws an IllegalStateException.
Thanks for creating this issue. I am currently working on it. It's not only the version.properties but some other options that need to be set in the RuntimeHintsRegistrar. Should be done in the next days.
I am attempting upgrade my application to the Spring Boot 3.0.
I have some JUnit tests that are used primarily for ensure Access Control logic is working as expected. These use SpEL expressions and a #Bean to help with authorization.
Example test:
#ActiveProfiles("test")
#AutoConfigureMockMvc
#SpringBootTest
public class EmployeeControllerTest {
private static final String TEST_EMP_ID = "10000";
#Autowired
private MockMvc mvc;
#MockBean
HRCoreService hrCore;
#MockBean
private EmpFilter empFilter;
#MockBean
private AWSHelper awsHelper;
#Autowired
private ObjectMapper mapper;
#BeforeEach
public void setup()
{
// The goal here is to test roles and validation, not the empFilter logic. Force it to return true.
given(this.empFilter.checkUserId(any(Authentication.class), any(String.class)))
.willReturn(true);
given(this.empFilter.checkAccessByLoc(any(Authentication.class), any(String.class))).willReturn(true);
}
// Code omitted for brevity
#Test
#WithMockUser(username = "admin", authorities = { RoleConstants.HR.VIEW_EMP })
public void testGetEmployee() throws Exception {
var dto = new EmployeeDTO();
dto.setEmail("email");
var jString = mapper.writeValueAsString(dto);
given(this.hrCore.getEmployee(TEST_EMP_ID)).willReturn(dto);
this.mvc.perform(get("/employees/" + TEST_EMP_ID)).andExpect(status().is2xxSuccessful())
.andExpect(content().json(jString));
}
The definition of EmpFilter is
#Component
public class EmpFilter {
private EmployeeRepo empRepo;
#Autowired
public EmpFilter(EmployeeRepo empRepo) {
this.empRepo = empRepo;
}
public boolean checkUserId(Authentication authentication, String id) {
return id.equals(authentication.getName());
}
public boolean checkAccessByLoc(Authentication authentication, String id) {
var props = JwtUtils.extractProperties(authentication);
return this.empRepo.empWorksAtLoc(id, props);
}
}
Snippet from SecurityConfig for above endpoint:
#EnableWebSecurity
#Configuration
#EnableMethodSecurity
public class WebSecurityConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(WebSecurityConfig.class);
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorize -> {
try {
.requestMatchers(HttpMethod.GET, "/employees/{id}")
.access(
new WebExpressionAuthorizationManager(
SecurityUtils.buildEmpAccessString(List.of(RoleConstants.HR.VIEW_EMP),
List.of(RoleConstants.HR.VIEW_EMP, RoleConstants.ESS.MNG_SELF, RoleConstants.INS.APPLICANT))))
// Code omitted for brevity
}
When run my test, I get the following error:
java.lang.IllegalArgumentException: Failed to evaluate expression '(hasAnyAuthority('SCOPE_hr-view-employee-info') and #empFilter.checkAccessByLoc(authentication, #id) ) or (hasAnyAuthority('SCOPE_hr-view-employee-info','SCOPE_ess-manage-self','SCOPE_ins-applicant') and #empFilter.checkUserId(authentication, #id) )'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:33)
at org.springframework.security.web.access.expression.WebExpressionAuthorizationManager.check(WebExpressionAuthorizationManager.java:76)
at org.springframework.security.web.access.expression.WebExpressionAuthorizationManager.check(WebExpressionAuthorizationManager.java:39)
at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.check(RequestMatcherDelegatingAuthorizationManager.java:82)
at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.check(RequestMatcherDelegatingAuthorizationManager.java:45)
at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:95)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:128)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.context.SecurityContextHolderFilter.doFilterInternal(SecurityContextHolderFilter.java:69)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:351)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:132)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:132)
at com.midamcorp.hr.config.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:57)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:132)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:201)
at com.midamcorp.hr.controller.EmployeeControllerTest.testGetEmployee(EmployeeControllerTest.java:235)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:95)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:91)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:60)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean 'empFilter'
at org.springframework.expression.spel.ast.BeanReference.getValueInternal(BeanReference.java:51)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:55)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:91)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:188)
at org.springframework.expression.spel.ast.OpAnd.getBooleanValue(OpAnd.java:57)
at org.springframework.expression.spel.ast.OpAnd.getValueInternal(OpAnd.java:52)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:188)
at org.springframework.expression.spel.ast.OpOr.getBooleanValue(OpOr.java:56)
at org.springframework.expression.spel.ast.OpOr.getValueInternal(OpOr.java:47)
at org.springframework.expression.spel.ast.OpOr.getValueInternal(OpOr.java:37)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:309)
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30)
... 115 more
Based on the output, the expression looks like it a proper SpEL expression (sorry, I know it is a little lengthy and could do with some cleanup) and the issue seems to be related to the the #empFilter not being correctly registered.
This worked fine prior the migration. I have reviewed Spring's migration guide and the relevant documentation for Spring Security 6.0, but found nothing that would explain the issue I am having.
Any pointers would be much appreciated.
Bean empFilter is registered in the ApplicationContext of the test. In Spring Security 6, WebExpressionAuthorizationManager uses an instance of DefaultHttpSecurityExpressionHandler as its SpEL expression handler. DefaultHttpSecurityExpressionHandler has no access to the application context unless explicitly configured.
DefaultHttpSecurityExpressionHandler can be made aware of the application context as follows:
#Autowired
private ApplicationContext applicationContext;
private WebExpressionAuthorizationManager getWebExpressionAuthorizationManager(final String expression) {
final var expressionHandler = new DefaultHttpSecurityExpressionHandler();
expressionHandler.setApplicationContext(applicationContext);
final var authorizationManager = new WebExpressionAuthorizationManager(expression);
authorizationManager.setExpressionHandler(expressionHandler);
return authorizationManager;
}
The relevant part of your security configuration then becomes:
.requestMatchers(HttpMethod.GET, "/employees/{id}")
.access(getWebExpressionAuthorizationManager(
SecurityUtils.buildEmpAccessString( // as in the question
It looks like this is the only way to provide the application context. A recently opened issue has been filed suggesting to make it easier to set the expression handler used.
I am using org.testcontainers:postgresql:1.17.2 for my integration tests. I also use io.zonky.test:embedded-database-spring-test:2.1.1 for unit tests that require a repository.
A database-related part of application-it.yml
spring:
main:
banner-mode: off
datasource:
url: jdbc:postgresql://localhost:5432/db
username: postgres
password: postgres
flyway:
user: flyway
password: password
schemas: public
placeholders:
user: ${spring.datasource.username}
BaseIT.java:
#ActiveProfiles("it")
#SpringBootTest
#Testcontainers
public abstract class BaseIT {
//...
// Some services injections
//...
static MockWebServer server;
#Container
public static PostgreSQLContainer<?> POSTGRESQL_CONTAINER =
new PostgreSQLContainer<>("postgres:14.3-alpine")
.withDatabaseName("db")
.withUsername("postgres")
.withPassword("postgres")
.withInitScript("init.sql");
#DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", POSTGRESQL_CONTAINER::getJdbcUrl);
registry.add("spring.datasource.username", POSTGRESQL_CONTAINER::getUsername);
registry.add("spring.datasource.password", POSTGRESQL_CONTAINER::getPassword);
}
}
MyIT.java:
#TestPropertySource(properties = {
"app.scheduling.enable=false"
})
public class MyIT extends BaseIT {
#BeforeAll
public static void beforeEachTest() throws IOException {
server = new MockWebServer();
server.start(8999);
}
#AfterEach
public void afterEachTest() {
repository.deleteAll();
}
//...
// Some tests
//...
}
MyUnitTest.java
#Import({
Service.class
})
#DataJpaTest
#TestPropertySource(properties = {
"spring.jpa.hibernate.ddl-auto=validate"
})
#ActiveProfiles("it")
#AutoConfigureEmbeddedDatabase(type = AutoConfigureEmbeddedDatabase.DatabaseType.POSTGRES)
public class MyUnitTest {
#Autowired
private Repository repository;
#Autowired
private Service service;
//...
// Some tests
//...
}
So, when I run MyIT the following exception occurs. Attaching full stacktrace:
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.forEachDatabase(EmbeddedDatabaseTestExecutionListener.java:90)
at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.resetDatabases(EmbeddedDatabaseTestExecutionListener.java:58)
at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.beforeTestClass(EmbeddedDatabaseTestExecutionListener.java:34)
at org.springframework.test.context.TestContextManager.beforeTestClass(TestContextManager.java:213)
at org.springframework.test.context.junit.jupiter.SpringExtension.beforeAll(SpringExtension.java:113)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$10(ClassBasedTestDescriptor.java:381)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:381)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:205)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Suppressed: java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.forEachDatabase(EmbeddedDatabaseTestExecutionListener.java:90)
at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.resetDatabases(EmbeddedDatabaseTestExecutionListener.java:58)
at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.afterTestClass(EmbeddedDatabaseTestExecutionListener.java:54)
at org.springframework.test.context.TestContextManager.afterTestClass(TestContextManager.java:492)
at org.springframework.test.context.junit.jupiter.SpringExtension.afterAll(SpringExtension.java:122)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllCallbacks$16(ClassBasedTestDescriptor.java:447)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllCallbacks$17(ClassBasedTestDescriptor.java:447)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeAfterAllCallbacks(ClassBasedTestDescriptor.java:447)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.after(ClassBasedTestDescriptor.java:229)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.after(ClassBasedTestDescriptor.java:80)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:161)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:161)
... 47 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [some.group.artifact.ApplicationSpringBootMainClass]; nested exception is java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseConfiguration
at app//org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:610)
at app//org.springframework.context.annotation.ConfigurationClassParser.access$800(ConfigurationClassParser.java:111)
at app//org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.lambda$processGroupImports$1(ConfigurationClassParser.java:812)
at java.base#17.0.2/java.util.ArrayList.forEach(ArrayList.java:1511)
at app//org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:809)
at app//org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:780)
at app//org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:193)
at app//org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
at app//org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
at app//org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
at app//org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
at app//org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at app//org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
at app//org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
at app//org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:414)
at app//org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:136)
at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
... 63 more
Caused by: java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseConfiguration
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:226)
at org.springframework.context.annotation.ConfigurationClassParser.processMemberClasses(ConfigurationClassParser.java:372)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:272)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:600)
... 81 more
Caused by: java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
at org.testcontainers.shaded.com.google.common.base.Preconditions.checkState(Preconditions.java:174)
at org.testcontainers.containers.ContainerState.getMappedPort(ContainerState.java:148)
at org.testcontainers.containers.PostgreSQLContainer.getJdbcUrl(PostgreSQLContainer.java:84)
at org.springframework.test.context.support.DynamicValuesPropertySource.getProperty(DynamicValuesPropertySource.java:43)
at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:85)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver$DefaultResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:123)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.findPropertyValue(ConfigurationPropertySourcesPropertyResolver.java:97)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:74)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:60)
at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:594)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseCondition.hasDataSourceUrlProperty(DataSourceAutoConfiguration.java:153)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseCondition.getMatchOutcome(DataSourceAutoConfiguration.java:136)
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
... 87 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [some.group.artifact.ApplicationSpringBootMainClass]; nested exception is java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseConfiguration
at app//org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:610)
at app//org.springframework.context.annotation.ConfigurationClassParser.access$800(ConfigurationClassParser.java:111)
at app//org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.lambda$processGroupImports$1(ConfigurationClassParser.java:812)
at java.base#17.0.2/java.util.ArrayList.forEach(ArrayList.java:1511)
at app//org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:809)
at app//org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:780)
at app//org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:193)
at app//org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
at app//org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
at app//org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
at app//org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
at app//org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at app//org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
at app//org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
at app//org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:414)
at app//org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:136)
at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
... 61 more
Caused by: java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseConfiguration
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:226)
at org.springframework.context.annotation.ConfigurationClassParser.processMemberClasses(ConfigurationClassParser.java:372)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:272)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:600)
... 79 more
Caused by: java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
at org.testcontainers.shaded.com.google.common.base.Preconditions.checkState(Preconditions.java:174)
at org.testcontainers.containers.ContainerState.getMappedPort(ContainerState.java:148)
at org.testcontainers.containers.PostgreSQLContainer.getJdbcUrl(PostgreSQLContainer.java:84)
at org.springframework.test.context.support.DynamicValuesPropertySource.getProperty(DynamicValuesPropertySource.java:43)
at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:85)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver$DefaultResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:123)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.findPropertyValue(ConfigurationPropertySourcesPropertyResolver.java:97)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:74)
at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:60)
at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:594)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseCondition.hasDataSourceUrlProperty(DataSourceAutoConfiguration.java:153)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseCondition.getMatchOutcome(DataSourceAutoConfiguration.java:136)
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
... 85 more
In other words, this chain of calls:
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at io.zonky.test.db.EmbeddedDatabaseTestExecutionListener.forEachDatabase(EmbeddedDatabaseTestExecutionListener.java:90)
... leads to these calls:
at org.testcontainers.shaded.com.google.common.base.Preconditions.checkState(Preconditions.java:174)
at org.testcontainers.containers.ContainerState.getMappedPort(ContainerState.java:148)
at org.testcontainers.containers.PostgreSQLContainer.getJdbcUrl(PostgreSQLContainer.java:84)
at org.springframework.test.context.support.DynamicValuesPropertySource.getProperty(DynamicValuesPropertySource.java:43)
at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:85)
but the container is not UP at this moment (as specified in the exception's message).
Removing io.zonky.test:embedded-database-spring-test:2.1.1 from dependecides helps to resolve this since EmbeddedDatabaseTestExecutionListener is no longer present in the classpath.
How can "disable" all stuff related with io.zonky.test:embedded-database-spring-test:2.1.1 during my integration tests? Or at least its EmbeddedDatabaseTestExecutionListener that I don't need in my IT.
Thanks!
The Test Methods
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Optional;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
#ExtendWith(SpringExtension.class)
#WebMvcTest(value = RoleController.class)
class RoleControllerTest {
#MockBean
RoleRepoService roleRepoService;
#Autowired
private MockMvc mvc;
private ObjectMapper mapper = new ObjectMapper();
//Error I keep getting
//java.lang.AssertionError: Status expected:<200> but was:<401>
#Test
void addRole_thenReturnsRole_andStatus200() throws Exception{
Role manager = new Role(1,"Administrator", "Administrative Privileges");
when(roleRepoService.saveRole(manager)).thenReturn(manager);
this.mvc.perform(post("/addRole")
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("UTF-8")
.content(mapper.writeValueAsString(manager)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.roleID").value("1"))
.andExpect(jsonPath("$.roleType").value("Administrator"))
.andExpect(jsonPath("$.role_description ").value("Administrative Privileges"));
verify(roleRepoService, times(1)).saveRole(manager);
}
//Error I keep getting
//java.lang.AssertionError: Status expected:<200> but was:<401>
#Test
void getRoleByID_andReturnsRole__andStatus200() throws Exception {
Role manager = new Role(1,"Administrator", "Administrative Privileges");
when(roleRepoService.selectRoleById(1)).thenReturn(Optional.of(manager));
this.mvc.perform(get("/getRole/1")
.characterEncoding("UTF-8"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.roleID").value("1"))
.andExpect(jsonPath("$.roleType").value("Administrator"))
.andExpect(jsonPath("$.role_description ").value("Administrative Privileges"));
verify(roleRepoService, times(1)).selectRoleById(1);
}
My Role POJO
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
public class Role {
#GeneratedValue
#Id
#Column(insertable = false, name = "roleID")
private int roleID;
#NotBlank
#Column(name = "roleType")
private String roleType;
#NotBlank
#Column(name = "role_description")
private String role_description;
public Role(#NotBlank #JsonProperty String roleType, #NotBlank #JsonProperty String role_description) {
this.roleType = roleType;
this.role_description = role_description;
}
public Role(#JsonProperty int roleID, #NotBlank #JsonProperty String roleType, #NotBlank #JsonProperty String role_description) {
this.roleID = roleID;
this.roleType = roleType;
this.role_description = role_description;
}
//useful for serializing
public Role() {
}
public int getRoleID() {
return roleID;
}
public void setRoleID(int roleID) {
this.roleID = roleID;
}
public String getRoleType() {
return roleType;
}
public String getRole_description() {
return role_description;
}
}
My RoleController
import com.cellulant.absalife.models.Role;
import com.cellulant.absalife.service.role.RoleRepoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;
#RestController
#RequestMapping("api/v1/role")
public class RoleController {
public RoleRepoService roleRepoService;
#Autowired
public RoleController(RoleRepoService roleRepoService) {
this.roleRepoService = roleRepoService;
}
//adds Role to database
#PostMapping(path = "/addRole", produces = ("application/json"))
#ResponseBody
public Role addRole(#Valid #RequestBody #NotNull Role role){
return roleRepoService.saveRole(role);
}
//gets single Role based on id
#GetMapping(path = "/getRole/{id}")
#ResponseBody
public Optional<Role> getRoleByID(#Valid #NotNull #PathVariable("id") int id){
return roleRepoService.selectRoleById(id);
}
//this role should have the id in the body, otherwise it'll add a new record
#PutMapping(path = "/updateRole")
public Role updateRole (#Valid #NotNull #RequestBody Role role){
return roleRepoService.saveRole(role);
}
//deletes single Role based on ID
#DeleteMapping(path = "/deleteRole/{id}")
public void deleteRoleByID(#Valid #NotNull #PathVariable("id") int id){ roleRepoService.deleteRoleByID(id);
}
//gets all Role in database
#GetMapping(path ="/getAll" )
#ResponseBody
public List<Role> getAllRoles(){ return roleRepoService.getAll(); }
//deletes all Role in database
#DeleteMapping(path = "/deleteAll")
#ResponseBody
public void deleteAllRoles (){roleRepoService.deleteAllRoles();}
}
My WebSecurityConfigurer
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers().permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}
My pom.xml
<?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="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cellulant</groupId>
<artifactId>absalife</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>absalife</name>
<description>Absa Life USSD Implementation</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The stacktrace after a failed test run
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE)
2020-03-26 11:54:40.514 WARN 4201 --- [ main] o.s.boot.StartupInfoLogger : InetAddress.getLocalHost().getHostName() took 5004 milliseconds to respond. Please verify your network configuration (macOS machines may need to add entries to /etc/hosts).
2020-03-26 11:54:45.524 INFO 4201 --- [ main] c.c.a.controllers.RoleControllerTest : Starting RoleControllerTest on Angelas-MacBook-Pro.local with PID 4201 (started by angelamutua in /Users/angelamutua/Desktop/absalife)
2020-03-26 11:54:45.526 INFO 4201 --- [ main] c.c.a.controllers.RoleControllerTest : No active profile set, falling back to default profiles: default
2020-03-26 11:54:47.216 INFO 4201 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-03-26 11:54:47.542 INFO 4201 --- [ main] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: 3c0525c4-c927-48c6-b77f-0263118021f0
2020-03-26 11:54:47.689 INFO 4201 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#53e76c11, org.springframework.security.web.context.SecurityContextPersistenceFilter#1697f2b3, org.springframework.security.web.header.HeaderWriterFilter#221a2068, org.springframework.security.web.authentication.logout.LogoutFilter#109f8c7e, org.springframework.security.web.authentication.www.BasicAuthenticationFilter#72503b19, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#3134153d, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#659feb22, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#42cc183e, org.springframework.security.web.session.SessionManagementFilter#1192b58e, org.springframework.security.web.access.ExceptionTranslationFilter#793d163b, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#49cb1baf]
2020-03-26 11:54:47.727 INFO 4201 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
2020-03-26 11:54:47.727 INFO 4201 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
2020-03-26 11:54:47.741 INFO 4201 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 14 ms
2020-03-26 11:54:47.777 INFO 4201 --- [ main] c.c.a.controllers.RoleControllerTest : Started RoleControllerTest in 17.571 seconds (JVM running for 18.831)
MockHttpServletRequest:
HTTP Method = POST
Request URI = /addRole
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"86"]
Body = {"roleID":1,"roleType":"Administrator","role_description":"Administrative Privileges"}
Session Attrs = {SPRING_SECURITY_SAVED_REQUEST=DefaultSavedRequest[http://localhost/addRole]}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 401
Error message = Unauthorized
Headers = [WWW-Authenticate:"Basic realm="Realm"", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<200> but was:<401>
Expected :200
Actual :401
<Click to see difference>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$matcher$9(StatusResultMatchers.java:627)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:196)
at com.cellulant.absalife.controllers.RoleControllerTest.addRole_thenReturnsRole_andStatus200(RoleControllerTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
2020-03-26 11:54:47.992 INFO 4201 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
Process finished with exit code 255
I have been trying to figure this out for a day now. I have tried disabling the SecurityConfiguration class in my test class, but that led to an error with the ObjectPostProcessor bean type.
Apologies for the code dump, but I'm unsure how to proceed. Any help would be greatly appreciated!
The URL of the resource you are trying to test in method addRole_thenReturnsRole_andStatus200() seems to be wrong.
Please try to change it to api/v1/role/addRole instead of only /addRole.
You could also consider trying first with tools like Postman, or Soap UI.
I am trying to build a simple consumer using spring boot to consume data from a kafka topic. However I get the following error before startup of the spring boot application:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.2.RELEASE)
java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration.restTemplateBuilder
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:184)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:144)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:120)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:337)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:242)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at com.gs.eq.art.rec.Start.main(Start.java:26)
Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration] from ClassLoader [sun.misc.Launcher$AppClassLoader#18b4aac2]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:481)
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:358)
at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:414)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.lambda$getTypeForFactoryMethod$2(AbstractAutowireCapableBeanFactory.java:743)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:742)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:681)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:649)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1604)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:520)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:491)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:230)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:223)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:213)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:167)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:142)
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
... 17 more
Caused by: java.lang.NoClassDefFoundError: org/springframework/transaction/ReactiveTransactionManager
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463)
... 33 more
Caused by: java.lang.ClassNotFoundException: org.springframework.transaction.ReactiveTransactionManager
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 37 more
Process finished with exit code 0
My project is a sub project of an existing gradle project. The build.gradle file for my sub project is as follows:
dependencies {
compile "org.springframework.kafka:spring-kafka:${SpringKafkaVersion}"
compile "org.springframework.boot:spring-boot-starter:${SpringBootVersion}"
}
Java classes:
Start.java:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Start {
public static void main(String[] args) {
try {
System.out.println("Application Started");
SpringApplication.run(Start.class, args);
} catch (Exception e) {
e.printStackTrace();
}
}
}
KafkaConsumerConfig.java:
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import java.util.HashMap;
import java.util.UUID;
#EnableKafka
#Configuration
public class KafkaConsumerConfig {
#Bean
public ConsumerFactory<String, String> consumerFactory() {
HashMap<String, Object> props = new HashMap<>();
props.put(
ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
<KAFKA_SERVER_ADDRESS>);
props.put(
ConsumerConfig.GROUP_ID_CONFIG,
UUID.randomUUID().toString());
props.put(
ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
StringDeserializer.class);
props.put(
ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
StringDeserializer.class);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
return new DefaultKafkaConsumerFactory<>(props);
}
#Bean
public ConcurrentKafkaListenerContainerFactory<String, String>
kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
KafkaConsumer.java
#Service
public class KafkaConsumer {
#KafkaListener(topics = <TOPIC_NAME>)
public void consume(#Payload ConsumerRecord<String, String> message) {
System.out.println("Consumed message: " + message);
}
}
The KAFKA_SERVER_ADDRESS and TOPIC_NAME have been correctly provided within my code.
Any ideas as to what the issue could potentially be?
You must include 'spring transaction' dependency (org.springframework:spring-tx) in your build.gradle.
I suggest you use dependencyManagement to be sure you use the correct dependencies and compatible versions.