I created a simple Spring WebMvc/Data Jdbc to experience the newest Spring 6.
- Java 17
- Spring 6.0.0-M2
- Spring Data Jdbc 2022.0.0
There is a record class for DTOs. This record is NOT annotated with any Spring annotations.
public record CreatePostCommand(String title, String content) {
}
There is a RouterFunction to handle the request.
@Component
@RequiredArgsConstructor
public class PostHandler {
private final PostRepository posts;
public ServerResponse all(ServerRequest req) {
return ok().body(this.posts.findAll());
}
@SneakyThrows
public ServerResponse create(ServerRequest req) {
var data = req.body(CreatePostCommand.class);
var saved = this.posts.save(Post.builder().title(data.title()).content(data.content()).build());
return created(URI.create("/posts/" + saved.getId())).build();
}
//...
}
I wrote a test to verify the REST APIs.
@Test
public void getGetAllPosts() throws Exception {
when(this.posts.findAll())
.thenReturn(List.of(
Post.builder().title("test").content("content of test1").build(),
Post.builder().title("test2").content("content of test2").build()
)
);
this.rest.perform(get("/posts").accept(MediaType.APPLICATION_JSON))
.andExpectAll(
status().isOk(),
jsonPath("$.size()", equalTo(2))
);
verify(this.posts, times(1)).findAll();
verifyNoMoreInteractions(this.posts);
}
When running the test, it failed.
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'createPostCommand' defined in file [D:\hantsylabs\spring6-sandbox\data-jdbc\
target\classes\com\example\demo\web\CreatePostCommand.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.No
SuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowir
e candidate. Dependency annotations: {}
The detailed test failure log can be found on Github actions, check here: https://github.com/hantsy/spring6-sandbox/runs/4989195307?check_suite_focus=true#step:7:179
I defined a Filter attribute in the @ComponentScan annotation in the web configuration.
@ComponentScan(
basePackageClasses = WebConfig.class,
useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(type = FilterType.REGEX, pattern ="^(com\\.example\\.demo\\.web\\.)(.+)$")
}
)
Update: When changing to the following to exclude the record classes, it works.
@ComponentScan(
basePackageClasses = WebConfig.class,
useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(type = FilterType.REGEX, pattern ="^(com\\.example\\.demo\\.web\\.)(.*Handler)$")
}
)
I am confused about the filters with regex pattern:
- It should include all Spring managed beans or any classes matched this pattern? In my mind, I think it should only handle the Spring managed beans.
- In another example, there is an
excludefilter, the result should contains the record classes and some other POJOs, but it does not treat them as Spring beans.