SpringBootApplication excludes of AutoConfigurations from base class - spring-boot

I have a really annoying problem, in our project we have lots of Spring Boot Applications, lately we have little bit stress with our start times in kubernetes, so we would like to turn off some AutoConfiguration files that are not necessary for us.
While we have more then 30 SB application, I thought it would be a nice idea to create a base class with those exclusions and use that in every 30 SB application as a base class, for that I used '#EnableAutoConfiguration' class while it also contains '#Inherited' annotation and then '#SpringBootApplication' well unfortunately this is not the case.
If I start my application in this configuration, I see in the DEBUG AutoConfiguration classes are still evaluated (they are not if I use #SpringBootApplication 'excludes' property).
Of course, if I use a Array in the Base Class, it does not work with the limitations of Java Annotations.
Now there is also 'spring.autoconfigure.exclude' property that I can defined classes in the application.yaml in a jar distribute that but that is not really elegant also.
What I try to achieve, I think it is not that ordinary, how would you solve this problem?

Related

How to make pf4j plugin beans injectable into Spring app

We are trying to utilize pf4j and pf4j-spring to provide a flexible application based on Spring.
Ideally, we would like to define Spring beans (#Service, #Repository and others) in plugins and inject them in the main application.
From what I can see, it seems to fail due to timing issues. Or in other words, Springs expects the beans to be available before the PluginManager gets instantiated.
There is an example repository that illustrates the issue on GitHub.
The question would be: Can I change something, so that Spring instantiates the PluginManager first? Is there another approach to make this work?
Note: Yes, we are aware of sbp. Unfortunately, it seems to be dead, and we didn't get it working properly either.

Is Java Spring really better than straight up Java programming

I have read that dependency injection is good for testing, in that a class can be tested without its dependencies, but the question comes to my mind if Class A depends on Class B or C or any class, testing Class A independent of some class is yielding a test result of zero, not a failed or past test.
Class A was created to do something and if it is not fed anything whether using new key word or setting up the extra files in Spring, Class A won't do any work.
About the idea of making code modular, readable and maintainable: so business classes became cleaner, but all we did was shift confusion from dirty Java business classes to convoluted XML files and having to delete interfaces used to inject to our loosened objects.
In short, it seems we have to make edits and changes to a file somewhere,right?
Please feel free to put me in my place if my understanding is lacking, just a little irritated with learning Spring because I see the same amount of work just rearranged.
Dependency injection is good for unit testing because you can individually test each method without that method depending on anything else. That way each unit test can test exactly one method.
I would say that if the xml is what’s annoying you check out Spring boot. It’s based on a java configuration so no xml and it simplifies a lot of configuration for you based on your class path. When I first started spring I found the xml very daunting coming from a java background but the annotation based configuration and the auto configuring done by spring boot is extremely helpful for quickly getting applications working.
IMO biggest advantage of using the spring is dependency injection which makes your life easy. For example if you would like to create a new service with three dependencies, then you can create a class very easily using Spring. But without spring, you will end up writing different factory methods which will return you the instances you are looking for. This makes your code very verbose with static method calls. You may want to take a look at the code repositories before spring era.
Again if you would like to use Spring or not is your personal call based on project complexity. But it's other features/advantages cant be overlooked.
And XML files or Java configs are the ways of achieving spring configuration - where you would like to add your business logic is personal flavour. Only thing is you should be consistent all across your project.
I would suggest that you read Martin Fowler's great article on Inversion of Control and Dependency Injection to gain a better understanding of why frameworks like Spring can be really useful to solve a well known set of common dependency injection problems when writing software.
As others have mentioned, there is no obligation to use Spring; and whatever you can do with Spring, you can probably do it by other means like abstract factories, factory methods, or service locators.
If your project is small enough, then you probably wouldn't mind solving the dependency injection issues on your own using some design patterns like those mentioned above. However, depending on the size of your project, many would prefer to use a framework or a library that already packs a bunch of solutions to these recurrent head scratchers.
In regards to the advantages of dependency injection frameworks when doing unit testing is the idea that you don't need to test the dependencies of your class, but only your class.
For example, most likely your application has a layered design. It is very common to have a data access class or a repository that you use to retrieve data from a datasource. Logically, you also have a class where you use that DAO.
Evidently, you already wrote unit testing for your DAO, and therefore, when you're testing your business class (where the DAO is being used) you don't care about testing your DAO again.
Fortunately, since Spring requires some form of dependency injection for your DAO, this means your class must provide a constructor or a setter method through which we can inject that DAO into our business class, right?
Well, then during unit testing of your business class, you can conveniently use those injection points to inject your own fake DAO (i.e. a mock object). That way, you can focus on the testing of your business class and forget about retesting the DAO again.
Now compare this idea with other solutions you may have done on your own:
You inject the dependency directly by instantiating the DAO within your business class.
You use a static factory method within your code to gain access to the DAO.
You use a static method from a service locator within your code to gain access to the DAO.
None of these solutions would make your code easy to test because there is no simple manner to get in the way of choosing exactly what dependency I want injected into my business class while testing it (e.g. how do you change the static factory method to use a fake DAO for testing purposes?).
So, in Spring, using XML configuration or annotations, you can easily have different dependencies being injected into your service object based on a number of conditions. For example, you may have some configurations for testing that evidently would be different than those used in production. And if you have a staging environment, you may even have different XML configurations of dependencies for your application depending on whether it is running in production or integration environments.
This pluggability of dependencies is the key winning factor here in my opinion.
So, as I was saying, my suggestion to you is that you first expand your understanding of what problems Spring core (and in general all dependency injection frameworks) is trying to solve and why it matters, and that will give you a broader perspective and understanding of these problems in a way that you could to determine when it is a good idea to use Spring and when it is not.

spring-boot Remove locations attributes from #ConfigurationProperties

Remove locations attributes from #ConfigurationProperties
What are the alternatives?
I've been using it like this before.
#ConfigurationProperties(locations = "a.yml")
Same problem here: we have hundreds of configuration keys on several yaml files, each of them conveniently mapped to a pojo that we inject into our business logic beans.
The best thing I could do to upgrade to Spring Boot 1.5 and at the same time keep our production application running without much refactoring is described here: http://fabiomaffioletti.me/blog/2016/12/20/spring-configuration-properties-handle-deprecated-locations/
Or, if that does not work for you, you can try this way which is simpler even if requires more refactoring (remove the #ConfigurationProperties annotation): http://fabiomaffioletti.me/blog/2017/02/09/spring-configuration-properties-locations-deprecation-another-approach/

Programmatically configure Spring Boot app

what's the easiest way to get the spring boot goodness but not try to autoconfigure all the things? For instance, to only run flyway with our already configured properties (some loaded via Consul + Spring Cloud), I was hoping I could do something like:
#Configuration
#Import({DataSourceAutoConfiguration.class, FlywayAutoConfiguration.class})
public class FlywaySetup {}
and have the main method just call SpringApplication.run(FlywaySetup.class)
The problem with this is it picks up all the Component Scan / crazy long list of other dependencies. Any way to specifically configure the dependencies (but still get the nicities of the framework)
If you run this app, it shouldn't use component scan at all. There's nothing that triggers component scan in spring boot besides #ComponentScan (that's available on #SpringBootApplication).
It would help if you could provide more accurate details rather than "crazy long list of other dependencies.". Running that FlywaySetup should only load those two configuration classes (important: these are not handled as auto-configuration anymore). If you have component scan, there's something else you're not showing.
You can exclude auto-configurations you don't need.
You may want to take a look at this SO answer to explore mechanism how to do that.

Classpath scanning in OSGi

My project has a set of custom defined annotations that could be present in any bundle deployed in the OSGi 4.3 framework. I want to find any class with these annotations in the classpath. I tried using BundleWiring.listResources(...) and Bundle.loadClass(...) for each class found. I have done some tests with an small set of bundles and it needs almost 200MB of Permanent Generation JVM memory space because all classes are loaded.
Is there a way to free loaded classes PermGen memory space when the program realizes that they does not have these annotations?
Is there a better way to look for annotated classes in an OSGi framework?
I think you should not do annotation scanning as it slows down startup and needs a lot of memory. JEE application servers do annotation scanning at startup to make lazy programmers happy and the result is very annoying (e.g. scan for JPA or EJB annotations).
I guess you are implementing a technology where you can define the rules. I suggest that you should define rules that are similar to these:
Annotate your class
Have a MANIFEST header where the annotated class must be listed.
An even better solution can be to use a custom capability namespace with specified attributes. E.g.:
Provide-Capability: myNamespace;classes=com.foo.myClass1,com.foo.myClass2
In your technology, you should write a BundleTracker that calls:
BundleWiring.getCapabilities("myNamespace");
If the namespace is present, you can find the classes that should be processed.
If you implemented the technology, you can consider an extension to Bnd to fill that MANIFEST header automatically. That extension can be used than when bnd is started from the command line or from build tools like maven.
Btw.: You can use ASM to parse the class bytecode or use the built in possibility of Java to build up AST. Although those could work to solve the memory issue, I still think that you should define the list of classes directly in the MANIFEST header as it makes things much more clear. You can read the MANIFEST headers, you can check the capabilities on webconsole but you cannot do the same with bytecode.
Usually, classpath scanning for annotations is a bad idea in an OSGi context, as the classpath is more like a graph. However, there are situations where this can be useful. Hence, OSGi encourages the usage of the Whiteboard Pattern.
What you could possibly do is register each of these classes as services in the OSGi registry. Then, create a separate bundle that just tracks these services and transforms/manipulates them in some way. For example, this project scans for all classes annotated with #Path and #Provider annotations, and transforms them into Jersey REST APIs.

Resources