I want my spring boot server to be up even if my redis cache isnt up.
I am using #EnableCachingannotation , but my server startup fails if redis is down giving me BeanCreationException. Because BeanCreationException cannot be handled , the only option I have is to lazy load my #EnableCaching class.
I tried annotating that class as under:
#Configuration
#EnableCaching
#Lazy
#Profile("dev")
public class RedisCache extends CachingConfigurerSupport {}
But still this bean is getting loaded at server startup and startup therefore fails.
How do I lazy load the above mentioned class
As far as I know Spring configuration is alwasy loaded on application startup, because that is when the ApplicationContext is created.
In order to do what you want you'd either have to create some sort of custom implementation of ApplicationContext (although I honestly cannot think of how it should work regarding the dependency resolution for dependency injection) or create custom wrapper for caching which would not try to establish connection to Redis until the cache is used.
It may also be possible to configure Spring Boot to skip this particular #Configuration class (Using Boot configuration classes) and then to manually create AnnotationConfigApplicationContext and then retrieve Redis connection Beans from this context manually rather than autowiring them.
Related
I am running a Spring Boot application connecting to a Cassandra database with Spring Data. The Spring Data connection relies on username and password that will be generated by a custom Configuration Class, but the application won't start because it loads CassandraDataAutoConfiguration before ever getting to the custom Configuration Class, causing the application to fail with an authentication error. I need to make sure that this custom Configuration class is loaded before CassandraDataAutoConfiguration.
I have tried adding #AutoConfigureBefore({CassandraDataAutoConfiguration.class}) to the custom Configuration class, but am still seeing the same issue.
If you want to configure the order in which beans are instantiated by spring you can use:
#DependsOn("A")
public class B {
...
}
This would create bean "A", than "B".
Reference
I've enabled caching in a SpringBoot application with the #EnableCaching and #Cacheable annotations. The cache properties are defined in the application.yaml file.
spring
cache
type=simple
Now I want to know if there is a way to access explicitly the cacheManager bean defined by Spring Boot(created to support the #EnableCaching annotation) without defining a new CacheManager Bean in the configuration files.
I'm basically trying to autowire the cacheManager bean defined by Spring Boot so that I can make explicit calls to it.
#Autowired
private CacheManager cacheManager;
...
Cache cache = cacheManage.getCache("toto")
Regards
Notes: My IDE is telling me that It can't autowire the cacheManager bean
Finally, the IDE warning was wrong. I was able to autowire the cache manager bean provided by Spring Boot and I was able to call it explicitly.
Regards
I have a spring configuration class in main that creates redis client bean.
In tests I have another configuration class which creates embedded redis server bean. The problem is to force embedded redis server bean to be created before redis client one. I tried with #Order anotation without success. Importing test configuration to main one isn't an option.
When I define EmbeddedRedis as #Component then it will be created before the client but this is also not an option since EmbeddedRedis is a part of shareable test library which should not be created when not needed.
I have a workaround solution with an interface called RedisServerConfiguration which has different implementations for main and test and client depends on it so I am able to start server before the client tries to connect but this requires another abstraction and it would be nice to simplify it. Is there any spring mechanism I am not aware of that allows to force the order of bean initialization ?
I am trying to avoid component scanning to reduce start up time in our module tests, and in our web app in general.
When I replace #SpringBootApplication with #SpringBootConfiguration #EnableAutoConfiguration, I get the following error:
Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean
Can I manually import the EmbeddedServletContainerFactory somehow?
My suggestion is to first run your application with the debug flag on and write down all the activated auto-configurations. Then, disable auto-configuration and import those configurations by using #Import on your application class.
Alternatively, you can look at each of those configuration classes and see what Spring Boot configures for you and decide if you want to provide your own configurations instead - you can just mimic the auto-configuration classes and everything should work the same way.
Miloš and Pieter provided the means to find the answer. A minimal Spring Boot Web Application can be started with the following:
#SpringBootConfiguration
#Import({EmbeddedServletContainerAutoConfiguration.class})
public class Application extends SpringBootServletInitializer {
...
}
ServerPropertiesAutoConfiguration.class might also be handy to pick up things like port number for the application.
I have a spring webapp with annotation driven configuration.
All Controllers, Repositories are autowired.
When integrating Spring Security I defined a separate security-app.xml. I created a Service called LoginUserService which implements UserDetailsService. Now the method loadUserByUsername() method of this class gets invoked for authentication.
This class has an autowired dependency for UserRepository. Now this autowired dependency turns out to be null. To fix this I enable annotation driven configuration and add the package name for the repository class in component scan configuration.
This solution is also discussed here
spring security with custom user details
But now the problem is that the UserRepository has an EntityManager field with #PersistenceContext annotation. For the spring security configuration it is able to locate the UserRepository but not able to locate the entity manager. Should I create a new EntityManagerFactory here? I guess that will create two persistence units in my application?
How can I inject an autowired dependency to UserRepository created with the original servlet xml?
Update
This is briefly discussed here:
https://stackoverflow.com/a/7078395/161628
But I guess a canonical detailed answer will be more useful to me.
Update
How about using ApplicationContext to get the UserRepository at runtime?
if (userRepository == null) {
userRepository = ApplicationContextProvider.getApplicatonContext().getBean(UserRepository.class);
}
Why is Spring's ApplicationContext.getBean considered bad?
EDIT: Beans that you declare in your config for your DispatcherServlet are not going to be available to any beans you declare or component scan in your contextConfigLocation config files. So in this case, if you're setting up your JPA config in your config file that you load for your DispatcherServlet there is no way to wire that in to beans your declare in your security config. You need to move any "core" bean config like that (datasource config, db connection pool config, JPA/Hibernate config, repository/service component scanning, etc.) into a config file that you load via the contextConfigLocation. Then that stuff will be available both to your security beans and your MVC beans. I think generally the idea is to only load MVC specific beans in your DispatcherServlet config (e.g. Controllers, views, request handlers, request scoped beans, etc.). That way you ensure you have a clean separation between MVC code and non-MVC code, with only a one-way dependency from the MVC code to the "core" code, and no dependencies on MVC code in your "core" code. This helps make your code more modular, and makes it easier to reuse your "core" code in other ways, specifically in unit tests.
(Original comment text was asking about how the security config is loaded, if it's in the contextConfigLocation or somewhere else.)