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);
Related
In my application I load resources in this manner:
WinProcessor.class.getResource("repository").toString();
and this gives me:
file:/root/app/repository (and I replace "file:" with empty string)
This works fine when I run my application from the IDE, but when I run the jar of my application:
java -jar app.jar
The path becomes:
jar:/root/app.jar!/repository
is there any way to solve this problem?
I'll use the "repository" dir name in order to create this:
ConfigurationContext ctx = (ConfigurationContext) ConfigurationContextFactory.createConfigurationContextFromFileSystem(repositoryString, null);
In the same manner, I'll get one file name (instead of a dir) and I'll use it this way:
System.setProperty("javax.net.ssl.trustStore", fileNameString)
It sounds like you're then trying to load the resource using a FileInputStream or something like that. Don't do that: instead of calling getResource, call getResourceAsStream and read the data from that.
(You could load the resources from the URL instead, but calling getResourceAsStream is a bit more convenient.)
EDIT: Having seen your updated answer, it seems other bits of code rely on the data being in a physical single file in the file system. The answer is therefore not to bundle it in a jar file in the first place. You could check whether it's in a separate file, and if not extract it to a temporary file, but that's pretty hacky IMO.
When running code using java -jar app.jar, java uses ONLY the class path defined in the manifest of the JAR file (i.e. Class-Path attribute). If the class is in app.jar, or the class is in the class path set in the Class-Path attribute of the JAR's manifest, you can load that class using the following code snippet, where the className is the fully-qualified class name.
final String classAsPath = className.replace('.', '/') + ".class";
final InputStream input = ClassLoader.getSystemResourceAsStream( path/to/class );
Now if the class is not part of the JAR, and it isn't in the manifest's Class-Path, then the class loader won't find it. Instead, you can use the URLClassLoader, with some care to deal with differences between windows and Unix/Linux/MacOSX.
// the class to load
final String classAsPath = className.replace('.', '/') + ".class";
// the URL to the `app.jar` file (Windows and Unix/Linux/MacOSX below)
final URL url = new URL( "file", null, "///C:/Users/diffusive/app.jar" );
//final URL url = new URL( "file", null, "/Users/diffusive/app.jar" );
// create the class loader with the JAR file
final URLClassLoader urlClassLoader = new URLClassLoader( new URL[] { url } );
// grab the resource, through, this time from the `URLClassLoader` object
// rather than from the `ClassLoader` class
final InputStream input = urlClassLoader.getResourceAsStream( classAsPath );
In both examples you'll need to deal with the exceptions, and the fact that the input stream is null if the resource can't be found. Also, if you need to get the InputStream into a byte[], you can use Apache's commons IOUtils.toByteArray(...). And, if you then want a Class, you can use the class loader's defineClass(...) method, which accepts the byte[].
You can find this code in a ClassLoaderUtils class in the Diffusive source code, which you can find on SourceForge at github.com/robphilipp/diffusive
And a method to create URL for Windows and Unix/Linux/MacOSX from relative and absolute paths in RestfulDiffuserManagerResource.createJarClassPath(...)
Construct a URL, you can then load a resource (even in a jar file) using the openStream method.
I'm trying to access my properties file in a war. The code is working, but when i'm exporting the code into a war and use a POST (with an accepted input) using Fiddler, it cannot find the config.properties. (NullPointerException)
The input and webservice are running correctly. Just trying to figure out a way to edit my properties while using a war.
Some facts:
I've made a RetreivePropertiesClass. This uses:
properties.load(this.getClass()
.getResourceAsStream("/WEB-INF/config.properties"));
My properties file path:
/com.webapp/WebContent/WEB-INF/config.properties
I'm trying to use the properties data in:
String url = RetreiveProperties.getUrl();
String driver = RetreiveProperties.getDriver();
String username = RetreiveProperties.getUsername();
String password = RetreiveProperties.getPassword();
// line below causes the NullPointerException
Class.forName(driver);
Getter used:
public static String getDriver() {
return driver = properties.getProperty("jdbc.driver");
}
When the war is deployed, the properties file is in:
webapps\com.webapp1\WEB-INF\config.properties
Config.properties:
jdbc.url = jdbc:postgresql://127.0.0.1:2222/gisdb
jdbc.driver = org.postgresql.Driver
jdbc.username = postgres
jdbc.password = admin
I already tried to work out the examples given here and here. Keeps giving the NullPointerException because the properties file isn't loaded.
Can anyone push me in the right direction?
Cheers!
If you are going to load the properties file from the classpath, it must be in the WEB-INF/classes directory inside of your war. (Or inside a jar inside of WEB-INF/lib ). The WEB-INF directory itself is not on the classpath.
If you make sure the file ends up as WEB-INF/classes/config.properties your above code should work if you change the getResourceAsStream call to getResourceAsStream("/config.properties")
If the method is a static method, the getClass() method will be failed, and prompts “Cannot make a static reference to the non-static method getClass() from the type Object“.
Instead, you should use CurrentClass.class.getClassLoader().getResourceAsStream.
Source: here
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()+"/";
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 want to write a program to dynamically invoke a method inside another Java class (uncompiled) whose file name with location is given. For this I've used the following code but it wasn't working.
//folder location of my java file to be loaded
String url = "C:/Temp/testcases/test.java";
//name of the java file to be loaded
String classname = "test.java";
this.class.classLoader.rootLoader.addURL(new URL(url+str));
Class.forName(str).newInstance();
The above instance is unable to invoke the method inside the java file that I want to load dynamically. What is the error in it?
The class loader is only able to load compiled classes. It's not able to open Java source files, compile them on the fly, and load their class.
Moreover, a class name is not the same as a file name.
I agree with your answer. The error in the above code is with the new URL(C://...). Had I mentioned the package name wrt path correctly, it should have worked. Anyways I was dealing with groovy files so I found this code more efficient than the normal class.forname that I've mentioned above.
def sourceString = (new File(C:/xyz.groovy)).getText()
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(sourceString);
template = groovyClass.newInstance()