How to pass property file from spring config server to YAML reader? - java

I am currently moving my property files to spring-config-server. I have created a config server and it is running on my localhost(http://localhost:8080).
In my application I can able to access the properties from config server for different environments like local and dev. But in my code I was reading one of the property file by Yaml reader for other mappings.
The following the code for reader:
Yaml yaml = new Yaml();
InputStream inputStream = clazz
.getClassLoader()
.getResourceAsStream("application-myprops.yml");
MyPropsYaml obj = yaml.loadAs(inputStream, MyPropsYaml.class);
By executing this I am getting the following error:
org.yaml.snakeyaml.error.YAMLException: java.io.IOException: Stream closed
at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:218)
at org.yaml.snakeyaml.reader.StreamReader.ensureEnoughData(StreamReader.java:176)
at org.yaml.snakeyaml.reader.StreamReader.ensureEnoughData(StreamReader.java:171)
at org.yaml.snakeyaml.reader.StreamReader.peek(StreamReader.java:126)
at org.yaml.snakeyaml.scanner.ScannerImpl.scanToNextToken(ScannerImpl.java:1198)
at org.yaml.snakeyaml.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:308)
at org.yaml.snakeyaml.scanner.ScannerImpl.checkToken(ScannerImpl.java:248)
at org.yaml.snakeyaml.parser.ParserImpl$ParseImplicitDocumentStart.produce(ParserImpl.java:213)
at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:165)
at org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:155)
at org.yaml.snakeyaml.composer.Composer.getSingleNode(Composer.java:141)
at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:151)
at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:491)
at org.yaml.snakeyaml.Yaml.loadAs(Yaml.java:484)
I have tried by passing the config server url as well like this, but it didn't work
Yaml yaml = new Yaml();
InputStream inputStream = clazz
.getClassLoader()
.getResourceAsStream("http://localhost:8080/application-myprops.yml");
MyPropsYaml obj = yaml.loadAs(inputStream, MyPropsYaml.class);
I dont want to place application-myprops.yml in my application. It should be in my config server. How can I make it work like that.
Thanks in advance!

Related

Deployed WAR can't access a file

I have a spring application, and i'm trying to access a json file with the following code :
try (FileReader reader = new FileReader("parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
I have put the parameter.json file in the project folder and I'm accesing the file data from an angular app through a rest api, and that works fine when I run the application on local machine, but when I deploy the war file on tomcat, my application can't load the file, should I put parameter.json file somewhere else on tomcat or what is the best solution for it.
Your question states you are attempting to access a file called parameter.json, while your code excerpt shows parameters.json. Perhaps that discrepancy indicates a typo in your source code?
If not, there are various ways to access a file from the classpath in Spring, with the first step for each being to ensure the file is in the project's src/main/resources directory.
You can then use one of the Spring utility classes ClassPathResource, ResourceLoader or ResourceUtils to get to the file. The easiest approach, though, may be to put your properties in a .properties file (default file name application.properties) and access the values using Spring's #Value annotation:
#Value("${some.value.in.the.file}")
private String myValue;
You can use other file names as well by utilizing #PropertySource:
#Configuration
#PropertySource(value = {"classpath:application.properties",
"classpath:other.properties"})
public class MyClass {
#Value("${some.value.in.the.file}")
private String myValue;
...
}
Make sure your parameters.josn filename is exactly same in the code.
Move you parameters.json file in the resources folder and then use the classpath with the filename.
try (FileReader reader = new FileReader("classpath:parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
Try to put the file under resources folder in your spring project. You should be able to access the file from that location.
FileReader is looking for a full-fledged file system like the one on your computer, but when your WAR is deployed, there just isn't one, so you have to use a different approach. You can grab your file directly from your src/main/resources folder like this
InputStream inputStream = getClass().getResourceAsStream("/parameters.json");

Apache Commons Configuration2 how to read data from InputStream

How can I read the data from InputStream by using Apache Commons Configuration2?
FileBasedConfigurationBuilder<XMLConfiguration> builder =
new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
.configure(
new Parameters()
.xml()
.setFileName("")
.setExpressionEngine(new XPathExpressionEngine())
);
XMLConfiguration config = builder.getConfiguration();
config.read(sourceJarFile.getInputStream(sourcePropertiesEntry))
Gives the above code, I will get the below exception if the setFileName is given empty string.
org.apache.commons.configuration2.ex.ConfigurationException: Could not locate: org.apache.commons.configuration2.io.FileLocator#61dc03ce[fileName=tmp.xml,basePath=<null>,sourceURL=,encoding=<null>,fileSystem=<null>,locationStrategy=<null>]
at org.apache.commons.configuration2.io.FileLocatorUtils.locateOrThrow(FileLocatorUtils.java:346)
at org.apache.commons.configuration2.io.FileHandler.load(FileHandler.java:972)
at org.apache.commons.configuration2.io.FileHandler.load(FileHandler.java:702)
at org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder.initFileHandler(FileBasedConfigurationBuilder.java:312)
at org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder.initResultInstance(FileBasedConfigurationBuilder.java:291)
at org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder.initResultInstance(FileBasedConfigurationBuilder.java:60)
at org.apache.commons.configuration2.builder.BasicConfigurationBuilder.createResult(BasicConfigurationBuilder.java:421)
at org.apache.commons.configuration2.builder.BasicConfigurationBuilder.getConfiguration(BasicConfigurationBuilder.java:285)
at com.test.installer.App.getXMLConfigurationProperties(App.java:185)
If I give null or just not call setFileName(); I will get the unable to load configuration exception at the read() line.
org.apache.commons.configuration2.ex.ConfigurationException: Unable to load the configuration
at org.apache.commons.configuration2.XMLConfiguration.load(XMLConfiguration.java:986)
at org.apache.commons.configuration2.XMLConfiguration.read(XMLConfiguration.java:954)
at com.test.installer.App.updateExistedProperties(App.java:84)
From the example in the API documentation:
Set up your file parameters (encoding and such):
FileBasedBuilderParameters fileparams = ...
FileBasedConfigurationBuilder<PropertiesConfiguration> builder =
new FileBasedConfigurationBuilder<>(PropertiesConfiguration.class).configure(fileparams);
and then:
FileBasedConfiguration config = builder.getConfiguration();
FileHandler fileHandler = new FileHandler(config);
Inputstream istream = ...
fileHandler.load(istream);
Note that you cannot use autosave with this. To save you'd probably need to provide an OutputStream. Something like:
fh.save(ostream)
Proper way of loading XML configuration data from Input Stream (in commons-collections 2.x) is as follows:
XMLConfiguration cfg = new BasicConfigurationBuilder<>(XMLConfiguration.class).configure(new Parameters().xml()).getConfiguration();
FileHandler fh = new FileHandler(cfg);
fh.load(inputStream);
After calling load() cfg will contain loaded configuration.
Also note, that using XMLConfiguration.read() method should not be used, as this method is designed for internal use and probably will be renamed to _read() in future (see: https://issues.apache.org/jira/browse/CONFIGURATION-641).
You can use XMLConfiguration.read(InputStream in) , but as far as I know, you need to have a XML file somewhere. The reason is that when you either get the configuration from the builder or call the read method above, there are a few checks in the private load method (line 963 in the XMLConfiguration.java in the source files).
Parameters params = new Parameters();
FileBasedConfigurationBuilder<XMLConfiguration> fileBuilder =
new FileBasedConfigurationBuilder<>(XMLConfiguration.class)
.configure(params.fileBased().setFileName("/tmp/dummy.xml"));`
XMLConfiguration xmlConfiguration = fileBuilder.getConfiguration();
xmlConfiguration.read(inputStream);
The dummy file can be anything as long as it’s well-formed, it doesn’t need to be valid. In my case, /tmp/dummy.xml just contains <_/>.

Setting a resource for Spring Batch reader from file system

I'd like to adjust my code to make the Spring Batch reader to read the resource file not from class path, but from the file system (like C:\inputData.xml). Is there any way, how to make it? My current code looks like this and reads given xml file from resources folder just fine:
#Bean
ItemReader<FamilyBatchEntity> xmlFamilyFileItemReader() {
StaxEventItemReader<FamilyBatchEntity> xmlFileReader = new StaxEventItemReader<>();
xmlFileReader.setResource(new ClassPathResource("inputData.xml"));
xmlFileReader.setFragmentRootElementName("Familiendetails");
Jaxb2Marshaller insurantMarshaller = new Jaxb2Marshaller();
insurantMarshaller.setClassesToBeBound(FamilyBatchEntity.class);
xmlFileReader.setUnmarshaller(insurantMarshaller);
return xmlFileReader;
}
Change your ClassPathResource to a FileSystemResource and pass in the path. You can read more about the FileSystemResource in the documentation here: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/FileSystemResource.html

Why do Properties load method failed in Eclipse plugin dev?

I'm trying to use Properties's load() method in my Eclipse plugin project. Since I wanna put the propertie file in a folder like this:
Pluging Project/
|
+----/src/...
+----/config/config.properties
+----/icons/...
+----META-IN/
+----build.properties
+----plugin.xml
And then I try code like this but failed:
Properties prop = new Properties();
InputStream inputStream = (InputStream) Activator.getDefault().getBundle().getEntry("/config/config.properties").getContent();
prop.load(inputStream);
This method receipt a input byte stream as parameter. And I'm pretty sure Activator.getDefault().getBundle().getEntry() returns a InputStream.
And if I put the propertie file in the same location of the calling class and use
InputStream inputStream = this.getClass().getResourceAsStream("config.properties");
It will go well.
So any hints?
The URL returned by Bundle.getEntry uses an internal Eclipse scheme and doesn't always support getContents(). You need to call org.eclipse.core.runtime.FileLocator.toFileURL() to convert it:
URL url = Activator.getDefault().getBundle().getEntry("/config/config.properties");
url = FileLocator.toFileURL(url);
InputStream inputStream = (InputStream)url.getContent();
Also make sure you have the config directory listed in the build.properties

Storing changes in .properties file that has been read via getClass().getResourceAsStream

I am writing a java web application that reads properties from a .properties file. Since I do not know the absolute path of the .properties file, because it depends on the environment the application will run on in the future, I have to load it with "getClass().getResourceAsStream":
Properties props = new Properties();
props.load(getClass().getResourceAsStream("test.properties"));
message = props.getProperty("testdata");
This works as expected. Now I want to change the value for testdata in the file. But I cannot open an Outputstream to write to, because I still don't know the path of the .properties file.
props.setProperty("testdata", "foooo");
props.store(new FileOutputStream("?????"), null);
Is there a way to get the path of the file or can I use the established Properties-object somehow? Any ideas are welcome that allow me to change the .properties file.
You can get an URL by using getResource() rather than using getResourceAsStream()
You can then use that URL to read from and write to your properties file.
File myProps = new File(myUrl.toURI());
FileInputStream in = new FileInputStream(myProps);
Etc.
The Properties class includes a store method that can be used to save the properties back to the stream that was read in getClass().getResourceAsStream("test.properties").

Categories

Resources