how to dynamically load the config in java with spring - java

I'm writing a WebApp back-end with spring in java. in the code there are a lot of magic numbers. is there a way to put this in a config in such a way that any changes in this config will be put in effect without restarting the entire app?

When java process start it loads spring context, once spring context is loaded it only reads properties file once so if you are changing any property you have to restart your app thats good to have way.
OR you can replace java.util.Properties with a PropertiesConfiguration from the Apache Commons Configuration project. It supports automatic reloading, either by detecting when the file changes, or by triggering through JMX.
one more alternate way is to keep all your prop variables in database and refresh your reference cache periodically that way you don't have to restart your app and can change properties on-fly from database.

You can call the configuration file through the below steps:
Use the #Configuration annotation for the class which calls the
config file.
Another annotation to be declared above the class for defining the path to the config file #PropertySource({"URL/PATH_OF_THE_CONFIG_FILE"})
#Value("${PROPERTY_KEY}") annotation above a variable where the value corresponding to the property_key needs to be assigned.
The the following bean in the same configuration invoking class.
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
Make sure the #ComponentScan covers the folder where the config file is placed

Here is the way you can configure it
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemalocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--To load properties file -->
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:META-INF/*-config.properties">
</property></bean>
<bean id="createCustomer" class="com.example.Customer">
<property name="propertyToInject" value="${example.propertyNameUnderPropertyFile}">
</beans>
You can also refer it in java file straight away
public class Customer {
#Value("${example.propertyNameUnderPropertyFile}")
private String attr;
}

Related

Can We Have Multiple Spring Configuration Files in One Project?

Can We Have Multiple Spring Configuration Files in One Project? If yes, can someone provide a working example to support this concept?
Yes, in large projects, having multiple Spring configurations increase maintainability and modularity.
You can load multiple files like this:-
#Configuration
#Import({MainConfig.class, SchedulerConfig.class})
public class AppConfig {
You can also upload one XML file that will contain all configs.
ApplicationContext context = new ClassPathXmlApplicationContext("spring-all.xml");
inside the XML file:-
<import resource="main.xml"/>
<import resource="scheduler.xml"/>

Is it possible to add hibernate validator settings via configuration properties in Spring Boot app?

At the moment, I'm doing it via META-INF/validation.xml file:
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration" version="1.1">
<property name="hibernate.validator.allow_parameter_constraint_override">true</property>
<!--other properties-->
</validation-config>
Does Spring Boot provide any possibility to do the same (to set those hibernate.validator settings) via configuration properties (in application.properties/application.yml)?
If no, is there any other way to get rid of validation.xml file (e.g. with overriding some beans etc.)?

Load spring xml config dynamically

At the startup time of a spring app, I want to scan a path on the computer, find the jar files and build a spring application context from an xml config files inside them. Every thing is OK to add jar file to the classpath and making an ApplicationContext. But I can't find any beans from new context. All of needed dependencies are available in the jar files in the specific path on computer (via a maven copier plugin) expect those dependencies which are in the base spring project (for example spring dependency itself).
The code is (In Kotlin language):
var loader = URLClassLoader(arrayOf(entry.toFile().toURL()), Thread.currentThread().contextClassLoader)
...
val context = ClassPathXmlApplicationContext("classpath*:/$name")//name is xml file. I'm sure the address in classpath is right. context is not creating when the address in wrong. for example: classpath://$name
val services = context.getBeanNamesForType(IService::class.java)//services is empty
I have tried many other ways to load the xml but none of them was successful. for example:
val beans = DefaultListableBeanFactory(applicationContext)
val reader = XmlBeanDefinitionReader(beans)
reader.beanClassLoader = loader
reader.resourceLoader = resourceLoader
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD)
jarFile.getInputStream(jarEntry).use {
reader.loadBeanDefinitions(EncodedResource(InputStreamResource(it)))
}
beans.preInstantiateSingletons()
the xml inside jar file looks like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<import resource="classpath*:/xxx-logic-context.xml"/>
<context:annotation-config/>
<context:component-scan base-package="aa.bbb.ccc.server"/>
</beans>
It's really interesting: When I define regular Beans instead using package scaning feature, I can get the bean in a sort of code
Great answer from #talex guided me. I fixed it by setting the current class loader:
val loader = URLClassLoader(arrayOf(entry.toFile().toURL()), Thread.currentThread().contextClassLoader)
Thread.currentThread().contextClassLoader = loader

how to read properties file in spring project?

Before post this Question, I google to get Properties from Spring project(Its NOT web-based project). I am confused as every one are talking about application-context.xml and have configuration like
However, I am working on normal Java Project with Spring(NO Web-app and stuff like that). But I would like to get some common properties from properties file and that needs to be used in JAVA file. How can achieve this by using Spring/Spring Annotations?
Where I should configure myprops.properties file under my project and how to invoke through spring?
My understanding is application-context.xml is used ONLY for web based projects. If not, how should I configure this application-context.xml as I do NOT have web.xml to define the application-context.xml
You can create an XML based application context like:
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
if the xml file is located on your class path. Alternatively, you can use a file on the file system:
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");
More information is available in the Spring reference docs. You should also register a shutdown hook to ensure graceful shutdown:
ctx.registerShutdownHook();
Next, you can use the PropertyPlaceHolderConfigurer to extract the properties from a '.properties' file and inject them into your beans:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
Lastly, if you prefer annotation based config, you can use the #Value annotation to inject properties into you beans:
#Component
public class SomeBean {
#Value("${jdbc.url}")
private String jdbcUrl;
}
As of Spring 4, you can use the #PropertySource annotation in a Spring #Configuration class:
#Configuration
#PropertySource("application.properties")
public class ApplicationConfig {
// more config ...
}
If you would like to have your config outside of your classpath, you can use the file: prefix:
#PropertySource("file:/path/to/application.properties")
Alternatively, you can use an environmental variable to define the file
#PropertySource("file:${APP_PROPERTIES}")
Where APP_PROPERTIES is an environmental variable that has the value of the location of the property file, e.g. /path/to/application.properties.
Please read my blog post Spring #PropertySource for more information about #PropertySource, its usage, how property values can be overridden and how optional property sources can be specified.
You don't have to use Spring.
You can read with plain java like this:
Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
Can you figure out how your project will be used in the whole app? If your project is used as a build path for a web app and the configuration in your project is achieved through spring annotations, so no doubt you are puzzled about how to add an application.xml file. My suggest is you have to announce the guys who will use your project, tell them what you need and you just need to add #Value("${valuename}") in your code.
Create new property file inside your src/main/resources/ directory and file extension must be .properties e.g. db.properties
Write following context properties in your spring xml configuration file:
<context:property-placeholder location="db.properties"/>
Usage: ${property-key}

spring ide and ref hyperlink click doesn't work if bean is defined in different file

when I have a bean
<bean name="myBean" class="mypackage.myBean">
<property name="otherBean" ref="otherBeanRef" />
</bean>
and I click on otherBeanRef I'm redirected to definition of otherBeanRef, however this only works if its in the same file.
how to configure spring ide to also support other spring files?
You need to add both files to the Spring Spring Config File Set.
Spring Explorer/Properties/Config Sets

Categories