Use Spring properties loading without initializing the Spring context - java

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.

Related

Spring boot - Loading configuration property file in to java.util.properties

I need to load a configuration property fully into java.util.Properties file in my spring boot project and then need to pass this wherever needed. With Spring boot I can load the full file and can get the access of the values though keys. But how I can load the whole configuration file into Properties object or pass the spring loaded property (not a single value rather all the values) wherever required?
My current code:
Properties myProps= new Properties();
myProps.load(resourceAsStream);
If you're looking for specific ways of loading them using Spring-boot I'd suggest looking into:
Binding properties to an object by using the #Configuration, #ConfigurationProperties and #PropertySource annotations if you want to enforce and implicitly manage type-safety at all times
The Environment interface you can #AutoWire to your classes, if you don't need to enforce type-safety at all times (you can still do it, but you're not forced to). #PropertySource can be used in this case as well to load properties outside the default default-loaded application.properties, although they'll be loaded only when the application context refreshes (e.g. they won't be available while the application is booting up)
The PropertiesLoaderUtils class, as suggested in the comments, if you want to selectively load a configuration file at runtime for example
I usually recommend the first. The result is the same as using an #AutoWired Environment, with the advantages of implicit type-safety and improved readability. You can then get the properties and write them inside your java.util.properties if you need them to be there.
However, there is more than one way to do that, both using Spring-Boot or not. Loading properties like that is also perfectly fine, although arguably not the best practice since you're using Spring-boot.

Where to define properties in SpringBoot which are common across all environments?

I have few properties common to all environments (Ex. spring.jpa.properties.hibernate.ejb.interceptor) which I have kept in application.properties under resource directory.
I have DB properties defined in environment based properties file which I pass externally through command line while starting the app:
java -jar -Dspring.config.location=<path-to-file> mySpringBootProject.jar
However, spring.jpa.properties.hibernate.ejb.interceptor is not being set when I am passing properties file externally.
Do I need to define common properties even in external file?
Or is there a way I can define them in a single place which is reused when not overridden?
You can use multiple profiles to do this. For example, create property files:
application-dev.properties
application-prod.properties
application.properties
Place your environment-specific properties in the application-${env}.properties file and your common properties in application.properties.
There are multiple ways to tell spring which profiles to use, for example the --spring.profiles.active flag.
See the Spring Boot documentation for more details about the property file search order.
application.properties will normally be overridden by Boot projects. Instead, you can add a properties file in a non-conflicting location (such as src/main/resources/my/package/foo.properties) and use #PropertySource on your autoconfiguration file to add it.
Properties is a file extension for files mainly used in Java related technologies to store the configurable parameters of an application. The advantage of using properties file is, we can configure things which are environment specific (or are prone to change over a period of time) without the need of changing anything in code. Hence inheriting common properties is not a good approach. If a property seems to be static for all e.g. environments, then it shouldn't be a property.
But, it could be we have multiple development environments and production, where we would share same properties in the environments meant for development purposes and different properties for production. In this case we could create a common properties file and inherit it in all our environment specific properties files. Another scenario could be, that at the moment of development the property is same for all environments, but we would like to provide the option of changing it in the future, when required.

Bean and Dependency Injection configuration from Database Instead XML

Currently we have all service class configuration defined in Application-Context.xml file. Application context will be initialized during the application startup with all beans defined in the context file and spring handles dependency injection.
I am looking for a solution where it has to load particular service class during run time based on specific parameter from Database.
For example, there are two classes exist in code base such as FooService1.java and FooService2.java. Each class will have dependency with appropriate DAO class such as FooDAO1.java and FooDAO2.java.
Instead of defining these in applciation-context.xml file, a run time parameter will decide which service needs to be loaded and its corresponding DAO which needs to be injected. Basically what i am trying to achieve here is DB oriented Dependency Injection to keep all application context information in database instead of XML.
Tables would look like: SERVICE_BEANS, DAO_BEANS and some intermediate table to have dependency information.
I just saw JdbcBeanDefinitionReader class in spring. Can I use this to implement DB oriented DI? I don't see much example on this. Please let me know if anyone has any examples.
I think you can generate beans # runtime and register them to spring-context.
Refer to Registering beans(prototype) at runtime in Spring
Hope that helps !

How to get bean definitions in Eclipse SWT Wizard?

I am developing a SWT component in which there is a child component through which user can view the Spring reference and can change the Spring bean definition, property etc..
I am facing 2 issues:
If the defintion of bean is defined in some other Spring XML rather than the selected Spring file, then how to proceed.
How to fetch source code of class (for preview) from defined beanClass e.g. com.xyz.abc.def.Foo.
For getting the info from the spring xmls, you have to do some parsing, there is no beating around that. However you could use O/X Mappers to simplify this process http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/oxm.html
As codejammer said, you will have to parse all xml files and possibly also included files through different mechanisms. The safest would be to use Spring's own classes to deal with it. More specifically, see XmlBeanDefinitionReader[1] for reading and using a, possible custom, implementation of BeanDefinitionRegistry[2] for holding a map of your valid beans.
The second problem of loading the source for a class, that is as easy as changing the class' packet name to a fully qualified path: com.xyz.abc.def.Foo -> com/xyz/abc/def/Foo.java
http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.html
http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/support/BeanDefinitionRegistry.html

Where should configuration be placed?

I have an application structured as follows:
dao
domain
main
services
utils
I've made a class that reads the application configuration from an XML file. The question is where should it be placed?
By reflex, I'd have placed it in utilities but utility classes have static methods and are stateless whereas this class uses an instance of Apache Commons XMLConfiguration. Should I just adapt the methods so this instance is limited to the scopes of the methods in this class?
I assume the items are packages, so I'd go with the main package.
dao
domain
main contains the application and its configuration readers
config
log
services
utils
Why? The configuration of an application, whether it be in XML or not and whether it is based on an application framework such as Spring or not, is part of its main functionality. Booting up an application is the main responsibility of the application. All the business functionality, all the shiny features it provides are implemented in the domain and service layers.
You're right, utils is all about static or similar tools. As the configuration of an application is very important, I wouldn't declare it a utility. A utility is something which can be easily replaced by another utility of same type (e.g. StringUtil vs. StringUtils vs. IOUtils etc. they all have very similar functionality)
This depends on the build system and application type you use i.g. maven would suggest to place configfiles in src/main/resources
In WAR file you could place them in WEB-INF or WEB-INF/config
According to your project structure I would suggest to introduce a folder config or resources, since almost everybody would expect them there.
If you are working with Spring, take a look at Configuration Placeholders. You can use a simple java properties file for your configuration properties and place it on your class path (or any other location). Alsou you could create your own implementation to use a different form of keeping your configuration values (XML, Database etc.)
As configuration is a cross-cutting aspect it doesn't map exclusively to one of these layers. Place the configuration files (XML or properties) into the classpath and use it via Spring to configure your beans.
For properties based configuration data the PropertyPlaceholderConfigurer is a good solution.
I urge you to have a look at Spring. Might seem like overkill for you in the first place, but you wil love it.

Categories

Resources