Reputation: 1269
I am developing a spring boot custom starter which pom contains some dependencies (other starters, libraries) and this starter does some config about jwt filtering to allow the filter at security level. The issue is when I add my custom starter as a pom dependency in another project (starter-consumer), it seems it detects the class I want to import but IntelliJ does nothing.
Maybe I didn't packaged the starter correctly, or at least the classes that I coded inside. The other dependencies that the starter contains in the pom are successfully added as a dependencies of the starter-consumer. For example, I use some jwt utils which dependency is in the parent starter. So that thing works ok.
import io.jsonwebtoken.impl.DefaultClaims;
The problem is when I try to import a custom class which I coded in the starter. This is my package structure:
I want to use the JwtConfig class in my starter-consumer. It appears but I can't import. It does nothing.
And then If I manually check package availability I see this:
Pepito is missing :( and theinit is the package name of the starter-consumer. The jar is installed in the local m2 so I get the dependency like this:
<dependency>
<groupId>com.pepito</groupId>
<artifactId>starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
Any insights on this?
Edit 1:
I removed the boot maven plugin as a you said, it seems now it is not packaged as boot app and my starter-consumer can import the clases I coded . One additional thing, what happens with beans? Does the autoconfigure starts the bean by itself or the starter-consumer needs to declare it?
Edit 2:
So as part of the solution of this post, I am trying to inject a bean from the starter into the starter-consumer.
Apart from another beans, here we have the jwtTokenAuthenticationFilter which I want to inject into my starter-consumer security config.
@Configuration
@ConditionalOnProperty(name = "security.jwt-enabled", havingValue = "true")
public class JwtAutoConfiguration extends AbstractHttpConfigurer<JwtAutoConfiguration, HttpSecurity> {
@Bean
public JwtConfig jwtConfig() {
return new JwtConfig();
}
@Bean
public FilterRegistrationBean registration(@Qualifier("jwtFilter") JwtTokenAuthenticationFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
@Bean
public JwtTokenAuthenticationFilter jwtFilter() {
return new JwtTokenAuthenticationFilter(jwtConfig());
}
@Override
public void init(HttpSecurity http) throws Exception {
// initialization code
}
}
This is my spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pepito.starter.configuration.security.jwt.JwtAutoConfiguration
And in the starter-consumer I have the following
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtTokenAuthenticationFilter jwtFilter;
And here is where I see the error in intellij that can't autowire that bean because it does not exist. I suppose is because of something about scan but in my starter-consumer I have @SpringBootApplication which is suppose it contains componentscan annotation.
Upvotes: 3
Views: 2330
Reputation: 42461
I believe A couple of issues that I see here and some clarifications will help you to find an answer:
Module with starter is a regular jar. The only thing that differs is that it has META-INF/spring.factories
which I see exist.
Having said that - I see in the Pepito starter module class SpringBootMicroserviceStarterApplication
. This is wrong. If the starter is a spring boot application, then the chances are that you're using spring boot maven plugin to prepare it as an application.
But the jar created by this plugin is not really a Jar, more specifically it stores other jars in BOOT-INF lib and in general can't be considered a Jar build-tool-wise and IDE-wise.
To put it simple you cannot declare a dependency on something that gets packaged as a spring boot application!
Update 1 To address your OP's question in comments:
The starter is not a spring boot application. It should not have a method annotated with @SpringBootApplication
, it should not be packaged as spring boot application and so forth.
The best way to view the starter is as an self-contained "feature" or "facility" (trying to find the most appropriate word in English) that can be used by Spring boot applications by importing the starter module.
In terms of testing, @SpringBootTest
should not be used in starter's module because it mimics the startup of spring boot application which obviously does not exist here.
Its possible to test it with Unit Test or with Spring Testing Framework:
@RunWith(SpringRunner.class)
@ContextConfiguration(<here comes the class of AutoConfiguration in starter)
One last thing to clarify here:
In spring Factories you can specify the autoconfiguration that in turn declares a series of beans required by the starter.
These beans are resolved by spring boot application just like other beans, the difference is that the Configuration is identified out of spring.factories
file and not by package structure or explicit configuration.
So to answer your question:
Would you know if I can declare a bean in the starter and then autowire it in the consumer?
Yes, as long as the starter gets loaded by spring boot application, you can autowire (or inject in any other way) beans from starter into the beans of the spring boot application itself.
Upvotes: 4