Spring: How to access a txt file located outside the jar? - spring

Currently, I am passing the environment specfic configs in a properties file outside the jar using -Dspring.config.location=/apps/conf/application-dev.properties. I also have properties file included in the jar named application.properties which has configs that don't change often. There's one config called nameFile:
nameFile=classpath:config/nameList.txt
And the actual nameList.txt is included in the jar under spring-app/src/main/resources/config/nameList.txt but I want to move the nameList.txt outside the jar.
What I've tried:
Changing it to nameFile =${auth.nameList} and added this to /apps/conf/application-dev.properties like:
auth.nameList=classpath:/apps/conf/nameList.txt
And I moved the nameList.txt file from the jar to /apps/conf/ location but the Spring application fails because it cannot find the txt file. How do I fix this? I want to move the nameList.txt to outside the jar.
Removed classpath:
auth.nameList=/apps/conf/nameList.txt
No luck!

When you provide a path, classpath will "tell" the JVM that the location is within the jar/war file. If you have the resource you need in an external location, you will need file instead.
auth.nameList=file:/apps/conf/nameList.txt

Related

spring boot loading property file from custom folder

I need to load a property file from src/main/resources/config folder. The loading part is written in a common dependency project where we dont have any control. We are just passing the file name expressed through a dependency. The code snippet in the dependent jar is like below, the standard resource loading.
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(propertyFileName);
Spring will always look for recources under recources folder directly, in this case its unable to load the file as its in the custom folder and its not under classpath.
How do we explicitly set the custom folder as additional classpath folder?
With maven we could do something like below which works fine. Is there any OOTB way to achieve this with annotation in spring boot?
`<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/resources/config</directory>
</resource>
</resources>`
Updated
`// This works if config.properties is directly under resource folder
// What if config.properties is under resources/config folder.
// Dont say to pass argument as /config/config.properties, there are some other limitations.
// So in that case with the same approach, config should come under classpath, so that the below
// method will work always when the property name is passed.
// As mentioned earlier, we can use maven resource settings to achieve this.
// The question here is, is there any way to explicitely advise spring to load property from this folder.
// I have seen something like loader.path config, not sure that helps!
InputStream stream = SpringBootStarter.class.getResourceAsStream("/config.properties");`
Before answering, when you say: Spring will always look for recources under recources folder directly, in this case its unable to load the file as its in the custom folder and its not under classpath., this is not correct.
Spring can look anywhere on your system. Here is how you can load different properties file with Spring and Spring boot:
#PropertySource("classpath:config/common.properties") => Will look under the class path for a file located under the config folder, at the root of your classpath.
#PropertySource("file:/config/common.properties") => Will look for the file common.properties at the root of your filesystem, here under /config/common.properties.
Now, there is the question of "what is the classpath", it seems like it is worth more explanation.
The classpath is for the JVM what the filesystem is for your OS. When you execute some java code (.jar file for instance), the JVM stores all the files you specify. You can specify files when executing java -classpath /a/shared/folder,/a/dependency/app.jar,myApp.jar MainClass. (See this for some others ways: https://javarevisited.blogspot.com/2012/10/5-ways-to-add-multiple-jar-to-classpath-java.html).
Quite often, what happens for developers (before we use Spring) was this:
We develop our application, and use maven for managing the dependencies
We execute our app with the IDE, everything works just as fine, life is wonderful
We are ready to go live (in production). We generate the famous myApp.jar and try executing the application java -jar myApp.jar and... Nothing works. You have issues with java (I assume you setup the main-class in the Manifest...) and you get something like Caused by: java.lang.ClassNotFoundException: my.dependency.OtherClass...
Finally, you realize life is hard and you are not ready to go live right now. You need to have something you can execute easily.
One possible solution to this, to avoid having classpath issues is to put everything in your JAR (called in spring-boot the FAT jar) and you use java -jar myApp.jar and it is working fine.
By default, when you generate a maven project, automatically you have some folders included like:
src/main/java => your java files and packages
src/main/resources => your config files (like .properties)
src/test/java => Your java test files
src/test/resources => the resources handy for your tests
When you generate your jar (more or less every configuration you added to your maven project, but let's say it is okay), what happens is the compiler takes all the folders and files under src/main/java and src/main/resources and put them at the root of your jar. (Don't hesitate to have a look inside your jar files. This is just a Zip, you can open it, browse it, and see for yourself).
With that said, when you say How do we explicitly set the custom folder as additional classpath folder?, and you talk about a custom folder located under src/main/resources, then when you generate your Jar, the custom folder will be in jar, and therefor, in your classpath.
If you still have troubles, this actions will help you:
Unzip your jar files and check what is inside. If you don't see any config/ folder in it, maybe your Jar generation is wrong
Try using #PropertySource(...) to load properties file, in your classpath and in your filesystem, to see how it works and what you achieve
Have also a look to this:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
Don't hesitate to migrate more and more of your old code to Spring-boot, will be a lot easier for you.

Spring boot external properties not working

My project structure looks like as attached file. Even though I have profile specific properties, I would like to run my app with external properties file i.e., outside of jar file.
I tried with following command:
java -jar test_service.jar --spring.config.location=file:///C:/external_props/test.properties
But its taking application-default.properties file.
from log file:
No active profile set, falling back to default profiles: default
Why it is not taking external properties file ?
When you pass --spring.config.location command line argument SpringBoot won't consider application-*.properties files in src/main/resources directory. The filename you mentioned for --spring.config.location is taken as base filename, in your case test. So, it will only load test.properties file from that path you provided as default profile.
If you want to enable certain profile, say prod, you need to create file C:/external_props/application-prod.properties and enable prod profile using --spring.profiles.active=prod.
Spring will automatically look for some property file in a specific location.
From where you execute the jar file, Spring will look in that directory for a property file called application.properties
An other way is to put a config directory in the directory you execute the jar from and put the application properties in there.
There is one more option and that is the -Dspring.profiles.active={profiles} parameter.
Spring will then look in the directory or config directory to application-{profile}.properties
Reference:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Also i think you use the
--spring.config.location=file:///C:/external_props/test.properties
is not used correctly for a windows based file path.
Windows uses the \ instead of the /.

Wrapping a text file in a war and in a jar format

I have a springboot program that reads from a text file present inside the project. I use eclipse IDE. I want to share the project. While packaging the project in war format the text file was missing. Can someone tell me how do I package it so as to have the text file inside the package ?
I want to know the steps for both war and jar packaging which will include the text file in them.
This will let the user who unpacks it finds the text file and it can be used by the springboot service directly.
Thanks
Put any resources (files) used at runtime in src/main/resources. They should be available in all packages.

Could not find fetcher.properties on classpath

I am working to implement RSS feed using the spring integration as mentioned in the article http://comdynamics.net/blog/295/spring-integration-rss-feed-reader/. However, when I run the application I am getting the following error:
Could not find fetcher.properties on classpath
Can you point me in the right direction?
Can you verify that you have the folder that contains this property file in the classpath of the project? You would have to look at .classpath file to verify this.
Ideally you would want to keep this file in a config folder and must be added to the classpath just like your source folder.
create an empty file named fetcher.properties on classpath. You don't have to add any entry to it.That will solve the problem

Shared Library websphere

I want to create share library in Websphere Application Server. I have abc.jar inside abc folder. I want to know the difference between specifying c:\abc Vs c:\abc\abc.jar in the classpath
If c:\abc contains other jars, they will also be added to the classpath. If c:\abc contains non-jar files (e.g., c:\abc\test.properties), then c:\abc will be added to the classpath itself, which allows getResource calls for the directory to work (e.g., ClassLoader.getResource("test.properties") will find the file).

Resources