Spring boot: external properties file an PropertySource - spring

I am developing a spring boot application with gradle.
I would love to tell spring where to read .properties files with a parameter. Since I am still running it via gradle, I have added this to my build.gradle
bootRun {
args = [
"--spring.config.additional-location=file:/path/to/my/props/folder/,file:/path/to/another/props/folder/"
]
}
into /path/to/my/props/folder/ I have created a file remote-connection.properties:
### remote-connection
remote.ip.address=127.0.0.1
remote.ip.port=5001
and I am trying to load those props like this
#RestController
#PropertySource("file:remote-connection.properties")
public class MyController {
#Value("${remote.ip.address}")
private String remoteIpAddress;
}
When i run ./gradlew bootRun i have the following error
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [my.package.MyApplication]; nested exception is java.io.FileNotFoundException: remote-connection.properties (No such file or directory)
(I have also tried #PropertySource("classpath:remote-connection.properties") and #PropertySource("remote-connection.properties"))
It works flawlessly if I place remote-connection.properties into src/main/resources, but I want that config file to be outside the resulting jar, being able to run it with
java -jar my-application.jar --spring.config.additional-location=file:/path/to/my/props/folder/,file:/path/to/another/props/folder/
What am I missing?
Thanks in advance.

Answering my own question.
Following this guide https://mkyong.com/spring/spring-propertysources-example/ I have changed my run args to
bootRun {
args = [
"--my.props.folder=/path/to/my/props/folder",
"--my.other.props.folder=/path/to/another/props/folder",
]
}
and loading props like this
#RestController
#PropertySource("file:${my.props.folder}/remote-connection.properties")
#PropertySource("file:${my.other.props.folder}/some-more.properties")
public class MyController {
#Value("${remote.ip.address}")
private String remoteIpAddress;
}
This way, it works!!

Related

Spring Batch is looking for source files during deployment

I am developing Spring batch application on Spring Boot. Batch process is based on fire and forget, which means migration process is triggered by Http GET method and doesn't wait for result. There are 6 (six) csv files which containes migration data and these data must be processed and transferred to DB. Source files path is provided by application.yml file. Batch config (template) looks like as follows:
#Configuration
public class BeginCureBtachConfig {
#Value("$batch-files.begincure-source")
private String dataSourceFilePath;
#Autowired
IteamReader<BeginCure> itemReader;
#Autowired
ItemProcessor<BeginCure, BeginCure> itemProcessor;
#Bean Job beginCureJob(JobBuilderFactory jbFactory, StepBuilderDactory stp, ItemWriter<BeginCure> begnCure {
//// code goes here
}
#Bean
public FlatFileItemReader<BeginCure> beginCureItemReader() {
FlatFileItemReader<BeginCure> ffReader = new FlatFileItemReader<>();
ffReader.setResource(new FileSystemResource(dataSourceFilePath));
ffReader.setLineMapper(lineMapper());
return ffReader;
}
#Bean
public LineMapper<BeginCure> lineMapper () {
//..
}
}
The problem is when project is deployed on openshift, batch looks for files even migratin is not triggered.
In the code, I think this part of code giving some error ffReader.setResource(new FileSystemResource(dataSourceFilePath));
Is there any workaround or solution? Did anybody have this kind of problem?
Thank you in advance^^

Share application.properties files in different project

Below showing the project structure
Core Project
|-config project
|
|-Service project
After building the core project we get Service.jar file.
While running the service.jar am passing spring.config.additional.location as command line argument.
java -jar Service-1.0.jar --spring.config.additional-location=C:/Users/Administrator/Desktop/Springboot/
above spring.config.additional.location path having application.property file and some xml files.
I can able to read application property file in service project ,following logic
Application.propertes
external.config=C:/Users/Administrator/Desktop/Springboot/config/
Mian Class
#ImportResource(locations = {
"${external.config}"+"/spring/service-config.xml",
"${external.config}"+"/spring/datasource-config.xml"
})
public class ServiceMain {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ServiceMain.class)
.build()
.run(args);
for (String name : applicationContext.getBeanDefinitionNames()) {
}
}
}
Similar kind of logic applied in config project is given below,its not working
#Configuration
public class ConfigurationFactory
{
#Value("${external.config}")
public String extConfPath;
public String REQ_CONF = extConfPath+"/Configuration.xml";
public static final String FILTER_XML_CONF = extConfPath+"/DocFilter.xml";
}
Is there any better way to do this? How can i read external application.properties in config project
Do we have any better way to do this in spring boot
As you are cleary developing a distributed web system the best practice is to used externalised configuration used by your different services allowing you to update settings without redeployment. Take a look at Spring Cloud Config

Spring boot. Reading MANIFEST.MF using jcabi manifests

I'm trying to add AppName and Version to actuator's /info endpoint using jcabi-manifests https://github.com/jcabi/jcabi-manifests library. Code snippet is below:
#Component
public class VersionInfoContributor implements InfoContributor {
#Override
public void contribute(Info.Builder builder) {
String artifactName = Manifests.read("Artifact-Name");
builder.withDetail("Artifact-Name", artifactName);
}
Artifact-Name is set in build.gradle file next way:
jar {
manifest {
attributes("Artifact-Name": "TestActuator")
}
}
The attribute IS present in META-INF/MANIFEST.MF file inside result .jar file but when trying to access /info endpoint getting error:
Attribute 'Artifact-Name' not found in MANIFEST.MF file(s) among 46 other attribute(s)
I know there is BuildProperties bean in Spring-boot actuator but won't like idea to expose all these fields - AppName and Version more than enough.

How to make externalized properties file available to spring boot integration tests?

I am developing an application using Spring Boot. I have an externalized properties file on file system. Its location is stored in an environment variable as below--
export props=file://Path-to-file-on-filesystem/file.properties
Properties from this file are loaded on classpath and are made available to application like below--
List<String> argList = new ArrayList<>();
String properties = System.getenv().get("props");
try (InputStream is = BinaryFileReaderImpl.getInstance().getResourceAsStream(properties)) {
if (is != null) {
Properties props = new Properties();
props.load(is);
for(String prop : props.stringPropertyNames()) {
argList.add("--" + prop + "=" + props.getProperty(prop));
}
}
} catch(Exception e) {
//exception handling
}
This argList is passed to SpringBootApplication when it starts like below--
SpringApplication.run(MainApplication.class, argList);
I can access all the properties using ${prop.name}
However, I do not have access to these properties when I run JUnit Integration Tests. All my DB properties are in this externalized properties file. I do not want to keep this file anywhere in the application eg. src/main/resources
Is there any way I can load these properties in spring's test context?
I could finally read the externalized Properties file using #PropertySource on linux machine. Could not get it working on Windows instance though.
Changes done are as below-
export props=/path-to-file
Note that file:// and actual file name has been removed from environment variable.
#Configuration
#PropertySource({"file:${props}/file-test.properties", "classpath:some_other_file.properties"})
public class TestConfiguration {
}
Keep this configuration class in individual projects' src/test/java folder. Thank you Joe Chiavaroli for your comment above.

Don't have access to Spring boot controller, but have access to index.html

I have a Spring Boot project, what I deployed on remote server. When I call http://109.206.178.66:8080/proxynator/ - I can see an index.html, but when I call rest controller by url http://109.206.178.66:8080/proxynator/countries - I have an error 404 whith
Description: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
It's strangely, because when I start this project on my local machine, all working right. Project structure is:
Line from catalina.out file:
SEVERE [http-nio-8080-exec-19] org.apache.tomcat.util.descriptor.web.WebXmlParser.parseWebXml Parse error in application web.xml file at [file:/opt/tomcat/webapps/proxynator/WEB-INF/web.
My controller:
#RestController
class MainController(val proxyRepo: ProxyRepo, val countryRepo:
CountryRepo) {
#GetMapping("/countries")
fun findCountries(): List<Country> = countryRepo.findAll()
#GetMapping("/proxies")
#ResponseBody
fun findProxies(#RequestParam countryid: Int): List<Proxy> =
proxyRepo.findAllByCountryid(countryid)
}
UPD
I added configuration class on the root package
#Configuration
open class RestConfiguration {
#Bean
open fun mainController():MainController
= MainController()
}
But it does not working. I don't understand, why I can see index.html by irl http://109.206.178.66:8080/proxynator/, but can't get access to my controllers. When I package my project I have some files:
Any advice?
your api access url is wrong access using http://109.206.178.66:8080/countries this is the correct path for your rest mapping, not http://109.206.178.66:8080/proxynator/countries
To solve this problem I was edit my Application class.
#SpringBootApplication
#EnableAutoConfiguration
open class Application: SpringBootServletInitializer(){
#Override
override fun configure(application: SpringApplicationBuilder?):
SpringApplicationBuilder {
return super.configure(application)
}
}
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
I was override configure method, and all is working!
Hope it will save time for anybody!

Resources