Loading properties file WebSphere Liberty - websphere

I have a simple application that uses Spring to load a properties file from the classpath. When deploying this application to WebSphere Liberty 8.5.5 it results in FileNotFoundException.
nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/myprops.properties]
Here is my spring #Configuration class:
#Configuration
#Profile("dev")
#PropertySource("classpath:/myprops.properties")
public class AppConfigDev extends AppConfig {
...
}
I am wondering where in the Liberty directory structure should my properties file reside?

The use of prefix classpath: in your annotation signifies that the given property file would be picked up from WebSphere's, well, classpath, via a ClassLoader.getResources(...) call.
Ref: http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/resources.html#resources-classpath-wildcards
You will need to create a jar of all your properties files for Websphere Liberty to be able to load them.
Ref:
1. https://developer.ibm.com/answers/questions/13384/websphere-liberty-8-5-setting-java-classpath.html
2. Websphere Liberty 8.5: Setting Java classpath

You can set the name/directory of your files in a file named jvm.options and put it in your ${server.config.dir}/jvm.options
Specific example :
In the file: ${server.config.dir}/jvm.options
Add the following line: -DAPP_ENV=PROD
Access the value with: System.getProperty("APP_ENV"); -> PROD

Related

Give external path in #Value Spring annotation and Resource

In spring boot application how do I give an external windows path using #Value Spring annotation and Resource
The below example works fine that look into resources folder but I want to give the path outside of application like c:\data\sample2.csv
#Value("classPath:/sample2.csv")
private Resource inputResource;
...
#Bean
public FlatFileItemReader<Employee> reader() {
FlatFileItemReader<Employee> itemReader = new FlatFileItemReader<Employee>();
itemReader.setLineMapper(lineMapper());
itemReader.setLinesToSkip(1);
itemReader.setResource(inputResource);
and if I want to get the value from properties file in annotaion, whats the format to put the path in windows?
i tried these, none of them worked:
in code
#Value("${inputfile}")
in properties file:
inputfile="C:\Users\termine\dev\sample2.csv"
inputfile="\\C:\\Users\\termine\\dev\\sample2.csv"
inputfile="C:/Users/termine/dev/sample2.csv"
inputfile="file:\\C:\Users\termine\dev\sample2.csv"
inputfile="file://C://Users//termine///dev//sample2.csv"
When you use classpath spring will try to search with the classpath even if you provide the outside file path.
so instead of using classpath: you can use file:
Ex.
#Value("file:/sample2.csv") //provide full file path if any
Use the key spring.config.location in properties to set the config location. Spring-boot will by default load properties from the locations, with precedence like below :
A /config subdir of the current directory.
The current directory
A classpath /config package
The classpath root
and apart from this when you start the jar or in application.properties you can provide the location of the config file like :
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
You can serve static files from the local disk, by making the resource(s) "sample2.csv" as a static resource. An easy way to do this is by adding spring.resources.static-locations configuration to your applicaiton.properties file. Example:
spring.resources.static-locations=file:///C:/Temp/whatever/path/sample2.csv",classpath:/static-files, classpath:/more-static-resource
When I did this in one of the projects, I was able to access the file form the browser using localhost:8080/sample2.csv.

How can I load additional properties file in a spring boot application packaged as a war?

I have a standard springboot web app. I want to load properties file that's not in the classpath. application.properties is in the classpath and is being read correctly.
I don't have an issue when I'm building a jar. I just put the .properties alongside the jar and it works. But when I package a war, I couldn't get the application to read the properties file .
You put the properties file parallel to application.properties file and load it in a class like this:
#PropertySource("classpath:foo.properties")
public class My class {
#Value( "${some.property}" )
String myProp;
}
You can using ClassPathResource. given Class for loading resources.
This is sample code for you
ClassPathResource resource = new ClassPathResource("/application/context/blabla.yml");
InputStream inputStream = resource.getInputStream();
File file = resource.getFile();
// using inputStream or file
ClassPathResource
You can use spring application.properties to have spring profiles and use the spring profiles to define separate properties for each environment as you like.You can even separate out the spring profiles in to different files like appication-dev.properties etc so that you can have each spring profile in different files.
You can read the properties by using #Configuration annotation :
#Configuration
#EnableConfigurationProperties(TestProperties.class)
public class MySampleConfiguration {
}
Here TestProperties.class is used to map the values from the property file or yaml .
Reference in detail : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Read both internal and external property file using Spring boot

I have a spring boot application jar
#SpringBootApplication
#EnableScheduling
#PropertySource({"classpath:1.properties","classpath:2.properties"})
public class MyClass {
//My class
}
1.properties is in src/main/resources
2.properties is in server location project location
| MyClass.jar
| config
| 2.properties
But I am getting file not found for 2.properties when starting the application.Please let me know what I could be missing here.
Like mentioned in the comment, your 2.properties file is not under your classpath. You can only use classpath if your file really exists in your jar or war.
To get the 2.properties you should use the command file: instead of classpath:.
#PropertySource("classpath:1.properties","file:${application_home}2.properties")
I am not quite sure if its still necessary to have an OS environment variable or a system property to set the path to your property file. In this case I named it application_home.

Spring boot on Tomcat with external configuration

I can't find an answer to this question on stackoverflow hence im asking here so I could get some ideas.
I have a Spring Boot application that I have deployed as a war package on Tomcat 8. I followed this guide Create a deployable war file which seems to work just fine.
However the issue I am currently having is being able to externalize the configuration so I can manage the configuration as puppet templates.
In the project what I have is,
src/main/resources
-- config/application.yml
-- config/application.dev.yml
-- config/application.prod.yml
-- logback-spring.yml
So how can I possibly load config/application.dev.yml and config/application.prod.yml externally and still keep config/application.yml ? (contains default properties including spring.application.name)
I have read that the configuration is load in this order,
A /config subdirectory of the current directory.
The current directory
A classpath /config package
The classpath root
Hence I tried to load the configuration files from /opt/apache-tomcat/lib to no avail.
What worked so far
Loading via export CATALINA_OPTS="-Dspring.config.location=/opt/apache-tomcat/lib/application.dev.yml"
however what I would like to know is,
Find out why loading via /opt/apache-tomcat/lib classpath doesn't work.
And is there a better method to achieve this ?
You are correct about load order. According to Spring boot documentation
SpringApplication will load properties from application.properties files in the following locations and add them to the Spring Environment:
A /config subdirectory of the current directory.
The current directory
A classpath /config package
The classpath root
The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).
[Note]
You can also use YAML ('.yml') files as an alternative to '.properties'.
This means that if you place your application.yml file to /opt/apache-tomcat/lib or /opt/apache-tomcat/lib/config it will get loaded.
Find out why loading via /opt/apache-tomcat/lib classpath doesn't work.
However, if you place application.dev.yml to that path, it will not be loaded because application.dev.yml is not filename Spring is looking for. If you want Spring to read that file as well, you need to give it as option
--spring.config.name=application.dev or -Dspring.config.name=application.dev.
But I do not suggest this method.
And is there a better method to achieve this ?
Yes. Use Spring profile-specific properties. You can rename your files from application.dev.yml to application-dev.yml, and give -Dspring.profiles.active=dev option. Spring will read both application-dev.yml and application.yml files, and profile specific configuration will overwrite default configuration.
I would suggest adding -Dspring.profiles.active=dev (or prod) to CATALINA_OPTS on each corresponding server/tomcat instance.
I have finally simplified solution for reading custom properties from external location i.e outside of the spring boot project. Please refer to below steps.
Note: This Solution created and executed windows.Few commands and folders naming convention may vary if you are deploying application on other operating system like Linux..etc.
1. Create a folder in suitable drive.
eg: D:/boot-ext-config
2. Create a .properties file in above created folder with relevant property key/values and name it as you wish.I created dev.properties for testing purpose.
eg :D:/boot-ext-config/dev.properties
sample values:
dev.hostname=www.example.com
3. Create a java class in your application as below
------------------------------------------------------
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
#PropertySource("classpath:dev.properties")
#ConfigurationProperties("dev")
public class ConfigProperties {
private String hostname;
//setters and getters
}
--------------------------------------------
4. Add #EnableConfigurationProperties(ConfigProperties.class) to SpringBootApplication as below
--------------------------------------------
#SpringBootApplication
#EnableConfigurationProperties(ConfigProperties.class)
public class RestClientApplication {
public static void main(String[] args) {
SpringApplication.run(RestClientApplication.class, args);
}
}
---------------------------------------------------------
5. In Controller classes we can inject the instance using #Autowired and fetch properties
#Autowired
private ConfigProperties configProperties;
and access properties using getter method
System.out.println("**********hostName******+configProperties.getHostName());
Build your spring boot maven project and run the below command to start application.
-> set SPRING_CONFIG_LOCATION=<path to your properties file>
->java -jar app-name.jar

#PropertySource cannot find classpath:

I am getting the following error:
Caused by: java.io.FileNotFoundException: class path resource [request-
ws/src/main/resources/application.yml] cannot be opened because it does
not exist
Class with the issue:
#Configuration
#PropertySource("classpath:request-ws/src/main/resources/application.yml")
public class RequestDataSource {
Now I am trying to access the yml file in from a different module. The module name is request-ws. The goal to to create two data sources. Any advice would be greatly appreciated.
The classpath for application.yml should be under: src/main/resources
according to: classpath:request-ws/src/main/resources/application.yml
you obviously don't have that yml file under:
src/main/resources/request-ws/src/main/resources/application.yml
Try to create your custom folder under: src/main/resources
Since my project is broken down into modules when the war file is made my application.yml file ends up in WEB-INF Put this on on your class:
#Configuration
#EnableConfigurationProperties
#PropertySource("classpath:WEB-INF/classes/application.yml")
public class DataSourceConfig {

Resources