PropertiesConfiguration.java doesn't have a close() method. Is there something else that needs to be done to release the file? I want to be sure before I use this in production. I've looked through the code and I don't see anything. I'm not entirely sure how PropertiesConfiguration.setProperty() is working without opening a connection to the file that would then have to be closed.
In org.apache.commons.configuration.PropertiesConfiguration the input (stream, path, url, etc...) is of course closed when the properties were loaded in the PropertiesConfiguration instance.
You could have the confirmation in the void load(URL url) method of org.apache.commons.configuration.AbstractFileConfiguration.
Here is how this method is called :
1) PropertiesConfiguration constructor is invoked :
public PropertiesConfiguration(File file) throws ConfigurationException
2) which calls its super constructor :
public AbstractFileConfiguration(File file) throws ConfigurationException
{
this();
// set the file and update the url, the base path and the file name
setFile(file);
// load the file
if (file.exists())
{
load(); // method which interest you
}
}
3) which calls load() :
public void load() throws ConfigurationException
{
if (sourceURL != null)
{
load(sourceURL);
}
else
{
load(getFileName());
}
}
4) which calls load(String fileName):
public void load(String fileName) throws ConfigurationException
{
try
{
URL url = ConfigurationUtils.locate(this.fileSystem, basePath, fileName);
if (url == null)
{
throw new ConfigurationException("Cannot locate configuration source " + fileName);
}
load(url);
}
catch (ConfigurationException e)
{
throw e;
}
catch (Exception e)
{
throw new ConfigurationException("Unable to load the configuration file " + fileName, e);
}
}
5) which calls load(URL url)
public void load(URL url) throws ConfigurationException
{
if (sourceURL == null)
{
if (StringUtils.isEmpty(getBasePath()))
{
// ensure that we have a valid base path
setBasePath(url.toString());
}
sourceURL = url;
}
InputStream in = null;
try
{
in = fileSystem.getInputStream(url);
load(in);
}
catch (ConfigurationException e)
{
throw e;
}
catch (Exception e)
{
throw new ConfigurationException("Unable to load the configuration from the URL " + url, e);
}
finally
{
// close the input stream
try
{
if (in != null)
{
in.close();
}
}
catch (IOException e)
{
getLogger().warn("Could not close input stream", e);
}
}
}
And in the finally statement, you can see that the inputstream is closed in any case.
Related
Function to be tested:
public void deleteFile(File file) {
try {
Files.delete(file.toPath()) ;
log.info("Csv file deleted from system succesfully after processing the data");
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
Test code:
#Test
void testExceptionDuringDeletingFile() {
helper=mock(Helper.class);
//String bucket ="bucket";
//String key = "key";
File file = new File("");
doThrow(IOException.class).when(helper).deleteFile(file);
Assertions.assertThrows(IOException.class,()->helper.deleteFile(file));
}
But I am getting the following exception:
org.mockito.exceptions.base.MockitoException: Checked exception is
invalid for this method! Invalid: java.io.IOException at
com.lululemon.product.ap.reprocess.producer.HelperTests.testExceptionDuringDeletingFile(HelperTests.java:191)
at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) at
Because your deleteFile() method doesn't throw the IOException. You catch it in your method implementation and do something with it.
And, your mocked Helper class instance really can't throw IOException from the deleteFile() method because the real deleteFile() method doesn't.
Throw the IOException from your method and you won't get the error.
deleteFile method:
public void deleteFile(File file) throws IOException {
try {
Files.delete(file.toPath());
log.info("Csv file deleted from system successfully after processing the data");
} catch (IOException e) {
throw new IOException("Couldn't delete file. Try again!");
}
}
Test method:
#Test
void testExceptionDuringDeletingFile() throws IOException {
File file = new File("");
Helper helper = mock(Helper.class);
doThrow(IOException.class).when(helper).deleteFile(file);
Assertions.assertThrows(IOException.class, () -> helper.deleteFile(file));
}
Problem: if the path to the file was not specified in the arguments, then it still displays the phrase "The file was closed". This works 2 times. In uploadToFile and read method. I pass one path in the arguments, and the second is written in the DownloadFile
public class Task implements AutoCloseable {
public static void main(String[] args) throws IOException {
String DownloadFile = "C:\\Users\\VGilenko\\IdeaProjects\\Task\\src\\main\\resources\\Out.txt";
Map<String, Departament> departments = new HashMap<>();
String path = args.length > 0 ? args[0] : null;
read(path, departments);
transferToDepartment(departments, DownloadFile);
}
private static void uploadToFile(List download, String path) {
int i = 0;
try (FileWriter writer = new FileWriter(path, false)) {
...
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
} finally {
System.out.println("The file was closed");
}
}
public static void transferToDepartment(Map<String, Departament> departments, String downloadFile) {
List<String> download = new ArrayList<>();
...
}
uploadToFile(download, downloadFile);
}
public static void read(String path, Map<String, Departament> departments) throws IOException {
assert path != null;
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "CP1251")); br) {
.....
}
}
} catch (FileNotFoundException e) {
System.out.println("The file was not found, check the path");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Correct the file path, step out of the array");
} catch (NullPointerException e) {
System.out.println("You forgot to register the path to the file");
} finally {
System.out.println("The file was closed");
}
}
#Override
public void close() {
System.out.println("The file was closed");
}
}
You have your printout "The file was closed" in your finally statement. If you don't specify a file, you will catch an Exception, and your finally block will be executed.
An easy fix would be to check for the existence of the path (not being empty, not being null).
I have a getMyProperties() method that pulls and returns various properties files and it handles the exception there. However, Eclipse says that another method getRequest() that calls getMyProperties() should also have "throws IOException". Even then after adding this, Eclipse says the main method which calls getRequest() should throw the exception as well. Is this the correct way to handle exceptions? Something about it seems wrong.
After doing what Eclipse suggests, I have the following in my main method. It shows no errors, but is it correct?
public static void main(String[] args) throws IOException {
//some code...
myRequest = TestApiCall.getRequest(type, sQuery);
//some more code...
}
Here are the methods in a separate class...
static String getRequest(String rType, String query) throws IOException{
Properties myProps = null;
String request = "";
switch (rType){
case "XML-SBQ":
request = CallConsts.XML_SBQ_CALL;
myProps = getMyProperties("configSBQ.properties");
//use the properties
break;
case "JSON-SBQ":
request = CallConsts.JSON_SBQ_CALL;
//use the properties
break;
case "JSON-gos":
request = CallConsts.JSON_GOS_CALL;
myProps = getMyProperties("configGOS.properties");
//use the properties
}
return request;
}
static Properties getMyProperties(String propName) throws IOException{
Properties prop = new Properties();
InputStream inputStream = null;
try {
String propFileName = propName;
inputStream = TestApiCall.class.getClassLoader().getResourceAsStream(propFileName);
if (inputStream != null) {
prop.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
} catch (Exception e) {
System.out.println("Exception: " + e);
} finally {
inputStream.close();
}
return prop;
}
Here is the method after the changes, as suggested by Jocelyn and Vasquez. Hopefully looking much better!
static Properties getMyProperties(String propName) {
Properties prop = new Properties();
String propFileName = propName;
try (InputStream inputStream = TestApiCall.class.getClassLoader().getResourceAsStream(propFileName)){
if (inputStream != null) {
prop.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
} catch (IOException e) {
System.out.println("Exception: " + e);
}
return prop;
}
getMyProperties(String propName) should not throw IOException since you are catching Exception here. Hence getRequest() has no need to declare it and your problem is solved.
Nevertheless, I advise you to never catch Exception as a whole, you should only catch IOException and FileNotFoundException here.
I have a java class with a file path.When i try to run that as java application it is working fine but when i try to access that method in the class from a servlet I am getting error java.io.FileNotFoundException
Java Class
public class PropertiesManager {
static Properties prop =new Properties();
static String PROPERTY_FILENAME = "Dashboard1.0/src/server_url.properties";
public static void main(String[] args) {
loadProperty();
System.out.println(prop.getProperty("DemoApps_DataBase"));
updateProperty();
}
public static void loadProperty(){
InputStream input = null;
try {
FileInputStream file= new FileInputStream(PROPERTY_FILENAME);
// load a properties file
prop.load(file);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void updateProperty(){
OutputStream output = null;
try {
output = new FileOutputStream(PROPERTY_FILENAME);
// set the properties value
prop.setProperty("DemoApps_DataBase", "Oracle");
System.out.println(prop.getProperty("DemoApps_DataBase"));
// save properties to project root folder
prop.store(output, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Servlet Class
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String name=request.getParameter("appName");
String link=request.getParameter("appLink");
String database=request.getParameter("appDB");
String webServices=request.getParameter("appWebService");
PropertiesManager.loadProperty();
PropertiesManager.updateProperty();
RequestDispatcher rd=request.getRequestDispatcher("updateappstatus.jsp");
rd.forward(request,response);
}
For one of my projects, I implement a Java 7 FileSystem over the Box API Java SDK (the new one).
However, for downloading files, when you want to have a stream to the content, it only provides methods taking OutputStream as an argument; specifically, I am using this one at the moment.
But this doesn't sit well with the JDK API; I need to be able to implement FileSystemProvider#newInputStream()... Therefore I elected to use Pipe{Input,Output}Stream.
Moreover, since the Box SDK API methods are synchronous (not that it matters here), I wrap them in a Future. My code is as follows (imports ommitted for brevity):
#ParametersAreNonnullByDefault
public final class BoxFileInputStream
extends InputStream
{
private final Future<Void> future;
private final PipedInputStream in;
public BoxFileInputStream(final ExecutorService executor,
final BoxFile file)
{
in = new PipedInputStream(16384);
future = executor.submit(new Callable<Void>()
{
#Override
public Void call()
throws IOException
{
try {
file.download(new PipedOutputStream(in));
return null;
} catch (BoxAPIException e) {
throw BoxIOException.wrap(e);
}
}
});
}
#Override
public int read()
throws IOException
{
try {
return in.read();
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public int read(final byte[] b)
throws IOException
{
try {
return in.read(b);
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public int read(final byte[] b, final int off, final int len)
throws IOException
{
try {
return in.read(b, off, len);
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public long skip(final long n)
throws IOException
{
try {
return in.skip(n);
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public int available()
throws IOException
{
try {
return in.available();
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public void close()
throws IOException
{
IOException streamException = null;
IOException futureException = null;
try {
in.close();
} catch (IOException e) {
streamException = e;
}
try {
future.get(5L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
futureException = new BoxIOException("donwload interrupted", e);
} catch (ExecutionException e) {
futureException = new BoxIOException("download failure",
e.getCause());
} catch (CancellationException e) {
futureException = new BoxIOException("download cancelled", e);
} catch (TimeoutException e) {
futureException = new BoxIOException("download timeout", e);
}
if (futureException != null) {
if (streamException != null)
futureException.addSuppressed(streamException);
throw futureException;
}
if (streamException != null)
throw streamException;
}
#Override
public synchronized void mark(final int readlimit)
{
in.mark(readlimit);
}
#Override
public synchronized void reset()
throws IOException
{
try {
in.reset();
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public boolean markSupported()
{
return in.markSupported();
}
}
The code consistenly fails with the following stack trace (that is in int read(byte[]):
Exception in thread "main" com.github.fge.filesystem.box.exceptions.BoxIOException: download failure
at com.github.fge.filesystem.box.io.BoxFileInputStream.read(BoxFileInputStream.java:81)
at java.nio.file.Files.copy(Files.java:2735)
at java.nio.file.Files.copy(Files.java:2854)
at java.nio.file.CopyMoveHelper.copyToForeignTarget(CopyMoveHelper.java:126)
at java.nio.file.Files.copy(Files.java:1230)
at Main.main(Main.java:37)
[ IDEA specific stack trace elements follow -- irrelevant]
Caused by: java.io.IOException: Pipe broken
at java.io.PipedInputStream.read(PipedInputStream.java:322)
at java.io.PipedInputStream.read(PipedInputStream.java:378)
at java.io.InputStream.read(InputStream.java:101)
at com.github.fge.filesystem.box.io.BoxFileInputStream.read(BoxFileInputStream.java:78)
... 10 more
But when it fails, the download is already complete...
OK, the thing is, I can grab the file size and hack around it but I'd prefer not to if at all possible; how can I modify this code so as to avoid EPIPE?
The SDK also provides BoxAPIRequest and BoxAPIResponse classes that let you make manual requests for advanced use-cases. These classes still automatically handle authentication, errors, back-off, etc. but give you more granular control over the request.
In your case, you could do make a download request manually by doing:
// Note: this example assumes you already have a BoxAPIConnection.
URL url = new URL("files/" + file.getID() + "/content")
BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
BoxAPIResponse response = request.send();
InputStream bodyStream = response.getBody();
// Use the stream.
response.disconnect();
Well, I found the solution, although I am not very satisfied with it...
Since I can know the file size which I try to open an inputstream on, I just pick the size and decrease it by the amount of bytes read -- unless the size reaches 0, in this case all read methods return -1.