Adding spring-cloud-starter-config dependency results in At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified error - spring

I've simply added the following dependency to my Spring Boot 1.4 app :
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
In order to use Spring Cloud Config Server as an externalized configuration server.
When I boot my app I now get this error:
Caused by: java.lang.IllegalStateException: At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. Typically this done by adding a #Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke WebSecurity.addSecurityFilterChainBuilder directly
at org.springframework.util.Assert.state(Assert.java:392)
at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:276)
at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:75)
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:334)
at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:41)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:104)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$fc86a60e.CGLIB$springSecurityFilterChain$5(<generated>)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$fc86a60e$$FastClassBySpringCGLIB$$a1dd410.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
I've already got an existing Security configuration, but that extends something different:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends GlobalMethodSecurityConfiguration
Has anyone any ideas about this? I'm thinking perhaps my dependency has resulted in upgrading perhaps part of Spring Security which now needs to be configured differently perhaps ?

This was caused by the following bean not being created because adding the spring cloud dependency set management.security.default to false, thereby disabling the creation of this bean.
#Configuration
#ConditionalOnMissingBean({ManagementWebSecurityAutoConfiguration.ManagementWebSecurityConfigurerAdapter.class})
#ConditionalOnProperty(
prefix = "management.security",
name = {"enabled"},
matchIfMissing = true
)
#Order(2147483637)
protected static class ManagementWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

Related

Spring-Boot: #EnableRedisHttpSession annotation ignores profiles (when negating them)

I´m running into this weird issue with Spring Boot Profiles and #EnableRedisHttpSession:
If I use this setup, everything is correct:
#Configuration
#Profile({"prod"})
#EnableRedisHttpSession
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
Neither WebSecurity nor RedisSession are initialized when running in other profiles than prod.
On the other hand, if I use "negated" profiles, both the security and redis logic are initialized:
#Configuration
#Profile({"!dev", "!test"})
#EnableRedisHttpSession
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
I´m am doing this, since I want to run using custom profiles given from the outside.
I have tried several workarounds:
For Security, I have disabled it by using this property: security.ignored: /**
However, I am unable to disable the Redis Session. I have tried this:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
And this too: spring.data.redis.repositories.enabled=false but without success.
I am running Spring-Boot v1.5.16.RELEASE
Edit: This is the stacktrace shown when initializing Redis (which is not wanted in this profile):
Caused by: org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:204) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:348) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration$EnableRedisKeyspaceNotificationsInitializer.afterPropertiesSet(RedisHttpSessionConfiguration.java:249) ~[spring-session-1.3.3.RELEASE.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1692) ~[spring-beans-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.beans.fa
I haven't done Spring in forever, but I did find this answer which suggests that you cannot "negate" profiles: Can I negate (!) a collection of spring profiles?

#EnableTransactionManagement in Spring Boot

Is #EnableTransactionManagement required in Spring Boot?
I did some research. Some folks say you don't need it, as Spring Boot has it already enabled, others say you do have to use it explicitly. So how is it?
Probably you're also using Spring Data. Calls on Spring Data repositories are by default surrounded by a transaction, even without #EnableTransactionManagement. If Spring Data finds an existing transaction, the existing transaction will be re-used, otherwise a new transaction is created.
#Transactional annotations within your own code, however, are only evaluated when you have #EnableTransactionManagement activated (or configured transaction handling some other way).
You can easily trace transaction behavior by adding the following property to your application.properties:
logging.level.org.springframework.transaction.interceptor=TRACE
(see Showing a Spring transaction in log)
According to > https://spring.io/guides/gs/managing-transactions/
Spring Boot will detect spring-jdbc on the classpath and h2 and will create a DataSource and a JdbcTemplate for you automatically. Because such infrastructure is now available and you have no dedicated configuration, a DataSourceTransactionManager will also be created for you: this is the component that intercepts the #Transactional annotated method.
You can also use spring-boot-starter-actuator to list your beans created in your context and you will find it
bean": "transactionManager"
Little old post but the answers given previously were not straight forward when I was searching for it.
#EnableTransactionManagement is optional in Spring boot, provided that spring-data* or spring-tx are found in classpath. How it works? As below:
Spring boot adds a spring-boot-autoconfigure.jar in the classpath. Go to the META-INF's spring.factories file and you can see org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration entry there. This initializes the transaction auto configuration for you.
Note that the class has following lines: (snippet)
#Configuration
#ConditionalOnClass({PlatformTransactionManager.class})
#AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
#EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
..
}
Have a look at TransactionAutoConfiguration to see that it enables transaction support if the PlatformTransactionManager is available in classpath. EnableTransactionManagementConfiguration is also configured there.
No. #EnableTransactionManagement is on by default, see that: https://github.com/jkubrynski/spring-boot/commit/9d219ef7a004c58a88bbbef82a520a22961c9402
#EnableTransactionManagement is conditionally turned on/off based of the dependency jars we add in the classpath. If we use spring data jpa starter it is turned on.
In the class org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, there is such code(Spring Boot 1.5+):
#Configuration
#EnableTransactionManagement(proxyTargetClass = false)
#ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
#Configuration
#EnableTransactionManagement(proxyTargetClass = true)
#ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
The default is spring.aop.proxy-target-class=true, enabling CGLIB proxy by default.
If you want to use JDK proxy, set spring.aop.proxy-target-class=false instead.

Spring boot metrics with Jersey2

I have an application running spring-boot, jersey2 and spring metrics:
below is maven snippet:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Jersey used to work well until introducing actuator dependency.
Then following bean has been created to make Jersey working as filter:
#Bean
public FilterRegistrationBean jerseyFilterRegistration() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setName("jerseyFilter");
bean.setFilter(new ServletContainer(resourceConfig()));
bean.setOrder(Ordered.LOWEST_PRECEDENCE);
bean.addInitParameter("com.sun.jersey.config.property.WebPageContentRegex", managementContextRegex);
return bean;
}
Metrics are mapped to /admin path. With this configuration I cannot make metrics working. However by adding management.port (different than main app port) both Jersey resource and metrics are available.
What I'm missing here to make both metrics and Jersey resource start working on the same port?
"com.sun.jersey.config.property.WebPageContentRegex"
This is the wrong property. That's for Jersey 1.x. For 2.x, it should be
"jersey.config.servlet.filter.staticContentRegex"
See ServletProperties.FILTER_STATIC_CONTENT_REGEX
As an aside you can avoid having to define your own FilterRegistrationBean by simply setting a couple configuration properties. In your application.properties, you could use the following
spring.jersey.type=filter
spring.jersey.init.jersey.config.servlet.filter.staticContentRegex=<your-regex>
Or you can configure the regex in your ResourceConfig subclass
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
property(ServletProperties.FILTER_STATIC_CONTENT_REGEX, "<your-regex>");
}
}
As another side, just an FYI, the cause of the problem is the default /* url-mapping used for Jersey. If you can change it, doing so would solve the problem. For instance /api. You can configure that in the properties with spring.jersey.applicationPath=/api or with #ApplicationPath("/api") on the ResourceConfig subclass.
And the final aside, there is also a property
ServletProperties.FILTER_FORWARD_ON_404
"jersey.config.servlet.filter.forwardOn404"
I'm not exactly sure how the staticContenRegex property works, I never really dug into to source code. So I don't know if it just does some file IO to get the static file or it forwards the request, but if it does some file IO, then I don't think the property will work for your use case, as the endpoints are not files. In which case the forwardOn404 should work.

Spring Boot and Spring Session, disable auto configuration in SessionAutoConfigure.java

We have a use case to not use Spring session, i.e. not have #EnableRedisHttpSession annotation even though Spring Session and Spring boot are in the classpath. We used to do that by having a custom property spring.session.enabled and having a #ConditionalOnProperty on the class that had the #EnableRedisHttpSession annotation. This worked in Spring boot 1.2.7. However with Spring Boot 1.3.0, the SessionAutoConfiguration class has a #EnableRedisHttpSession annotation on it.
Is there a way to disable the class from being used?
To disable Spring Boot Auto-Configuration of Spring Session:
#SpringBootApplication(exclude = {SessionAutoConfiguration.class})
public class Application
{
...
}
Then, to enable Spring Session depending on a property (for example, you may want it disabled when in development but enabled in production):
#Configuration
#ConditionalOnProperty(value = "spring.session.enabled", havingValue = "true", matchIfMissing = false)
#EnableRedisHttpSession
public class HttpSessionConfig
{
...
}
I had the same question and through the comments, I was able to get my answer so I'm putting this down here so the question is marked as answered:

SpatialRepository not autowiring

Does anyone know how to get SpatialRepository #Autowiring in a spring boot app? I have put the additional dependency in my classpath
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-spatial</artifactId>
<version>0.9</version>
</dependency>
with the following configuration options
#SuppressWarnings("unused")
#Configuration
#EnableAutoConfiguration
#EnableTransactionManagement
#EnableNeo4jRepositories(basePackages = {"com.eanda.prototype", "test.com.eanda.prototype"})
#ComponentScan({"com.erranda.prototype", "org.springframework.data.neo4j"})
I have tried it all but no avail. My domain class is this:
public interface ErrandRepository extends GraphRepository<Errand>, SpatialRepository<Errand> {}
I get the following exception when running a query on the spatial repo
java.lang.IllegalArgumentException: No index provider 'spatial' found. Maybe the intended provider (or one more of its dependencies) aren't on the classpath or it failed to load.
Are you introducing the spatial engine to an existing database?
Have you installed the spatial extension in the plugin directory?
Lorenzo

Resources