Is it possible to load a class from a jar file and then create an object from it?
Note: The jar file is not there when the program is compiled, but is added by the user later and is loaded in when the user starts the program.
My code goes likes this: The user has a jar file with nothing but a compiled java class in it. The user then puts this jar file in a directory and starts my program which looks through the directory and finds this jar file. It then loads this jar file and creates a class from it which it then creates an object from that and adds it to an array.
I have everything down except for creating a class from the jar file (loaded as a java.io File) and then creating and object from that class.
Any help? Thanks.
You're looking for Class#forNameand Class#newInstance methods.
This link provides a good example about initializing a class knowing its name (extracted from the link):
Class c = Class.forName("com.xyzws.AClass");
AClass a = (AClass)c.newInstance();
A good example for these situations is using JDBC (as the link also points out), because you initialize an object of the db engine driver you want to connect. Remember than this driver comes from an imported jar into your project, it could be a jar to MySQL, Oracle or MSSQL Server, you just provide the driver class name and let the JDBC API and the jar handles the SQL work.
Class.forName("org.gjt.mm.mysql.Driver");
Connection con = DriverManager.getConnection(url, "myLogin", "myPassword");
Also, for this specific problem loading the jar dynamically, there are question and answer:
How should I load Jars dynamically at runtime?
A simpler? way would be for the user to put the jar file in the classpath.
That way your code will have access to the class that will be loaded by the jvm
Edit: Even #Luiggi's answer assumes that the jar is in the classpath
Related
I am new in Netbeans, I am doing project which is manipulate with MS Access Database (.mdb or .accdb).
Inside my code, I need to write the whole directory of my database file in order to connect it, like:
conn = DriverManager.getConnection("jdbc:ucanaccess://D:/abc/def/db.accdb");
Which folder should I put my database file in so that I no need to write the whole directory to connect it, like: conn = DriverManager.getConnection("jdbc:ucanaccess://db.accdb");?
You do not want to hardcode a database path in your code: good point!
Unfortunately, it looks like UCanAccess offers no special folder to automagically find the database: it just tries to find it where it is declared. So if you use a relative path, it will rely on Java processing and Javadoc for File class says:
By default the classes in the java.io package always resolve relative pathnames against the current user directory. This directory is named by the system property user.dir, and is typically the directory in which the Java virtual machine was invoked.
If you use shortlinks under window, you can specify a start directory in the shortlink, but I would not rely on it because it is not a common usage even on Windows.
So the correct way (and common usage) is to use an environment variable. This variable would contain the database fullpath if you have no other external configuration value, or it will contain the path of a property file that in turn contains other configuration values.
I have completed a program in eclipse and now I would like to export it as a single runnable jar file. The program contains a resource folder with images and text files in it. This is located beneath the source folder.
The res file is not added to the build path however when I run the program in Eclipse it still works.
The thing that is confusing me is that the res file is being saved into the runnable jar file when I export it as I can open the Jar file with WinRar and I see the folder is there with all the objects in it. But when I run the problem it stops at the point that the resource folder is referenced. To add to my confusion when I manually copy and paste the res folder next to where the runnable jar file is saved and run the program it works exactly as it should do.
Now I know this is something to do with how I reference the files in my code. At the moment I have it like this
reader = new LineNumberReader(new FileReader("res/usernames.txt"));
This works exactly how I want and accesses the res folder without any exceptions - in Eclipse and when I move the resource folder next to the Jar file.
I would like it to work normally but without having a folder outside of the Jar file I would like it all encapsulated in one Jar file.
I did a lot of research and what seems to be a common fix - may I add I don't really know how it works but everyone seems to mention it - is to somewhere use:
myClass().getResource()
When I create a new FileReader it needs a String input however when I use myClass().getResource() it returns a resource and not a string. I also don't have a clue how it is meant to reference the resource folder. Should I move the resource folder into the source folder?
Does anyone know how I can reference the resource folder from within the runnable jar file?
Sorry for rambling question I know what I want for my final product but I'm getting confused by the build paths and referencing from within classes and I have searched online for a long time trying to figure it out.
Resources, when you deploy your software, are not deployed as files in a folder. They are packaged as part of the jar of your application. And you access them by retrieving them from inside the jar. The class loader knows how to retrieve stuff from the jar, and therefore you use your class's class loader to get the information.
This means you cannot use things like FileReader on them, or anything else that expects a file. The resources are not files anymore. They are bundles of bytes sitting inside the jar which only the class loader knows how to retrieve.
If the resources are things like images etc., that can be used by java classes that know how to access resource URLs (that is, get the data from the jar when they are given its location in the jar), you can use the ClassLoader.getResource(String) method to get the URL and pass it to the class that handles them.
If you have anything you want to do directly with the data in the resource, which you would usually do by reading it from a file, you can instead use the method ClassLoader.getResourceAsStream(String).
This method returns an InputStream, which you can use like any other InputStream - apply a Reader to it or something like that.
So you can change your code to something like:
InputStream is = myClass().getResourceAsStream("res/usernames.txt");
reader = new LineNumberReader( new InputStreamReader(is) );
Note that I used the getResourceAsStream() method from Class rather than ClassLoader. There is a little difference in the way the two versions look for the resource inside the jar. Please read the relevant documentation for Class and ClassLoader.
Suppose I had a directory containing resource files stored somewhere within the "src" source directory, containing things like templates, config files, etc.
I'm aware that from a Servlet I can access files by name like:
File file = new File(ServletContact.getResource("some/namespace/filename.txt").getPath());
And from a non-Servlet I can do:
File file = new File(Object.class.getResource("some/namespace/filename.txt").getPath());
But the problem is that I have code that needs to access these resource files and can be run independent of the runtime environment. e.g. Some code uses templates from within a servlet (under Tomcat 7). Other code runs as a Quartz background job and works with templates. If I try the Object.class.getResource() method in a Tomcat servlet, it returns null.
How can I access resources files in a safe way regardless of runtime environment, app engine, etc.?
To read file from classpath you can use:
getClass().getClassLoader().getResourceAsStream("path/to/resource");
Also there is simple and useful Spring utility ClassPathResource class:
Resource resource = new ClassPathResource("path/to/resource");
I would use any class (e.g. domain class) from your project, use getClassLoader() or getContextClassloader() and provide the path to your resource. Should work.
This is the well known problem of loading resources from a jar file. This is not the first time I've tried to do this, but now it doesn't work the way I expect it to.
Normally I try to load the Resources with this.getClass.getResource("foo.png"), or getResourceAsStream()and it works. Now however it does not. The Resource is always null.
If I let System.out.println(this.getClass.getResource("")) print me the path (from eclipse) it shows /path/to/eclipseproject/package/structure/. Running this from a jar it just shows rsrc:package/structure
If I recall correctly this should print the path to the jar. Furthermore I thought this would print the package structure in both cases. Am I doing something wrong?
Here is the thing...
When Extracting the file from the Jar use:
this.getClass.getResource("/foo.png")
When running from a runnable Jar use, to reference an external file in the Jar folder path:
this.getClass.getResource("foo.png")
// When running this from Eclipse, it would refer to files in project root!
I have a code in the lower level determining where I'm running from to determine the correct path.
Doe this get the path you need?
this.getClass().getClassLoader().getResource("<your class name>.class").getPath();
See also this question for more on this issue.
Unless you prepend the path to the resources with '/', Class.getResource() will search for the resource in class package. E.g.: tld.domain.Foo.class.getResource("Bar.txt") will search for tld/domain/Bar.txt
Check the URLClassLoader for all the gory details, but it really depends on whether you are trying to access a ressource in the jar,
using a class loaded inside the same jar, in this case your file 'root' is the root of the jar
using a class loaded outside the jar (your eclipse case) where the root is your 'working directory'
To access resources inside a jar from outside, you should use something like
URL url = new URL( "jar", "", "file:" + jar.getCanonicalPath( ) + "!/" + localPathResource );
url.openStream(...)
This answer provides an explanation of how to load class resources from JAR files, even when the class is not in the JAR file and not in the Class-Path specified in the JAR file's manifest. There are also links to code.
I'm trying to read signals from a PLC trough Java, and for that I think I should use a "bridge" called JEasyOPC. The problem is that I don't how to install it, and make it work.
I followed a tutorial but I get always stuck at the same problem. I get an error:
Property file javafish.clients.opc.JCustomOpc doesn't exist. System terminated.
If you are using JEasyOpc inside a web application (e.g. inside a .war file), then you may need to do the following
Replace this line in PropertyLoader.java with
ClassLoader cl = ClassLoader.getSystemClassLoader();
with
ClassLoader cl = PropertyLoader.class.getClassLoader();
Also, make sure you specify -Djava.library.path=[path to folder containing dll]
The property file is in a directory called resources. If you have the jeasyopc.jar in a directory, /jeasy, then the resources directory should be in a directory such as /jeasy/resources. You need to put this on your classpath. This can be done in your environment or at run time with something like java -Djava.ext.dirs=.:/jeasy/resources .