I am creating some REST APIs. For this I have some application level common name value pairs. To configure those name value pairs , I just created an xml file in WebContent and accessed values from the xml in a static block of a class and initialized with static variables. So all values which are given for each name in xml will be assigned to respective static variable from a class's static block.
I am able to access those variables and get values in each classes other than from a REST API client. The problem comes, when I'm creating a REST API client for consuming API's created in the same project, FileNotFoundException is throwing for the path I have given for my xml file(WebContent/myxml.xml).
I can see that, its searching for the same xml file in my eclipse path(/home/aneesh/eclipse/WebContent/myxml.xml). And FileNotFoundException throwing.
How can I resolve this issue?
1. class which accessing xml file
class Constants {
public static String name;
static {
initializeConstants();
}
public static void initializeConstants() {
try {
//initializing Constants
//"Reading file"
File xmlFile = new File("WebContent/myxml.xml");
.......
//file is getting read perfectly and "name" is initialized
}
}
2. class accepting static variable Constants.name
// accepting value of 'name' using Constants.name successfully
// writing a method which is accepting some parameters and using Constants.name.
// writing a "main" method and calling this class's methods will work perfectly.
// value of Constants.name will be accessible here.
3. REST API created which will call methods of second class with parameters.
4. Webscript client created for consuming above created API.
// Here the exception is coming.
// Eception is throwing from the class Constants
//Exception from Constants : FileNotFoundException
java.io.FileNotFoundException: /home/aneesh/eclipse/eclipse/WebContent/myxml.xml (No such file or directory)
So, why in this case its looking for the file in eclipse's path? How to resolve it?
Tried by putting into src folder also, but not working.
Try giving the path as WebContent//myxml.xml
(Note the double forward slashes //)
You will have to find the path of the XML file dynamically.
You can use ServletContext object's getRealPath() - you can use it like : getRealPath("/"), which returns you the path of the application deployed. Then from there you can navigate to the XML file required inside your application.
ServletContext context = session.getServletContext();
String path = context.getRealPath("/");
Use the variable path and navigate to your XML.
As I my class is not a Servlet class; I followed;
public String getAppPath() {
java.net.URL r = this.getClass().getClassLoader().getResource("myxml.xml");
String filePath = r.getFile();
String result = new File(new File(new File(filePath).getParent()).getParent()).getParent();
if (!filePath.contains("WEB-INF")) {
// Assume we need to add the "WebContent" folder if using Jetty.
result = FilenameUtils.concat(result, "WebContent");
}
return result;
}
Related
I am in CS1050, and we are doing a lab that includes grabbing information from files in order to print new information onto a different file. I have no idea what one of the methods my teacher wrote in the test case class is trying to do. Ive looked up all of the methods that this method uses, but I dont know what the end result is.
static String getBadPath(String name) {
return new File(new File(TestSuite.class.getResource("empty.txt").getPath()).getParent(), name).getAbsolutePath();
}
This basically get the absolute path of a file whose name is name and resides in the same directory with empty.txt.
You can break it down into following code:
//get the File object named "empty.txt".
File emptyTxt=new File(TestSuite.class.getResource("empty.txt").getPath());
//get the directory this emptyTxt reside in
File parentDirectory=emptyTxt.getPath().getParent();
//get the File whose name is same as the parameter name and reside in parentDirectory.
File resultFile=new File(parentDirectory,name)
//return the absolute path of the resultFile
return resultFile.getAbsolutePath();
I am trying to create a file and write to it, but I'm getting error in my path.
Here is my code:
#Value("${base.location}")
private String folderName;
if (StringUtils.isBlank(dateFileName)) {
setdateFileName(new StringBuilder().append("MY_FILE")
.append(".txt").toString());
}
dateFile = new File(
new StringBuilder().append(folderName).append(File.separator).append(dateFileName).toString());
if (!dateFile.exists()) {
try {
dateFile.mkdir();
dateFile.createNewFile(); //error
}
You can’t have a folder and a file with the same name in the same path location.
That’s why this code fails:
dateFile.mkdir();
dateFile.createNewFile();
Here you’re first creating a folder, and then you’re attempting to create a file with the same path name. You need to choose a different name for the file.
I’m guessing you potentially intended the following instead:
dateFile.getParentFile().mkdirs();
dateFile.createNewFile();
I.e. create the parent folder of your file (including all its parents, as necessary), and then create the file inside it.
For some reason I keep getting an NPE in a gradle javafx project.
My folder structure is very basic. I have a package with my java files in the main/java folder. I also have my resources in the main/resources folder. When I try to load image.png it gives me an NPE.
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource(url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}
This is a helper class.
From the Scene I call: Image image = Helper.createImage(this, "image.png");
The absolute path to the image would be main/resources/images/image.png.
I checked every tutorial on the internet but I couldn't find any solution for this. I also tried it with the path to the image as parameter and also with an InputStream but it never worked.
Resources
The Class#getResource(String) and related API are used for locating resources relative to the class path and/or module path. When using Class to get a resource you can pass an absolute name or a relative name. An absolute name will locate the resource relative to the root of the class path/module path; an absolute name starts with a /. A relative name will locate the resource relative to the location of the Class; a relative name does not start with a leading /.
In a typical Maven/Gradle project structure, the src/main/java and src/main/resources are roots of the class path/module path. This means all resource names are relative to those directories. It's slightly more complicated than that because the files under those directories are moved to the target/build directory and it's that location that's put on the class path/module path, but for all intents and purposes consider the source directories as the root. There's a reason a get-resource API exists in the first place, to provide an application-location-independent way of obtaining resources.
Issues in Your Code
From your question I gather your project structure looks something like:
<project-dir>
|--src/
|--main/
|--java/
|--resources/
|--images/
|--image.png
And you're calling your method with an Object and a resource name of image.png. The problem here is that, since you're passing a relative name, the resource is located relative to the Class of the passed Object (i.e. context). I doubt your class is located in a package named images which means the resource will not be found relative to said class. You need to pass an absolute name: /images/image.png.
The other problem is your use of URL#getPath(). The URL you obtain from Class#getResource(String) will, if the resource were to be found, look something like this:
file:/path/to/gradle/project/build/resources/main/images/image.png
But the result of URL#getPath() will give you:
/path/to/gradle/project/build/resources/main/images/image.png
This causes a problem due to the way Image works. From the documentation:
All URLs supported by URL can be passed to the constructor. If the passed string is not a valid URL, but a path instead, the Image is searched on the classpath in that case.
Notice the second sentence. If the passed URL does not have a scheme then it's interpreted as a resource name and the Image will locate the image file relative to the classpath. In other words, since you're passing the value of URL#getPath() to the Image constructor it searches for the resource image.png in the package path.to.gradle.project.build.resources.main.images. That package does not exist. You should be passing the URL as-is to the Image constructor via URL#toString() or URL#toExternalForm().
Solution
If you're going to use the URL returned by Class#getResource(String) to load the Image then no matter what you need to use URL#toString() or URL#toExternalForm() instead of URL#getPath().
public static Image createImage(Object context, String resourceName) {
URL _url = context.getClass().getResource(resourceName);
return new Image(_url.toExternalForm());
}
Then you have at least two options:
Pass the absolute resource name (i.e. "/images/image.png") to your #createImage(Object,String) method since the image.png resource is not in the same package as the passed Object (i.e. context).
Move the resource to the same package as the class of the passed in Object (i.e. context). For instance, if the context object's class is com.foo.MyObject then place the resource under src/main/resources/com/foo and it will be in the same package as MyObject. This will allow you to continue passing the relative resource name.
Of course, as noted by the documentation of Image you can pass a scheme-less URL and it's interpreted as a resource name. In other words, you could do:
Image image = new Image("images/image.png");
And that should work. A note of caution, however: When using modules the above will only work if the resource-containing package is opens unconditionally or if the module itself is open.
Try using the path /images/image.png.
The resources always get referenced from the class root, in your case src/main/resources, so from there going to /images/image.png should be the correct path.
this is how I am passing the images in my application. ivSerialAssignmentLogo is a FXML element (ImageView).
ivSerialAssignmentLogo.setImage(new Image(getClass().getResourceAsStream("/img/serialAssignment.svg")));
In your case, you could use something like that
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource("/images/" + url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}
I have two classes. One is intended to be a common library and another a client that consumes from the library.
The library is structured as below:
public class Library
{
public Library()
{
String pathToResourceA="src/main/resources/A.xls";// A.xls is present within resources
String key="apples";
Resource res= loadResourceBasedOnDoc(pathToResource,key);
...//process resource
}
}
It's corresponding test class
public class LibraryTest
{
#Test
public void testLibrary()
{
new Library();// works as expected- the test passes and the resource is loaded.//ie. A.xls is found in the right place
}
}
However, when I try to access the library from my client in the following manner
import packagename.Library
public class Client{
Library lib;
public Client()
{
lib= new Library();// throws a FileNotFoundException!
}
}
I get a FileNotFoundException. I'm guessing this is something to do with defining the right value to pathToResourceA in class A but cant figure out what it is. Any thoughts would be appreciated. Thanks!
Code for loadResourcesBasedonDoc
protected Resource loadResourceBasedOnDoc(String filename,String password)
{
InputStream in = null;
try {
in = new FileInputStream(filename);
//further in is processed...
The problem is that you are using relative file paths:
String pathToResourceA="src/main/resources/A.xls";// A.xls is present within resources
This is then processed in the loadResourceBasedOnDoc method as follows:
in = new FileInputStream(filename);
This call looks for the file (src/main/resources/A.xls) on the file system. Because the path is relative, it looks for the file in a directory that is relative to the current working directory. In your unit test, the current working directory is probably the directory from which the test is launched. Assuming that is the root of your project, the test likely finds A.xls on the file system within your project.
To solve this, I recommend using full pathnames in the loadResourceBasedOnDoc as follows:
String programLaunchDir = System.getProperty("user.dir")
in = new FileInputStream(programLaunchDir + File.separator + filename);
The user.dir system property should be the current working directory. So if you can enforce that the program is launched from that dir, you are all set. Otherwise, you might want to wrap you program in a batch file or shell script that passes the directory to the program.
What is a best practice for storing user messages in a configuration file and then retrieving them for certain events throughout an application?
I was thinking of having 1 single configuration file with entries such as
REQUIRED_FIELD = {0} is a required field
INVALID_FORMAT = The format for {0} is {1}
etc. and then calling them from a class that would be something like this
public class UIMessages {
public static final String REQUIRED_FIELD = "REQUIRED_FIELD";
public static final String INVALID_FORMAT = "INVALID_FORMAT";
static {
// load configuration file into a "Properties" object
}
public static String getMessage(String messageKey) {
//
return properties.getProperty(messageKey);
}
}
Is this the right way to approach this problem or is there some de-facto standard already in place?
You're on the right track with putting the messages into a property file. Java makes this pretty easy if you use ResourceBundle. You basically create a property file containing your message strings for each locale you want to support (messages_en.properties, messages_ja.properties) and bundle those property files into your jar. Then, in your code, you extract the message:
ResourceBundle bundle = ResourceBundle.getBundle("messages");
String text = MessageFormat.format(bundle.getString("ERROR_MESSAGE"), args);
When you load the bundle, Java will determine what locale you're running in and load the correct message. Then, you pass in your args along with the message string and create the localized message.
Reference for ResourceBundle.
Your approach is almost correct. I want to add one more thing. If you are talking about configuration file, it is always better to have two .properties file.
One for default configuration of the application. (let's say defaultProperties.properties)
Second for user-specific configuration (let's say appProperties.properties)
. . .
// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();
// create application properties with default
Properties applicationProps = new Properties(defaultProps);
// now load properties from last invocation
in = new FileInputStream("appProperties");
applicationProps.load(in);
in.close();
. . .
Spring already has support for doing this kind of thing. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#context-functionality-messagesource would be a good starting point