I am using Spring Framework's MultipartFile to allow a user to upload a picture to a profile. I've configured DispatcherServlet in a servlet initializer class that extends AbstractAnnotationConfigDispatcherServletInitializer. In that class, I've overridden the customizeRegistration() method as follows:
#Override
protected void customizeRegistration(Dynamic registration) {
registration.setMultipartConfig(new MultipartConfigElement("/tmp/practicewellness/uploads", 2097152, 4194304, 0));
}
The MultipartFile's transferTo() method calls for a file location in the filesystem where the uploaded file will be written temporarily. Can this location be anywhere? When I used the following location in the method:
profilePicture.transferTo(new File("tmp/practicewellness/" + employee.getUsername() + ".jpg"));
... I get the following error:
Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [C:\Users\kyle\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\work\Catalina\localhost\practicewellness\tmp\practicewellness\uploads] is not valid
So I can see that it's looking for this file location deep inside one of my Eclipse plugins. I don't understand why it looks there. When I look there, the "tmp" directory is not there. But regardless, is it okay for me to go into that plugin and create the directory there? Or is there a better way to smooth this out?
I've uploaded files using Spring mvc, but never used transferTo(), I just assume that your problem is due to "No existence of specified path" because there wont be a path ending with .jpg. Try it like this.
String path = "/tmp/practicewellness/";
File dirPath = new File(path);
if (!dirPath.exists()) {
dirPath.mkdirs();
}
And then execute the transferTo() code.
Also do not set the path directly like you've done. Since you're doing it in spring, so I assume you want the folder to be in your Project path not the eclipse's metadata path. So change your path to this.
String path = request.getSession().getServletContext().getRealPath("/tmp/practicewellness/");
It will create a folder inside your Project's Webapp folder using mkdir. If you want to save differentiate the files for each user, you can create a folder for each user by using this below path.
String path = request.getSession().getServletContext().getRealPath("/tmp/practicewellness")+"/"+employee.getUsername()+"/";
Related
I am trying to load an image to use as an icon in my application. The appropriate method according to this tutorial is:
protected ImageIcon createImageIcon(String path, String description)
{
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
So, I placed the location of the file, and passed it as a parameter to this function. This didn't work, i.e. imgURL was null. When I tried creating the ImageIcon by passing in the path explicitly:
ImageIcon icon = new ImageIcon(path,"My Icon Image");
It worked great! So the application can pick up the image from an explicitly defined path, but didn't pick up the image using getResources(). In both cases, the value of the path variable is the same. Why wouldn't it work? How are resources found by the class loader?
Thanks.
getClass().getResource(path) loads resources from the classpath, not from a filesystem path.
You can request a path in this format:
/package/path/to/the/resource.ext
Even the bytes for creating the classes in memory are found this way:
my.Class -> /my/Class.class
and getResource will give you a URL which can be used to retrieve an InputStream.
But... I'd recommend using directly getClass().getResourceAsStream(...) with the same argument, because it returns directly the InputStream and don't have to worry about creating a (probably complex) URL object that has to know how to create the InputStream.
In short: try using getResourceAsStream and some constructor of ImageIcon that uses an InputStream as an argument.
Classloaders
Be careful if your app has many classloaders. If you have a simple standalone application (no servers or complex things) you shouldn't worry. I don't think it's the case provided ImageIcon was capable of finding it.
Edit: classpath
getResource is—as mattb says—for loading resources from the classpath (from your .jar or classpath directory). If you are bundling an app it's nice to have altogether, so you could include the icon file inside the jar of your app and obtain it this way.
As a noobie I was confused by this until I realized that the so called "path" is the path relative to the MyClass.class file in the file system and not the MyClass.java file. My IDE copies the resources (like xx.jpg, xx.xml) to a directory local to the MyClass.class. For example, inside a pkg directory called "target/classes/pkg. The class-file location may be different for different IDE's and depending on how the build is structured for your application. You should first explore the file system and find the location of the MyClass.class file and the copied location of the associated resource you are seeking to extract. Then determine the path relative to the MyClass.class file and write that as a string value with "dots" and "slashes".
For example, here is how I make an app1.fxml file available to my javafx application where the relevant "MyClass.class" is implicitly "Main.class". The Main.java file is where this line of resource-calling code is contained. In my specific case the resources are copied to a location at the same level as the enclosing package folder. That is: /target/classes/pkg/Main.class and /target/classes/app1.fxml. So paraphrasing...the relative reference "../app1.fxml" is "start from Main.class, go up one directory level, now you can see the resource".
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../app1.fxml"));
Note that in this relative-path string "../app1.fxml", the first two dots reference the directory enclosing Main.class and the single "." indicates a file extension to follow. After these details become second nature, you will forget why it was confusing.
getResource by example:
package szb.testGetResource;
public class TestGetResource {
private void testIt() {
System.out.println("test1: "+TestGetResource.class.getResource("test.css"));
System.out.println("test2: "+getClass().getResource("test.css"));
}
public static void main(String[] args) {
new TestGetResource().testIt();
}
}
output:
test1: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
test2: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
getResourceAsStream() look inside of your resource folder. So the fil shold be placed inside of the defined resource-folder
i.e if the file reside in /src/main/resources/properties --> then the path should be /properties/yourFilename.
getClass.getResourceAsStream(/properties/yourFilename)
Fairly new to Wicket so excuse my ignorance.
I have a Wicket app...starts with WicketApplication.class I have a WicketApplication.properties file to load some values. The properties file sits next to the class file (same package). Works fine, no issues.
Now, I would like to move the properties file outside the application WAR/JAR. Exported the app as a WAR to run on Tomcat. I have create a a folder called properties under tomcat root & moved WicketApplication.properties to this directory. Added the following to init() method in WicketApplication.class...
String realPath = getServletContext().getRealPath("/");
realPath = realPath.replaceAll("\\\\", "/");
if (realPath.toUpperCase().indexOf("WEBAPPS") != -1) {
String newRes = realPath.substring(0, realPath.toUpperCase().indexOf("WEBAPPS") -1);
System.out.println (newRes + "/properties");
getResourceSettings().getResourceFinders().add(new Path( newRes + "/properties"));
}
I get an exception thrown.
How do I "externalise" the properties file?
Also, if I could take one step further, how do I map a properties file name to class name..it, myapplication.properties -> WicketApplication.class
Thanks in advance.
You need to add new IStringResourceLoader with application.getResourceSettings().getStringResourceLoaders().add(...).
See https://github.com/apache/wicket/blob/515e2be2a5301f5caf7b1baee4a593d21c20e275/wicket-core/src/main/java/org/apache/wicket/settings/ResourceSettings.java#L220-L224 for the default ones.
IResourceFinder should be used when you want to add custom location for your HTML files.
There is no way to map myapplication.properties to WicketApplication.class. By adding an additional IStringResourceLoader you just tell Wicket to search in yet another place.
I am trying to invoke a Method present within a JAR file from my Web Application (A simple Servlet Application). Below is the code that method is using for accessing the properties file:
InputStream inputStream =
ClassLoader.getSystemClassLoader()
.getResourceAsStream("demo.properties");
properties.load(inputStream);
When this method is invoked using my Web Application, I am getting this NullPointerException:
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Unknown Source)
at java.util.Properties.load0(Unknown Source)
at java.util.Properties.load(Unknown Source)
Possible reason for this exception is: My Web Application is not able to find the demo.properties file, hence the inputStream is NULL and this exception is thrown.
Please let me know:
How to resolve this exception.
Do I need to place the properties file manually within my Web Based Application? If yes then where exactly where to place this demo.properties file in my Web Application for resolving this exception.
The system class loader only knows about the core Java libraries, for example, those in java.lang., java.util., etc.
You want to load the properties file using the same class loader which looks at that JAR file, which is probably the same class loader that loaded your class.
Try something like this:
public class PropertyFileTest {
public void loadProperties() {
InputStream inputStream = PropertyFileTest.class.getResourceAsStream("/demo.properties");
properties.load(inputStream);
// do something with properties to see if it worked or not.
}
}
Note that I used Class.getResourceAsStream, which will use that class's class loader for you, per:
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
The class loaders interprete the passed string as absolute path, hence as if it were /demo.properties (but never use the heading slash for ClassLoader.getResource). So open the war and look for /WEB-INF/classes/demo.properties. This must be case sensitive.
You might (in general) be interested in alternatives:
MyServletClass.class.getResourceAsStream("/demo.properties") -- better;
ResourceBundle bundle = ResourceBundle.get("demo");
Using Servlet's init parameters in /WEB-INF/web.xml.
ClassLoader does not identified which properties file location.
Use this code:
String path = AbcServiceImpl.class.getClassLoader().getResource("abc.properties").getFile().toString();
path = path.replace("%20", " ");
File f = new File(path);
All,
I have decided to adopt the java.util.Properties class within my servlets to facilitate easier maintenance of configs.
I am using the poperties class function loadFromXML to fetch an XML file that contains denatured (XML compliant ) SQL queries that my servlet will then execute.
Using this code which works fine in normal CLI Java application:
// retrieve all queries from xml from classpath
queries = new Properties();
try
{
String path = getServletContext().getRealPath("/WEB-INF");
System.out.println(path + "/queries.xml");
queries.loadFromXML(MyServlet.class.getResourceAsStream(path + "/queries.xml"));
}
catch (IOException io)
{
io.printStackTrace();
}
The output is a NULL Pointer Exception thrown by the loadFromXML method
java.lang.NullPointerException
at java.util.Properties.loadFromXML(Properties.java:851)
The file exists as produced by the system out message in the web server logs.
CORE3282: stdout: /u02/SunONE61060/testserver/myservlet/WEB-INF/queries.xml
I tried moving the XML file to the base directory where the Servlet class exists and call it from there but still the same NPE.
Any ideas?
Your problem is here:
MyServlet.class.getResourceAsStream(path + "/queries.xml")
This will return null. .getResourceAsStream() can only load from the classpath (for instance, /com/foo/myclass/MyResource.xml).
Since you have the absolute path of your resource, just use a standard FileInputStream, for instance.
Also: close your stream after you are done with it. Right now you don't: you have a resource leak. See the javadoc for Closeable.
You are attempting to load the resources from your classpath but are providing a real path. These two are not the same.
When you are using
MyServlet.class.getResourceAsStream("queries.xml")
Then the classloader will attempt to load the class from whereever your MyServlet.class file is, so if the package is my.pkg, it will attempt to load it from WEB-INF/classes/my/pkg/queries.xml.
You can also put the queries into the root of your class hierarchy (WEB-INF/classes/queries.xml) and load it like so:
MyServlet.class.getResourceAsStream("/queries.xml")
Then it will expect the file in WEB-INF/classes/queries.xml.
Alternatively, if you want to leave the file where it is, just use the servlet context to get the input stream:
getServletContext().getResourceAsStream("/WEB-INF/queries.xml")
It isn't valid to get a real path and then treat that as part of a resource path. It isn't. Make up your mind. Just do
getResourceAsStream("/WEB-INF/classes/.../queries.xml")
where the ... is the package of MyServlet, and put the resource file there.
I created a JSP Tag Handler class in Java and defined it in XML in the .tld file.
In my .jsp file, I declared the tag and defined its attributes - one of them being the path to the file that is to be read.
When passing the virtual path to the ServletContext's getRealPath method, it returns this weird, non-existent file path. When I tried to just simply pass the real file path outright to the tag, it gives me some weird "access denied" message.
What makes this more confusing to me, is that I managed to accomplish the same thing without tags but having the HttpServlet handle the work all by itself. The HttpServlet has no problems with carrying out this task, but the jsp tag class can't and I don't know why.
Can someone with any experience in IO tasks and writing custom java tags help me on this one?
Update:
Here's what the file directory of my website looks like (where ".." represents that there are additional files and folders within that directory that aren't shown). Also note, that using "<" and ">" causes the text to disappear on this forum, so I couldn't use them to specify a general label for the directory but that whatever is in all caps isn't actually the name of the directory:
ROOT/Accounts/.. (location of
Login.jsp)
ROOT/data/.. (location of
datafile to be read)
ROOT/.. (other
folders)
Since, the project is named "Epsilon" in Eclipse, the resulting URL for any one of these directories is:
http://localhost:8080/Epsilon/Accounts/..
http://localhost:8080/Epsilon/data/..
http://localhost:8080/Epsilon/..
In the jsp file, I define it as follows:
<tags:HeaderContent path="/data/header.markup" id="topMenu"></tags:HeaderContent>
*Note the attribute "path", because it's really important!
In the Java class, in the doStartTag() method, I have the following:
ServletContext context = pageContext.getServletContext();
JspWriter out = pageContext.getOut();
String realPath = context.getRealPath(context.getContextPath()
+ path);
out.println(getHeaderContent(realPath).toString());
The context.getContextPath() and the path variables both end up being
"/Epsilon/data/header.markup".
I pass those two concatenated strings as arguments for the ServletContext object's getRealPath method. What the realPath String results in is the following:
"Z:\Dropbox\workspaces\Sites.metadata.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\Epsilon\Epsilon\data\header.markup"
I really don't know why it returned the metadata folder, but this is not where the file is actually located. And, as I already mentioned earlier, the HttpServlet didn't encounter this same problem but the JSP tag's class did.
You should not include the context path in the getRealPath() call. The context path is only represented in URLs and not in the local disk file system. The getRealPath() expects a relative local disk file system path relative to the webcontent root.
context.getRealPath(path);
As to why it's located in Eclipse's metadata folder, that's just because you deployed and run this from inside Eclipse. This should not harm, this is exactly what the getRealPath() should be taking care of.