Is getResourceAsStream() thread-safe? - java

I need to read a properties file containing some configuration data in a JSF web application.
Right now the code looks like this
private Properties getConfig() {
Properties properties = new Properties();
InputStream inputStream = null;
try {
inputStream = this.getClass().getResourceAsStream("/config.properties");
try {
properties.load(inputStream);
} catch (IOException e) {
logger.error("Error while reading config properties", e);
}
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
return properties;
}
Is it safe to do it this way or can I run into concurrency issues when multiple threads are calling getConfig()?

No, that should be perfectly safe. I can't see any concurrency issues in there.
However, the exception handling might not be ideal - is it valid to return an empty properties object if you fail to load the config, or should you propagate the exception out of getConfig()? Up to you, really....

Related

Springboot #Scheduled Pauses

I've written a springboot application to perform etl from data source to another data lake every 15 mins. I've scheduled the execution using #Scheduled annotation to a function.
I had created jar and was executing directly through java -jar ingest.jar. It works fine for some days (3-4 days). And just pauses without any exception. To resume, I have to go and press any key to make it active again.
#Scheduled(initialDelayString = "${ingest.initialdelay.in.seconds}000", fixedRateString = "${ingest.rate.in.seconds}000")
public void ingestData(){
// Ingestion Logic
}
Because the problem persisted, I created war and deployed to the tomcat server. But the problem still remains.
Can somebody point me what am I missing here? The same application works fine if I deploy to cloudfoundry.
IO Streams - FileInputStream and FileOutputStream
Helper Functions for IO
public static void saveLastSuccessfulDate(String filepath, String propertyName, Date dateTime) {
Properties prop = new Properties();
OutputStream output = null;
try {
String lastDate = getDateInFormat(dateTime);
log.info("Saving: " + lastDate);
output = new FileOutputStream(filepath);
prop.setProperty(propertyName, lastDate);
prop.store(output, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//Helper to Write to properties file
public static String checkLastSuccessfulDateAsString(String filepath, String propName) {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(filepath);
// load a properties file
prop.load(input);
String lastSuccesfulDate = prop.getProperty(propName);
log.info("Last Successful Date: "+lastSuccesfulDate);
return lastSuccesfulDate;
} catch (FileNotFoundException f) {
log.error("checkLastSuccessfulDateAsString: File Not Found: " + f.getMessage());
} catch (IOException ex) {
log.error(ex.getMessage());
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
Regards
In default, spring #Scheduled use single thread. So, if one task was blocking, the next task won't run.
You can make your task class implements SchedulingConfigurer.It will use multithread to run task and avoid blocking. Code like it:
#Component
public class TaskService implements SchedulingConfigurer {
#Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(taskExecutor());
}
#Bean(destroyMethod = "shutdown")
public ScheduledExecutorService taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
// your code
#Scheduled(initialDelayString = "${ingest.initialdelay.in.seconds}000", fixedRateString = "${ingest.rate.in.seconds}000")
public void ingestData(){
// Ingestion Logic
}
}
May help you.

Propert file is not loading properly

Getting NullPointerException when running all my script in the middle. I have xpath written in the property file and I'm loading the property file in BeforeSuite. The element will be present and the page is also present. Getting null in locator.
may be your property file is not giving the exact value of you element.
try calling this function by providing the property name.
public static String getProperty(String propertyname)
{
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(("path of your property file"));
// load a properties file
prop.load(input);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println(prop.getProperty(propertyname));
//Return the property value
return prop.getProperty(propertyname);
}

Unable to read properties file after creating it

I am creating a properties file and putting into my classpath folder Resources.
When I tried to read this file , i am not getting the expected result. i am getting the result of the previous values printed instead of the property values set now.
My class file is as follows :
public class App {
public static void main(String[] args) {
Properties prop = new Properties();
PrintWriter output = null;
try {
output = new PrintWriter("Resources/config.properties");
// set the properties value
prop.setProperty("database", "localhost");
prop.setProperty("dbuser", "mkyong");
prop.setProperty("dbpassword", "password");
// save properties to project root folder
prop.store(output, null);
if(output!=null) {
System.out.println("Output");
output.close();
}
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null) {
output.close();
}
}
Properties prop1 = new Properties();
BufferedInputStream input = null;
try {
String filename = "config.properties";
input = (BufferedInputStream) AppCPLoad.class.getClassLoader().getResourceAsStream(filename);
if(input==null){
System.out.println("Sorry, unable to find " + filename);
return;
}
//load a properties file from class path, inside static method
prop1.load(input);
//get the property value and print it out
System.out.println(prop1.getProperty("database"));
System.out.println(prop1.getProperty("dbuser"));
System.out.println(prop1.getProperty("dbpassword"));
if(input!=null) {
System.out.println("Input");
input.close();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally{
if(input!=null){
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Please help.
When you run the program, the properties file is loaded and the values are read. After you rewrite the properties file, that doesn't mean that the properties you have loaded already have be to rewritten. You need to reload the properties file and re-read the values. You are looking for an implementation like ReloadableResourceBundleMessageSource

Learning handling exceptions, can't figure out this FileNotFoundException

I'm a beginner still, and currently learning about handling exceptions. The exercise in my book I'm trying to figure out tells me to add a Finally block to close out the file I opened, and I don't understand what I'm doing wrong. Keep in mind the file name and path are fake but here is what I have:
public static String readLineWithFinally()
{
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = new RandomAccessFile("products.ran", "r");
try
{
String s = in.readLine();
return s;
}
catch (IOException e)
{
System.out.println(e.toString());
return null;
}
finally
{
try
{
in.close();
}
catch (Exception e)
{
System.out.println("Generic Error Message");
}
}
}
To add on to Taylor Hx's answer, you can take advantage of Java 7's try-with-resources construct to avoid having to use finally altogether in your case.
public static String readLineWithFinally() {
System.out.println("Starting readLineWithFinally method.");
try (RandomAccessFile in = new RandomAccessFile("products.ran", "r")) {
return in.readLine();
} catch (IOException e) {
System.out.println(e.toString());
return null;
}
}
You'll also want to be certain that your usage is consistent with what the API mandates for RandomAccessFile.
The code that you posted shouldn't compile, as RandomFile(String, String) can possibly throw FileNotFoundException. As such, we must include it in the try block.
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = null;
try {
in = new RandomAccessFile("products.ran", "r");
String s = in.readLine();
return s;
} catch (IOException e) {
System.out.println(e.toString());
return null;
} finally {
try {
if(in != null) {
in.close();
}
} catch (Exception e) {
System.out.println("Generic Error Message");
}
}
Keep in mind the file name and path are fake but here is what I have:
That is why you will have a FileNotFoundException while creating RandomAccessFile("products.ran", "r") with read access mode "r".
From the documentation: RandomAccessFile(String name, String mode)
This constructor throws a FileNotFoundException if the mode is
"r" but the given string does not denote an existing regular file,
or if the mode begins with "rw" but the given string does not denote
an existing, writable regular file and a new regular file of that name
cannot be created, or if some other error occurs while opening or
creating the file

How do I refactor closing a stream in Java?

Due to my company's policy of using Eclipse and using Eclipse's code-autofix, the following code pattern appears excessively in the codebase:
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// handle error
}
}
}
IMO it's extremely fugly and hard to read, especially the portion within the finally block (is there really a need to catch 2 instances of IOException?). Is there anyway to streamline the code such that it looks cleaner?
Why do anything? It's working code. It's correct.
Leave it be.
First, about using IOUtils - may worth a shot telling your supervisors that the very application-server / Java runtime environment they might use, uses IOUtils and similar libraries itself. so in essence you're not introducing new components to your architecture.
Second, no, not really. There isn't really any way around it other than writing your own utility that will immitate IOUtils' closeQuietly method.
public class Util {
public static void closeStream(inputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// log something
}
}
}
Now your code is
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
Util.closeStream(is);
}
Not a lot else to do as the IOException in the catch might have some specific processing.
See this question, use the closeQuietly() solution.
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
IoUtils.closeQuietly(is);
}
// stolen from the cited question above
public class IoUtils {
public static closeQuietly (Closeable closeable) {
try {
closeable.close();
} catch (IOException logAndContinue) {
...
}
}
}
Or wait for JDK7's ARM blocks.
You could define something like this somewhere:
private static interface InputStreamCallback {
public void doIt(InputStream is) throws IOException;
}
private void with(InputStreamCallback cb) {
InputStream is = null;
// Creational code. Possibly adding an argument
try {
cb.doIt(is);
} catch (IOException e) {
// handle error or rethrow.
// If rethrow add throws to method spec.
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// handle error or rethrow.
}
}
}
}
And invoke your code like this:
with(new InputStreamCallback() {
#Override
public void doIt(InputStream is) throws IOException {
is = url.openConnection().getInputStream();
// .....
}
});
If you declare with method static in a helper class, then you could even do an import static of it.
There's a drawback. You need to declare url final.
EDIT: creational code is not the point. You can arrange it in several ways. The callback is the point. You could isolate what you need to do there.

Categories