How to load PropertySources sooner in Spring Boot - spring-boot

I have currently a problem in my DEV environment. I have for Spring Security two configurations, one for the Admin part of my application and the other for the rest of the user. For the admin part, I create one or another depending on beans decorated with a Conditional annotation. This conditionals rely on some property that is loaded from a class that is annotated with #PropertySource and this is important, this property I cannot set it neither in application.properties nor application-<environment>.properties. The problem comes that when these conditionals are evaluated because are spring security classes, the properties that are expected to perform such evaluation are not available, they come in a later stage, when Spring boot do some refresh context. My question is how I can do it do this class annotated with #Configuration #PropertySources to be loaded much sooner, right after the Profile is processed.
Thanks in advance.

Related

Is an explicit CacheManager bean definition mandatory when using Spring Boot + Spring Cache?

From documentation Spring Boot uses ConcurrentMapCacheManager as CacheManager implementation by default if we don't define own CacheManager bean definition. But I keep getting 'No qualifying bean of type 'org.springframework.cache.CacheManager' available' error eventhough spring-boot-starter-cache and #EnableCaching is there.
Any help would be greatly appreciated.
Best regards,
SetNug
Short answer... NO.
I suspect you are having problems while (integration) testing? If so, then you probably need to declare the appropriate "test slice annotation", that is #AutoConfigureCache; see Javadoc.
To demonstrate, I created a simple example with a test class contained in this module of my SO repository. You must declare the #AutoConfigureCache annotation in configuration (see here) even if your test is a #SpringBootTest.
As Spring Boot's documentation describes, all of Spring Boot's auto-configuration (which is quite extensive) can be a bit much for testing. As such, none of Spring Boot's auto-configuration is enabled by default. Therefore, you must explicitly enable what you want, or, alternatively, you can declare that you want Spring Boot's entire auto-configuration enabled, by replacing the #AutoConfigureCache annotation declaration with Spring Boot's #EnableAutoConfiguration annotation instead.
You are correct that Spring Boot will auto-configure a "Simple" caching provider (i.e. the ConcurrentMapCacheManager, or in other words, a Spring CacheManager implementation backed by a java.util.concurent.ConcurrentHashMap; see here) when no other cache provider implementation (e.g Redis) is present or explicitly declared.
However, Spring Boot auto-configuration is only in effect when your Spring Boot application is an "application", which I have shown here.
Of course, it is also true that if your #SpringBootApplication annotated class is found (in the classpath component-scan) by your test as described, then it will also enable caching without any explicit annotations, such as, no need to explicitly declare the #AutoConfigureCache test slice annotation, even.
NOTE: In my example, I deliberately did not package the source according to the suggested structure. So, if I were to replace the #AutoConfigureCache annotation declaration in my test configuration with #Import(SpringBootDefaultCachingApplication.class) and comment out this assertion from the application class, then the test would also pass. Using the #Import annotation in this way works similarly as if the test class and application class were in the same package, or the application class were in a parent package relative to the test class.
1 last tip... you can always enable Spring Boot debugging (see Baeldung's blog) to see what auto-configuration is applied while running your application, or even while running tests.

Implementation provided for BatchConfigurer is not connsidered when using #EnableBatchProcessing(modular=true)

I am developing a sample application that Spring Batch with Spring Boot. My requirement is:
Have my own implementation of BasicBatchConfigurer so that I can configure AsyncTaskExecutor and my own dataSource as I am using SAP HANA as DB for which databaseType is not supported.
I want to use #EnableBatchProcessing(modular=true) so that I can register multiple jobs and launch them with separate Child Context
I have added all the required configurations. Without setting modular=true the Job is Launched and works as expected. It initializes the beans defined from my implementation of BasicBatchConfigurer.
However, once modular=true is set, the beans from my implementation are not initialized.
The code is hosted here: https://github.com/VKJEY/spring-framework-evaluation
I debugged further into the issue:
Looks like, When we set modular=true, BatchConfigurationSelector uses ModularBatchConfiguration
In ModularBatchConfiguration, there's a field Collection<BatchConfigurer> configurers. This has been annotated as #autowired.
I assume that this field is auto initialized if I provided a implementation
of BatchConfigurer as it has been mentioned in the comments of ModularBatchConfiguration class as well
However, While debugging I realized that the above field is still null beacuse of which, It loads DefaultBatchConfigurer and follows the default flow.
My question is why is that field configurers not being initialized in ModularBatchConfiguration? Am I missing something?
I am using Spring boot 2.1.2.
My question is why is that field configurers not being initialized in ModularBatchConfiguration? Am I missing something?
You are hitting a lifecycle issue between Spring Boot custom auto-configuration that you defined in the META-INF/spring.factories file and Spring Batch configuration.
I debugged your code and here is how to fix the issue:
remove org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.job.data.persistence.config.AsyncBatchConfigurer
from META-INF/spring.factories file. This is not needed as Spring Batch
will detect the AsyncBatchConfigurer when it is declared as a bean.
You can even remove this spring.factories file
remove #ConditionalOnMissingBean(BatchConfigurer.class) from AsyncBatchConfigurer:
Since you declared this class as a #Configuration class, it will also be defined as a bean of type BatchConfigurer and will be detected by ModularBatchConfiguration
With these two changes, the field configurers in ModularBatchConfiguration is correctly autowired with your AsyncBatchConfigurer.
As a side note, you don't need the AsyncBatchConfigurer#configurers method as Spring will do the work of injecting all BatchConfigurer beans in ModularBatchConfiguration.
Hope this helps.

Spring Boot - Load bean only if it is enabled by a property

I have a Spring Boot application with different submodules which also contains spring components.
And in the main web modules I use 70% of the beans from the submodules. It depends on the application.yml properties, if the property group (which points to a bean) is enabled or not.
First I wanted to create Aspect-s, so when a method of a bean (which is not enabled by it's property) is called, then throw an exception. This solution could work, but then I would need to create Aspect classes, method annotations, import more and more dependencies.
So I am just wondering, would be there any other easier solution to disable a bean, or do not load at all to the spring boot container?
I would imagine something like #DependsOn, but for this you need to give a name of a bean name, but you cannot use this annotation to work with yml property.
Other easy solution is to #Bean or #Import every bean I want to managed by spring container, instead of #Import everything once from submodules, but then it is a static setting, cannot be overwrite by a single property from yml.
Spring introduced the concept of conditionals quite some time ago. Spring Boot uses this to a great extend to conditionally enable features. It even created a lot of conditional rules which you can use.
One of those rules is the conditional on a property rule. To use this rule add an #ConditionalOnProperty annotation to your bean. Now it will only be included if said property is enabled or has the specific value.
#ConditionalOnProperty(name="your.property.name")

What is good practice to configure Spring MVC application with Spring security?

Assume I have Spring MVC powered application with Spring security. I have:
UserBean class which provides CRUD operations on table User
UserController : controller which expose operation on User to http clients
UserLogin: Authentication provider from Spring security, which authenticates users.
How should I configure my application if:
I want simple XML configuration, with auto-discovering beans by annotations (<context:component-scan base-package="org.example"/>)
UserLogin and UserController needs UserBean to work
UserLogin and UserController use transaction annotations and aspect annotations
I see the following oportunities:
Create one common Spring XML configuration file, used both by DispatcherServlet and ContextLoaderListener
Disadvantage: nobody shows that solution in tutorial. All beans are duplicated (one instance in ContextLoaderListener context, second in DispatcherServlet). Duplication may cause some hard to track bugs. Duplication is not elegant
Create two Spring XML configuration files, one for ContextLoaderListener (main) and one for DispatcherServlet (controllers). UserBean is declared in first config and visible in second one
Disadvantage: to avoid duplication I have to add complex component scanning rules to both files (context:component-scan). <tx:annotation-driven and <aop:aspectj-autoproxy/> must be defined in both files. I will have still doubts which config file is appropiate when declaring new stuff.
Create two Spring XML configuration files and include third for common settings like <tx:annotation-driven
Disadvantage: I wanted simple solution...
Summary: I'm looking for good practice to configure application with Spring MVC + Spring Security AND security part is highly connected with business part. I was searching for good example but I always find case when security code is isolated from business code. But I need example when security and business share the code
Similar question: ContextLoaderListener or not?
I have two xml files for my configuration, no particular reason, that's just how it worked out.
These sample spring security projects provide good examples of lots of different types of configurations maybe you can find something that works for you:
https://github.com/spring-projects/spring-security/tree/master/samples
Hidden message in my question was: having two contexts is stupid.
Did someone already notice that?
Is there a way to have single application configuration?
Answers:
Yes. https://jira.springsource.org/browse/SPR-6903
Yes. https://github.com/michaldo/spring-single-context-demo
The best practice which applies to my case is described here: https://stackoverflow.com/a/14032213/2365727

Hard?: Spring security on classes that are not Spring Beans?

Definitely need some expert help with this! I think this is mainly a Spring Security question, but as I don't know for sure, so I am also tagging with the general Spring tag!
When the Application Context is loaded (mine is all via Java Config, though I don't believe that matters), the "DefaultListableBeanFactory" is processed and eventually (via the ProxyFactory) Spring Security Advisors are added. This is great when I have Spring Beans as I have Permissions that need authorization.
My question is: how do I get the same effect when I no longer require those classes to be Spring Beans? Said differently, if I have an object instance created as a singleton bean via Java Config and the authorization is working correctly, is it possible to maintain that with the object instance being a POJO? Again, for the experts, I want the interception chain returned in the JdkDynamicAopProxy to contain the Spring Security interceptors.
And "no", I am not really expecting an answer to this, maybe just hoping!!!
To add security interceptors to beans not instantiated by spring container
switch global-security tag to mode aspectj and weave the provided AnnotationSecurityAspect in the aspecj module.
For your second question I suppose that you want to do one of the following:
Use a ProxyFactoryBean to secure a bean.
Create security proxies programmatically: Use ProxyFactory.addAdvice() method.
Add the security interceptor to all proxies created by an AutoProxyCreator: This usually don't needed, but you can use the AbstractAutoProxyCreator.interceptorNames property to add common interceptors. The global-security tag parser uses a generated name for the MethodSecurityInterceptor, so you need to configure the interceptor manually and set a consistent SecurityMetadataSource.

Resources