How to assign a value from application.properties to a static variable?
Think about your problem for a second. You don't have to keep any properties from application.properties
in static fields. The "workaround" suggested by Patrick is very dirty:
- you have no idea when this static field is modified
- you don't know which thread modifies it's value
- any thread at any time can change value of this static field and you are screwed
- initializing private static field that way has no sense to me
Keep in mind that when you have bean controlled by @Service
annotation you delegate its creation to Spring container. Spring controls this bean lifecycle by creating only one bean that is shared across the whole application (of course you can change this behavior, but I refer to a default one here). In this case any static field has no sense - Spring makes sure that there is only one instance of UserService
. And you get the error you have described, because static fields initialization happens many processor-cycles before Spring containers starts up. Here you can find more about when static fields are initialized.
Suggestion
It would be much better to do something like this:
@Service
public class UserService {
private final String svnUrl;
@Autowired
public UserService(@Value("${SVN_URL}") String svnUrl) {
this.svnUrl = svnUrl;
}
}
This approach is better for a few reasons:
- constructor injection describes directly what values are needed to initialize the object
final
field means that this value wont be changed after it gets initialized in a constructor call (you are thread safe)
Using @ConfigurationProperties
There is also another way to load multiple properties to a single class. It requires using prefix for all values you want to load to your configuration class. Consider following example:
@ConfigurationProperties(prefix = "test")
public class TestProperties {
private String svnUrl;
private int somePort;
// ... getters and setters
}
Spring will handle TestProperties
class initialization (it will create a testProperties
bean) and you can inject this object to any other bean initialized by Spring container. And here is what exemplary application.properties
file look like:
test.svnUrl=https://svn.localhost.com/repo/
test.somePort=8080
Baeldung created a great post on this subject on his blog, I recommend reading it for more information.
Alternative solution
If you need somehow to use values in static context it's better to define some public class with public static final
fields inside - those values will be instantiated when classloader loads this class and they wont be modified during application lifetime. The only problem is that you won't be able to load these values from Spring's application.properties
file, you will have to maintain them directly in the code (or you could implement some class that loads values for these constants from properties file, but this sounds so verbose to the problem you are trying to solve).
spring - read property value from properties file in static field of class
In you Utility
class you can have a setter method to set the properties and then you can use MethdInvokingFactoryBean
.
class Utility{
static String username;
static String password;
public static setUserNameAndPassword(String username, String password){
Utility.username = username;
Utility.password = password;
}
//other stuff
}
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:/myservice_detaults.properties</value>
<value>classpath*:/log4j.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="foo.bar.Utility.setUserNameAndPassword"/>
<property name="arguments">
<list>
<value>${username}</value>
<value>${password}</value>
</list>
</property>
</bean>
JAVA Spring Boot : How to access application.properties values in normal class
There's no "magic" way to inject values from a property file into a class that isn't a bean. You can define a static java.util.Properties
field in the class, load values from the file manually when the class is loading and then work with this field:
public final class AppUtils {
private static final Properties properties;
static {
properties = new Properties();
try {
ClassLoader classLoader = AppUtils.class.getClassLoader();
InputStream applicationPropertiesStream = classLoader.getResourceAsStream("application.properties");
applicationProperties.load(applicationPropertiesStream);
} catch (Exception e) {
// process the exception
}
}
}
How to inject property value using @Value into static fields
The only way is to use setter for this value
@Value("${value}")
public void setOutputPath(String outputPath) {
AClass.outputPath = outputPath;
}
However you should avoid doing this. Spring is not designed for static injections. Thus you should use another way to set this field at start of your application, e.g. constructor.
Anyway @Value annotation uses springs PropertyPlaceholder which is still resolved after static fields are initialized. Thus you won't have any advantages for this construction
How to read a property on a static field in a spring-boot application?
You can achieve this using the class Environment
from the package org.springframework.core.env
.
Example :
@SpringBootApplication
public class Example {
// autowire the Environment
@Autowired
private Environment environment;
private static String fatalCode;
public void someMethod(String errorNumber) {
fatalCode = environment.getProperty("app.directory.errorcode." + errorNumber);
}
public static void main(String[] args) {
SpringApplication.run(Example.class, args);
}
}
I hope this may help you.
Thanks :)
How to inject a property from properties file to a non-managed class in Spring?
You might do one of the following:
- Make the class a "normal" Java class where the regex is passed in via constructor or method parameter by the Spring managed class who uses it.
- Give the class a static field "regex" (with a default value perhaps) that gets set by a Spring bean via a setter on startup (
@PostConstruct
). - Give the class a static field "regex" (with a default value perhaps) that gets set using a
static
block in your class reading from the properties file (if it is available on the classpath!). - Make the class a "normal" Singleton (with default values perhaps) that gets initialized on Spring startup (https://www.baeldung.com/running-setup-logic-on-startup-in-spring)
Why I fail to use properties from application.properties file in Spring Boot?
Alternatively, you can do the following, the setter method will handle for the injection:
@Component
public class PostDao
{
public static String DATABASE_URL;
@Value("${url}")
public void setUrlStatic(String name){
PostDao.DATABASE_URL = name;
}
// And others..
}
Related Topics
Rsa Decryption Error - Illegalblocksizeexception: Data Must Not Be Longer Than 128 Bytes
Geting Http Status 400 - Required Multipartfile Parameter 'File' Is Not Present in Spring
Scheduling a Job With Spring Programmatically (With Fixedrate Set Dynamically)
How to Retrieve Mapping Table Name for an Entity in JPA At Runtime
How to Evaluate a Math Expression Given in String Form
How to Remove All Special Character in a String Except Dot and Comma
How to Solve Gradle Error Cannot Find Symbol
Java Program to Check for Similar Digits
How to Split a Huge Zip File into Multiple Volumes
Spring - Thymeleaf: Exception Processing Template
Spring-Boot @Autowired Interface (Crudrepository) in My Service Class => Null Pointer Exception
Saveastextfile() to Write the Final Rdd as Single Text File - Apache Spark
How to Generate a Unique and Short File Name in Java
Intellij Idea - Gradle: Execution Failed for Task ':Compilejava'
Spring Boot Required Request Part 'File' Is Not Present
How to Split Single Row into Multiple Rows in Spark Dataframe Using Java
How to Read a File, Reverse the Order, and Write Reverse Order
Using Loop to Accept Additional User Input Until User Enters a Value That Ends the Input