I want to add a custom PropertySource (the class, not annotation). Annotation is not sufficient as it only handles file sources.
The approach which works is to define own ApplicationContextInitializer and add proper declaration to META-INF/spring.factories. ApplicationContextInitializer just uses:
Environment.getPropertySources().addLast(...)
But there are some drawbacks, mainly:
It is always run, but the preferable behaviour would be to only run if certain conditions are met (#ConditionalOnClass, etc)
How to achieve that? Ideally I'd write my autoconfiguration with #Condition... annotations and inside declare such initializer (preferably Ordered).
Edit:
In my particular case I want to define Archaius PolledConfigurationSource, but only if Archaius is on the classpath - that's why I'd like to use #ConditionalOnClass together with a listener on an event very early in the lifecycle.
You could have an intermediary class - part of your application, let's call it the "ProviderConfigurer" - of which goal will be to load a Service (packaged in a separate jar with META-INF/services/targetSPi) that in turn will load Archaius.
So to activate Archaius you will have to place 2 jars instead of one, but then the ProviderConfigurer will be able to load the property source provided by the Service (the API will be part of the interface you will have to define...) if any is discovered in the class path and do nothing in case the Service doesn't find any class implementing the SPI you will define for the purpose.
Related
Why do we need META-INF/spring.factories when create starters for Spring Boot applications? What if omit it at all or leave empty?
Doesn't the target application's #SpringBootApplication which is
a combination of three annotations #Configuration (used for Java-based
configuration), #ComponentScan (used for component scanning), and
#EnableAutoConfiguration
scan everything and find all beans from all the starters with no help of META-INF/spring.factories?
Component Scanning would scan the packages that you give it. You could technically tell it to scan all the packages of your dependencies, too, and it would start loading up any beans defined in them. If you don’t specify any packages to scan, then Spring will use the base package where the annotation is applied, which would very likely not include beans defined in any dependency libs.
There’s another layer to this- a lot of the libraries you use may be using annotations like “#AutoConfigureBefore” to give spring instructions on the order of bean creation. Component Scanning will not respect that, which could result in some weird behaviors if some dependency tries to override a bean from another which is annotated with #ConditionalOnMissingBean (I.e. create this bean only if it doesn’t exist.) You could easily end up with name collision issues where that bean actually gets created first, and then the override bean is created, too.
So the answer seems to be no. You need spring.factories.
Doesn't the target application's #SpringBootApplication scan everything...
No, it doesn't scan everything because if it was it could take a lot of time and resources. Think about it in a way that in order to understand whether the file with an extension *.class contains a bean (something annotated with #Component for example) it needs at least to read a class and analyze the byte code or even load it into memory to check the annotation by reflection.
So if your application's root package is in com.sample.app (the package with the class annotated with #SpringBootApplication), then spring boot by convention scans only the beans in this package and the packages beneath it. This means that it won't scan any thirdparties (assuming they won't be placed in com.sample.app anyway).
Now Its true that you can change the rules of component scanning, but again, you don't want to scan everything for performance reasons at least.
So Autoconfiguration modules (technically implemented with META-INF/spring.factories can specify an additional place (classes annotated with #Configuration) that spring boot will load despite the fact that they are not placed under the packages of your application
or, in other words, they do not obey the default component scanning rules.
In addition, spring.factories file allows to specify much more than auto configuration rules, you can specify environment post processors there for example, and other stuff that can be useful for your application, probably mostly beneficial at the level of application infrastructure, but still.
I love the Spring properties loading mechanism. The fact that you can define several profiles and override or extend properties with other profiles, that you can use different file types (.properties, XML, JSON, ...) to store your properties, that you can use the value of other properties to resolve its own value, aso.
But to use the properties, you have to somehow initialize the Spring context (#SpringBootApplication or #SpringBootTest). And I would like to use this property loading mechanism in some libraries, where I cannot guarantee that the context is loaded (and I do not want to load it).
So, my question:
Can I somehow create a class that uses the Spring libraries to load the properties (on demand) in the same way Spring loads its properties?
Other classes will then use this class to access the properties. No need to load with annotations.
I was searching for this for some time, but I haven't found a solution, yet.
Would be great if so. knows a solution for that.
Regards, stay healthy and merry X-Mas!
The property lookup mechanism is defined by interface PropertyResolver, extended by interface Environment to support profiles, further extended by interface ConfigurableEnvironment to support PropertySources, i.e. the concept of searching through a set of property sources to find a property.
It is implemented e.g. by class StandardEnvironment, which defines property source for:
system properties
system environment variables
All the above are part of package org.springframework.core.env, i.e. part of the spring-core-XXX.jar file.
Support for application.properties files is added by class ConfigFileApplicationListener in package org.springframework.boot.context.config.
The class needs an instance of SpringApplication in package org.springframework.boot.
They are part of the spring-boot-XXX.jar file.
So, getting basic Spring property support is easy, just create a StandardEnvironment object.
Getting application.properties files loaded is deeply embedded in the Spring Boot code, and would be really difficult to do without initializing the Spring context.
I want to change the package of classes that have been annotated with a particular annotation. I want to do this so that they can't be picked up by Jersey. I'm wondering if this is achievable within a Spring (Boot) application. If so, where is the best place to add this? I had originally wanted to do this in a ImportBeanDefinitionRegistrar so I could add an EnableXXX annotation on a config class, but I think that might be too late in the Spring lifecycle to redefine classes.
Yes, Byte Buddy allows you to change the name of any instrumented type. You can create an AgentBuilder to match all types that carry your annotation and change their package name using the DSL.
Do however note that any references to this class would not be updated automatically and other implications of a package change would be rather unpredictable. Generally, I would not recommend you to go down that route.
I'm working in a webapp and this is the first time that I'm using Java based configuration. I have a bunch of class to configure all:
ApplicationContext
PersistenceContext
SecurityContext
WebAppInitializer
WebMvcContext
Now I'm defining Spring Data repositories and the service layer so I need to inject the repositories there. Normally I would use Autowired but I've read that it is preferable to define the injections manually so the question is, where?
Maybe neither of the previous configuration classes is suitable for such task but, do I have to create a single class to define all the injections or is better to have on for each function? What happens if the project grows too much?
I think that the main question would be what is best way to organize dependencies in a Spring project. What do you do?
I add here an image of the structure of the project as a petition. I'm trying to decouple layers and now I need to inject UserRepository to UserService.
No, I would not define a single class to do all the injections. All your classes are coupled that way.
I don't understand what "define the injections manually" means. You have to specify them in either XML or annotations. There's no other way that I know of.
You don't say if you're using XML or annotation configuration. I find myself using the latter more of the time, with only enough XML configuration to tell the Spring app context to scan for annotations.
The Spring idiom would have you specify your configuration in layers if you're using XML. It's a moot point for annotations, because they go into your source code.
Your application will read the Spring context on start up, instantiate all the beans, and wire together the necessary dependencies. You're good to go from then on.
I disagree with the link you provided. Avoid autowiring? No.
The article said that he recommends using XML configuration for large projects. This is a very small project at this point. It seems to me that auto wiring with annotations would be fine even by the article's author's words.
I have been searching for a while, but I can't found any information on how to achieve in Java EE to define custom annotations (interceptor bindings) to be able to be used in multiple maven modules without declaring it in every package where I would like to use it. It's basic interceptor where implementation only prints something into console.
An example is like javax.ws.rs.Path where this annotation can be used on multiple locations and everything what it needs to do is to import correct dependency. I cannot achieve same affect with my annotation.
I have created new maven module with the interceptor and binding annotation. I also have beans.xml file in META-INF folder to enable CDI. Then I add dependency of this module to other project, where I want to use this annotation. Problem is, that when I want to use this annotations, the implementation of annotation does not execute method which is annotated with #AroundInvoke annotation.
I don't know what I'm doing wrong, because weld should start initializing bean implementation because CDI is enabled, but he don't, unless I put extra configuration for <interceptor> in beans.xml file where I want to use annotation.
Assuming by package you mean module;
You need to declare your annotation in its own maven module (possibly with other shared logic). Then pull in that maven module as a dependency in your other modules. That way you can use the annotation wherever you want.