Get Maven basedir from a properties file in a SpringBoot project - java

The Maven project I inherited has some resource files used in JUnits.
Those files are referred in a properties file as absolute paths.
Let's assume the Maven project is under myproject, where the main pom.xml resides.
A config.properties file has:
keystore.file=C:/Users/tom/myproject/web/src/test/resources/myfile.jks
I want to refer to that resource from a relative path of the Maven project.
So I have been trying something like:
keystore.file=${project.basedir}/web/src/test/resources/myfile.jks
I have been reading about resource filtering which is referred in this question.
The project uses SpringBoot, and when running a JUnit, complains with:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'project.basedir' in string value "${project.basedir}/web/src/test/resources/myfile.jks"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)

After trying different things, found a solution to my problem.
Adding this line in Spring Boot application.properties:
maven.basedir=#project.basedir#
And then in config.properties:
keystore.file=${maven.basedir}/web/src/test/resources/myfile.jks
Makes it work.
Check: Spring Boot automatic Property Expansion Using Maven.

Related

How to reference resource file in java maven project running in docker container

I am trying to run a java maven (spring boot) project in a docker container to access the zoho api.
For authentication I need a file zoho-oauthtokens.properties which is located in src/main/resources and which I reference from another property file called oauth_configuration.properties like this:
oauth_tokens_file_path=src/main/resources/zoho-oauthtokens.properties
As long as I run the application in eclipse as spring application everything works fine but as soon as I run it in a docker container I get:
com.zoho.crm.library.exception.ZCRMException com.zoho.oauth.common.ZohoOAuthException. Caused by : com.zoho.oauth.common.ZohoOAuthException. Caused by : java.io.FileNotFoundException: src/main/resources/zoho-oauthtokens.properties (No such file or directory)
So how do I reference the resource file correctly that it will also be found when I run it i a docker container? Any idea?
I tried:
oauth_tokens_file_path=src/main/resources/zoho-oauthtokens.properties
oauth_tokens_file_path=classpath:/zoho-oauthtokens.properties
oauth_tokens_file_path=/zoho-oauthtokens.properties
oauth_tokens_file_path=zoho-oauthtokens.properties
and also after placing it in the root folder of my project:
oauth_tokens_file_path=/zoho-oauthtokens.properties
oauth_tokens_file_path=zoho-oauthtokens.properties
Best, Nils
EDIT:
It tried more options:
../../../zoho-oauthtokens.properties
./zoho-oauthtokens.properties
/BOOT-INF/classes/zoho-oauthtokens.properties
BOOT-INF/classes/zoho-oauthtokens.properties
Also I have inspected the jar file after the maven build. This is where the relevant files are located:
BOOT-INF/classes/de/xxx/xxx/Application.class
BOOT-INF/classes/zoho-oauthtokens.properties
BOOT-INF/classes/oauth_configuration.properties
Have you tried
oauth_tokens_file_path=classpath*:zoho-oauthtokens.properties
Since it is in a different jar. Again I am not sure how zoho-oauthtokens.properties is loaded in code. Just worth a try.

META-INF/spring.factories file missing from Spring Boot application

I am fairly new to Spring and Spring Boot, and was asked to work on a legacy Spring Boot project. I am supposed to include in the project some FailureAnalyzers provided by Spring Boot. According to tutorials I came across (like here), all that needs to be done is registering the several FailureAnalyzer classes in the META-INF/spring.factories file.
But when I build the project (using Maven), I don't see a spring.factories file inside the target/META-INF directory. I tried adding one myself but it doesn't seem to be read by the project. What am I missing? What should I be doing to register these FailureAnalyzers?
In case you need it, the spring.factories file looks like this:
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.AbstractInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer
I think you have mistaken the location of spring.factories file. This file will not be present in the project resources folder. Go to Maven dependencies and look into each Jar META-INF file and you will find spring.factories file in most of the jars.

Spring not able to find classpath resource with #PropertySource

I am using #PropertySource in my datasource configuration file to get property files located on classpath. Below is my project structure.
I believe I can do it in two ways:
By creating a package in src folder and add them there. As src folder is already included in the classpath in eclipse, following should work.
#PropertySources({
#PropertySource("classpath: com/spring/property/general.properties"),
#PropertySource("classpath: com/spring/property/hibernate.properties")
})
Second way is to create a resources folder and add it to the classpath and following should work
#PropertySources({
#PropertySource("classpath: general.properties"),
#PropertySource("classpath: hibernate.properties")
})
In my case neither of the two is working. Being an intermediate java developer this still confuses me. Can anybody guide me in the right direction. And also how we can configure classpath resources for Spring in a production environment.
EDIT:
I have changed my project structure to include properties file in src/java/resources and I can see the resources folder in build path. Still .properties are not found by spring.
For anybody facing problem with usign .properties files in Spring 4+, look at the thread below to match your setup with that of OP. Setup is all good except for a whitespace in configuration.
Not able to inject .properties file into Spring MVC 4.3 using #PropertySource

ClassPathXmlApplicationContext error, Spring framework

I have encountered a problem when it comes to the Springs framework, which leads to that the communication between the server and the database does not work.
The project that I created is a Spring project, then refactored to Maven.
At this line in the code:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("projectName/spring.xml");
I get this error:
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [projectName/spring.xml]; nested exception is java.io.FileNotFoundException: class path resource [projectName/spring.xml] cannot be opened because it does not exist
But it does exist. And I've tried solutions for this problem such as writing ClassPathXmlApplicationContext("spring.xml") instead. This doesn't help however, since then Spring automatically looks in the folder src/main/resources. This doesn't work for me since my project structure doesn't allow me to add this folder and put a XML-file in it. If I try to create this folder, then it is automatically put inside the Java-resources folder, and Eclipse won't allow me to put XML in there.
This is how my project looks:
enter image description here
Is there a way for me to declare where Spring should look for this spring.xml-file?
The ClassPathXmlApplicationContext assumes that the file is on your classpath (Javy describes how to do load a resource from your classpath).
If you want to load the configuration from your file system (as you're doing), you might want to consider using FileSystemXmlApplicationContext instead. Using this mechanism to load your context you can pass a file system location as you're currently doing.
new ClassPathXmlApplicationContext(this.getClass().getResource("/spring.xml").getPath())
try the code above
hope that helped
Spring doesn't look at the src/main/resources, it looks at the classpath.
If you write projectName/spring.xml you need to have this file in bin/projectName/spring.xml or build/projectName/spring.xml. Where bin or build your build folder.
If you build a jar, this file should be in the jar!projectName/spring.xml.
For the web-application this file should be in the WEB-INF/classes/projectName/spring.xml.
If you add src/main/resources at the class path, then content of this folder will be in the build folder. Maven adds src/main/resources at the class path automatically.
Sometimes you should rebuild (clean) your project in the IDE to have such files in the build folder.
Use "FileSystemXmlApplicationContext" as
ApplicationContext context = new FileSystemXmlApplicationContext("spring.xml");

Loading a jar's context.xml from classpath

I'm trying to load an application context which is inside a jar as a plugin. I use this to load the context:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:**my-context.xml");
When I load the jar through pom.xml, it works fine.
Then I add it directly in the classpath using eclipse instead of maven to avoid to compile every time (ultimate goal is the shared lib folder in tomcat, not working too). Now spring is unable to find it and return a default context (no exception)
I checked that it's correctly insert in the classpath using:
InputStream in1 = this.getClass().getClassLoader().getResourceAsStream("my-context.xml");
It works.
I checked logs. Using the pom.xml, spring is correctly searching in the jar
Searching directory [...target\classes\META-INF\maven\x.y.z] for files matching pattern [...\x.y.z/target/classes/**/my-context.xml]
Searching directory [...ehealth.poc.module1] for files matching pattern [D:/JRB/Projects/Vivates/workspaces/default/extcom/ehealth.poc.module1/target/classes/**/ecm-context.xml]
...
Resolved location pattern [classpath*:**/my-context.xml] to resources [file [...\target\classes\my-context.xml]]
Loading XML bean definitions from file [...\target\classes\my-context.xml]
...
In the second case, nothing in the log about my jar.
Why spring does not have the same behavior when I use maven or directly the classpath? I maven doing something else than simple adding dependencies location in the classpath?
Finally, we found the solution on eclipse.
The problem comes from the ** in
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:**my-context.xml");
It looks like ** doesn't scan the .jar files. Setting the direct path is working :
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:my-context.xml");

Categories