I'm currently working on a Java project where I have a set of data which I wish to output in several custom formats. I have a class for each format, which takes the raw data and converts it accordingly. However, to begin with I am only implementing two or three of these formats, but wish to allow more formats to be added at a later date without having to do a massive rebuild of the application.
My idea was to create a DLL for each of the format classes, and have my application pass the data to be converted to each of these. This way, I can create a DLL later on and have my main application accessing it. (I would gladly listen to any alternative ways of doing this, as someone who has done this in C++/C# before this felt like the logical solution but it may not be applicable to Java)
My problem is that I have absolutely no idea how to do this - in C++/C# I could write this in a few lines of code but I'm not sure how it works with Java. At the risk of asking a terribly vague question, how can I do this?
Answers are greatly appreciated and cookies and tea will be offered. :)
Thanks in advance, M
Edit: Sorry, just to add: I am also unsure how to create the DLL, which must be in Java for this project, to be read in the first place. Thanks. :)
Rather than using a DLL per se, it seems like what is wanted is a plugin architecture of some sort.
One reason why I wouldn't recommend using a DLL unless it is necessary is that linking Java code with native code will require using the Java Native Interface (JNI) which would probably require more effort than a pure Java solution.
One relatively simple way to do so is to use the reflection capabilities of Java.
From the information given, I would probably go along the lines of the following:
Class.newInstance method can instantiate objects from class files loaded by the ClassLoader.)With these steps, it would be possible to implement a simplistic plugin which wouldn't require a full rebuild when support for a new format is required.
Step 1: Define the interface
Let's say we end up with an interface like the following:
public interface Outputter {
public void write(Data d);
}
Step 2: Make an implementation class
Then, we'll make an implementation class.
public class TextOutputter {
public void write(Data d) {
// ... output data to text
}
}
Then, compiling the above, we'll end up with a class file called TextOutputter.class.
Step 3: Make the class available from the classpath
When running the main application, we'll need to have the above TextOutputter.class in the classpath. Normally, one would tell the JVM a list of places to consider as the classpath, and that should include the above class file.
Once that is done, we should be able to load the above class using reflection.
Step 4: Dynamically load the class using reflection
Now, when we actually want to load the above class, we'd do something like the following:
// Note: We load the class by specifying the fully-qualified class name!
Class<?> clazz = Class.forName("TextOutputter");
// Then, we instantiate the class.
// Note that the following method will call the no-argument constructor.
Outputter outputter = clazz.newInstance();
// Now, we can give data to the TextOutputter object that we loaded dynamically.
outputter.write(...);
The Class.forName method is used to attempt to find the TextOutputter class from the default ClassLoader. Once we obtain the class as a Class representation, we can then instantiate an object of that class.
Instantiating the object can be performed by using the Class.newInstance method. If something other than the no-argument constructor should be used, the Constructor of the class would have to be obtained proceed to instantiate the object from there.
The object instantiates via reflection is then placed into a Outputter variable, so the write method can be called on the TextOutputter.
Adding more formats would entail the above process, but changing the fully-qualified class name (e.g. for String, the FQCN is java.lang.String) is all that is needed to load up a different class.
In a nutshell, that's what it will take to dynamically load class files and use it from your application.
(Just as a side note, I did not actually compile the above code, so there may be some errors here and there, but I hope I could illustrate the process it will take.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With