#Value In Spring MVC is not getting populated - spring

I am trying to populate an attribute using the #Value annotation in Spring MVC, and it is not getting populated.
I am trying to access the attribute using Struts2 JSP property. my use case looks like that:
public class TransferCreditsAction extends StudentAwareAction {
protected Log logger = LogFactory.getLog(this.getClass());
#Value( "${transfer.credit.url}" )
private String transferCreditUrl;
public void setStates( List<TranslatedValue> states ) {
this.states = states;
}
#Value( "${transfer.credit.url}" )
public String getTransferCreditUrl() {
return transferCreditUrl;
}
}
My property file looks like:
transfer.credit.url
I am accessing this attribute using JSP which looks like:
<s:property value='transferCreditUrl'/>"
I know for a fact that my JSP can access this field, because I tested it when I have this field set for a default value.
However, this field is not getting populated from my property file. I am using Spring 4.1.6
Any help is really appreciated.

Spring can only inject values in its own managed spring beans. That means your TransferCreditsAction should be a spring bean.
There are various ways to declare your TransferCreditsAction class as a spring bean, already answered elsewhere.

You haven't added whats on top of TransferCreditsAction class.
Values will be injected in a Bean Env.
There are many ways of Doing it
Assuming my property file contains
username=Ashish
app.name=Hello
1.
#Service
#PropertySource(value = { "classpath:sample.properties" })
public class PaloAltoSbiClientImpl implements PaloAltoSbiClient {
public static String username;
#Value("${username}")
public void setUrl(String data) {
username = data;
}
...
2.
#Service
public class PaloAltoSbiClientImpl implements PaloAltoSbiClient {
#Value("${username}")
public static String username;
...
3.
#Component
public class TokenHelper {
#Value("${app.name}")
private String APP_NAME;

Just give the properties file reference on top of the class in which you are trying to get.
#PropertySource(value = { "classpath:sample.properties" })

This issue was happening because I was missing <context:annotation-config/> in my applicationContext. Once I added it, it start working with no issues.

Related

Spring #Value not working in Spring Boot 2.5.5, getting null values

I am trying to inject some property values into variables by means of Spring #Value annotation but I get null values. I tried different configurations and triks but it doesn't work. Think is that before today everythink was working properly. I do not know what I changed in order to get things broken.
Here is my java class:
#Component
#ConditionalOnProperty(prefix = "studioghibli", name = "get")
public class StudioGhibliRestService {
#Value("${studioghibli.basepath}")
private static String BASE_PATH;
#Value("${studioghibli.path}")
private static String PATH;
#Value("${studioghibli.protocol:http}")
private static String PROTOCOL;
#Value("${studioghibli.host}")
private static String HOST;
private static String BASE_URI = PROTOCOL.concat("://").concat(HOST).concat(BASE_PATH).concat(PATH);
#Autowired
StudioGhibliRestConnector connector;
public List<StudioGhibliFilmDTO> findAllFilms() throws SipadContenziosoInternalException {
var response = connector.doGet(BASE_URI, null, null);
if (!response.getStatusCode().is2xxSuccessful() || !response.hasBody()) {
throw new SipadContenziosoInternalException(Errore.INTERNAL_REST_ERROR, "FindAll(), microservizio ".concat(BASE_URI), null);
}
return (List<StudioGhibliFilmDTO>) response.getBody();
}
}
As you can see, the class is annotated with #Component, that because I will need to use it as #Service layer in order to make a rest call in my business logic.
The class is also annotaded with conditional on property...
Here is a screenshot of the debug window at startup:
Since the PROTOCOL value is null, i get a null pointer exception immediately at start up.
Here is part of the application-dev.properties file:
studioghibli.get
studioghibli.protocol=https
studioghibli.host=ghibliapi.herokuapp.com
studioghibli.basepath=/
studioghibli.path=/films
First of all, #Value annotation does not work with static fields.
Secondly, fields with #Value annotation is processed when the instance of the class (a bean) is created by Spring, but static fields exist for a class (for any instance), so when the compiler is trying to define your static BASE_URI field other fields are not defined yet, so you get the NPE on startup.
So you might need a refactoring, try to inject values with the constructor like this:
#Component
#ConditionalOnProperty(prefix = "studioghibli", name = "get")
public class StudioGhibliRestService {
private final StudioGhibliRestConnector connector;
private final String baseUri;
public StudioGhibliRestService(StudioGhibliRestConnector connector,
#Value("${studioghibli.basepath}") String basePath,
#Value("${studioghibli.path}") String path,
#Value("${studioghibli.protocol:http}") String protocol,
#Value("${studioghibli.host}") String host) {
this.connector = connector;
this.baseUri = protocol.concat("://").concat(host).concat(basePath).concat(path);
}
// other code
}
Thanks, It works for me, I have to add some codes to my project. Then I check the spring core document in "#Value" section. Besides
When configuring a PropertySourcesPlaceholderConfigurer using
JavaConfig, the #Bean method must be static.
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}

Retrieve all key-value pairs from properties file in Spring Boot with a given prefix and suffix

I have been trying for sometime now. I want to read from the properties file and store as a hashmap.
Here is an example.
sample.properties
pref1.pref2.abc.suf = 1
pref1.pref2.def.suf = 2
...
...
Here is the Config class.
#ConfiguraionProperties
#PropertySource(value = "classpath:sample.properties")
public class Config{
#Autowired
private Environment env;
public HashMap<String, Integer> getAllProps(){
//TO-DO
}
}
I want to be able to return {"abc":1, "def":2};
I stumbled upon answers like using PropertySources, AbstractEnvironment etc., but still can't get my head around using it.
Thanks in advance!
The class
org.springframework.boot.actuate.endpoint.EnvironmentEndpoint
reads all configured properties and puts them in a Map.
This is used to return all properties and their values from a REST endpoint. See production ready endpoints
You can copy the 3 methods that build the Map with all properties from class EnvironmentEndpoint into your own. Then just iterate over the Map and select all properties by their key.
I have done that in one project, worked quite well.
its possible using spring boot #component, #PropertySource and #ConfigurationProperties
create a component like
#Component
#PropertySource(value = "classpath:filename.properties")
#ConfigurationProperties(prefix = "pref1")
public class Properties{
/**
*should be same in properties pref1.pref2.abc.suf = 1
*It will give u like abc.suf = 1 , def.suf = 2
*/
private Map<String,String> pref2;
//setter getter to use another place//
public Map<String, String> getPref2() {
return pref2;
}
public void setPref2(Map<String, String> pref2) {
this.pref2= pref2;
}
}
use in other class suing #autowired
public class PropertiesShow{
#Autowired
private Properties properties;
public void show(){
System.out.println(properties.getPref2());
}
}

how to load property file in to spring boot project with annotations?

I have written queries in property file. I want to read the property file in to one class with annotations in spring boot. How can i read it? And is there any better approach for writing queries in spring boot project?
If you add your properties in application.properties file, you can read them inside the spring boot classes like:
#Service
public class TwitterService {
private final String consumerKey;
private final String consumerKeySecret;
#Autowired
public TwitterService(#Value("${spring.social.twitter.appId}") String consumerKey, #Value("${spring.social.twitter.appSecret}") String consumerKeySecret) {
this.consumerKey = consumerKey;
this.consumerKeySecret = consumerKeySecret;
} ...
You can annotate fields in your components by #Value("${property.name}")
Else, you can use Properties Object in java.util package.
For example, i have a mode property, which values are dev or prod, i can use it in my beans as follow :
#Value("${mode:dev}")
private String mode;
The other approach is by using :
Properties pro = new Properties();
pro.load(this.getClass().getClassLoader().getResourceAsStream());
You can use #PropertySource to read the properties from a file and then pass them to a bean. If you have a file called "queries.properties" that has a property like:
query1: select 1 from foo
Then your config might look like:
#PropertySource("classpath:queries.properties")
#Configuration
public class MyConfig {
#Bean
public DbBean dbBean(#Value("${queries.query1}") String query) {
return new DbBean(query);
}
}

How to bind a string array of properties in Spring?

I have the following in my application.properties file
some.server.url[0]=http://url
some.server.url[1]=http://otherUrl
How do I refer to the array of properties using the #Value anotation inside a #Bean method?
I am using Java 6 with Tomcat 7 and Spring boot 1.4
I was also having the same problem as you mentioned and it seems using index form on application.properties was not working for me either.
To solve the problem I did something like below
some.server.url = url1, url2
Then to get the those properties I simply use #Value
#Value("${some.server.url}")
private String[] urls ;
Spring automatically splits the String with comma and return you an Array. AFAIK this was introduced in Spring 4+
If you don't want comma (,) as seperator you have to use SpEL like below.
#Value("#{'${some.server.url}'.split(',')}")
private List<String> urls;
where split() accepts the seperator
You can use a collection.
#Value("${some.server.url}")
private List<String> urls;
You can also use a configuration class and inject the bean into your other class:
#Component
#ConfigurationProperties("some.server")
public class SomeConfiguration {
private List<String> url;
public List<String> getUrl() {
return url;
}
public void setUrl(List<String> url) {
this.url = url;
}
}
Follow these steps
1)
#Value("${some.server.url}")
private List urls;
2)
#ConfigurationProperties("some.server")
public class SomeConfiguration {
3)
You should have getter and setter for instance variable 'urls'

Error while using parameter in #Scheduled in a spring 4.1 application

I have Spring 4.1 Application. I am trying to schedule based on value from property file. I have read this post. But I do not want the following way of EL inside #Scheduled
#Scheduled(fixedDelayString = "${my.fixed.delay.prop}")
public void readLog() {
...
}
Here is my class.
public class MyService {
#Value("${timerInMilliSeconds: 60000}")
private long timerinMilliSeconds;
public myService(){
}
#Scheduled(fixedRate = timerinMilliSeconds)
public void myTimer() {
//do stuff
}
}
I get this error.
The value for annotation attribute Scheduled.fixedRate must be a constant
expression
You can't do that; it's a limitation of the way annotations work - Strings in annotations have to be constants (they are stored in the class and can't be different for each instance).
By the way ${my.fixed.delay.prop} is not "EL", it's a property placeholder.

Resources