How to programmatically instantiate dynamically loaded class from values in a file? - java

I have basic knowledge of Java's reflection API - therefore, this is not only a question of how, it's a question of whether it's possible and whether I'm going about a solution the best way.
We're doing some acceptance testing of multiple, interrelated projects; each of these projects retrieve data from a MongoDB store using an in-house abstraction API. To facilitate this testing, each component needs some pre-loaded data to be available in the database.
I'm building a command-line tool to accept a DTO (pre-compiled class binary), for loading of multiple instances using the morphia ORM library. I would like each member of our team to be able to run the generator passing in via cli their DTO (in jar or directory form), and a file (csv or otherwise) for instantiating a desired amount of records.
I have the class loading working fine with URLClassLoader. Now I'm trying to instantiate an instance of this class using data from a file.
Is this possible? Would serialized objects be a better approach?

That's perfectly possible using the Java Reflection API :
Load Class instance by name (Class.forName(className), you don't really need the ClassLoader instance)
Grab Constructor instance of constructors have parameters and invoke newInstance(Object... args) on this constructor instance to create an instance of your DTO class.
Invoke getDeclaredFields() on your Class instance and iterate over them to set their values (field.set(instance, value)). Make sure to invoke field.setAccessible(true) to be able to access private fields.

If by "serialized objects" you mean canned instances, then no, by loading properties from a text file you allow much easier tweaking of test data (if that's a goal), including the number of objects.
But sure, it's possible; unmarshal the data from the input file and use it to initialize or construct the object in question like you would in regular code.

Related

How instantiate classes dynamically based on configuration in Java

Is there any way to change which class is going to be instantiate in Java (in Spring If it is possible).
For example, using Refection and reading configuration from a database it could be possible but Reflection is heavy technique because the number of created object is going to be very high.
So that, what I need is create objects in runtime based in a external configuraciĆ³n. If I change the configutation, in runtime and without redeploying I would like yo create objects of a diferent class than before. For example, a process is creating objects of class A, an after changing the configutation without redeploying, the process must create objects of class B
You can use newInstance method.
Class.forName("<<your class name>>").newInstance()
But you need to typecast the new instance.

How to implement an xml saveable/loadable class?

I would like to create a class, which would be loadable and saveable to an XML file. I want to use one class which is doing the loading task and I want to integrate it with the actual class that I want to save and load, everything seems to be doable up to the point where JAVA doesn't allow the class instance to be change from within the class, i.e. there is no:
this = JAXBLoader.load();
So currently that's the problem I'm facing.
And I want to be able to control the loading and saving it via the public methods from the class itself, so that from the outside I don't need any factories or managers to load it. Currently the only solution I've seen to this was if I extended the class that I want to save as an xml and then delegate all the methods to the intance of the actual class and then when loading a new instance from the file, the instance would get replaced. But it is a bit of overhead to have to delegate all of the methods, especially pain in the ass if you need to add new methods to the class and have multiple implementations...
So are there any good practices or patterns on achieving something similar or solving the problem I demonstrated above? Actually I'm open, if somebody can overall share what are the best ways to do class saving and loading the easiest ways I would really glad about it.
I'm not quite sure why do you want to avoid external factories and managers. For me it seems quite natural to extract serialization and not handle it in the model classes themselves. But okay.
What I understood is that your core problem is to load data into this instance. Here's a simple way to achieve this with JAXB.
I'm the author of JAXB2 Basics, a plugin package for JAXB/XJC. It contains the copyable plugin which generates a few copyTo methods in the schema-derived classes.
This will give you methods like copyTo(Object target). With this you can first unmarshal data from XML into some temporary instance and then copyTo(this). Something like:
MyType temporaryInstance = unmarshaller.unmarshal(source, MyType.class).getValue();
temporaryInstance.copyTo(this);
You can add this method to your schema-derived code via code injection or by subclassing.

A better way to call static methods in user-submitted code?

I have a large data set. I am creating a system which allows users to submit java source files, which will then be applied to the data set. To be more specific, each submitted java source file must contain a static method with a specific name, let's say toBeInvoked(). toBeInvoked will take a row of the data set as an array parameter. I want to call the toBeInvoked method of each submitted source file on each row in the data set. I also need to implement security measures (so toBeInvoked() can't do I/O, can't call exit, etc.).
Currently, my implementation is this: I have a list of the names of the java source files. For each file, I create an instance of the custom secure ClassLoader which I coded, which compiles the source file and returns the compiled class. I use reflection to extract the static method toBeInvoked() (e.g. method = c.getMethod("toBeInvoked", double[].class)). Then, I iterate over the rows of the data set, and invoke the method on each row.
There are at least two problems with my approach:
it appears to be painfully slow (I've heard reflection tends to be slow)
the code is more complicated than I would like
Is there a better way to accomplish what I am trying to do?
There is no significantly better approach given the constraints that you have set yourself.
For what it is worth, what makes this "painfully slow" is compiling the source files to class files and loading them. That is many orders of magnitude slower than the use of reflection to call the methods.
(Use of a common interface rather than static methods is not going to make a measurable difference to speed, and the reduction in complexity is relatively small.)
If you really want to simplify this and speed it up, change your architecture so that the code is provided as a JAR file containing all of the compiled classes.
Assuming your #toBeInvoked() could be defined in an interface rather than being static (it should be!), you could just load the class and cast it to the interface:
Class<? extends YourInterface> c = Class.forName("name", true, classLoader).asSubclass(YourInterface.class);
YourInterface i = c.newInstance();
Afterwards invoke #toBeInvoked() directly.
Also have a look into java.util.ServiceLoader, which could be helpful for finding the right class to load in case you have more than one source file.
Personally, I would use an interface. This will allow you to have multiple instance with their own state (useful for multi-threading) but more importantly you can use an interface, first to define which methods must be implemented but also to call the methods.
Reflection is slow but this is only relative to other options such as a direct method call. If you are scanning a large data set, the fact you have to pulling data from main memory is likely to be much more expensive.
I would suggest following steps for your problem.
To check if the method contains any unwanted code, you need to have a check script which can do these checks at upload time.
Create an Interface having a method toBeInvoked() (not a static method).
All the classes which are uploaded must implement this interface and add the logic inside this method.
you can have your custom class loader scan a particular folder for new classes being added and load them accordingly.
When a file is uploaded and successfully validated, you can compile and copy the class file to the folder which class loader scans.
You processor class can lookup for new files and then call toBeInvoked() method on loaded class when required.
Hope this help. (Note that i have used a similar mechanism to load dynamically workflow step classes in Workflow Engine tool which was developed).

Adding a field to Java class

Looked at using CGLib, ASM, BCEL (aspect) and Javassist to add a field to a class during runtime....
Just to get my head straight it looks like these bytecode manipulators don't update the actual class rather allow the user to only dump the modification (like with CGLib and the writeFile method). Was hoping I would find a solution that (a) loaded the class (rather than doing an InputStream with BCEL) and (b) updated the class.
Maybe this is normal? Do people usually create a proxy and pass the proxy around?
What I want to do is to add a field (note: not a property via get/set methods) before passing the object along to a framework that looks for fields (not properties) with a particular annotation. So "clients" are creating my target classes that I want to inject with an extra field. Intercepting with AOP calls to a service layer where I want to manipulate these objects.
You can redefine classes with Intrumentation. However a common limiation is that you cannot change the fields used. This is because you cannot change the contents of a object (or add to it) once it has been created.
In your case you can,
create a proxy as you suggest, however proxies need to be interfaces.
create a subclass which has the additional field(s)
add the field before the class has loaded.

Design of a standalone class/framework requiring external data

For the sake of an example, I have a class called FileIdentifier. This class:
Has the method identify which accepts a File and returns a String representing the type.
Requires external data since new file formats are a possibility.
How could this class be written so it could used in any project while remaining unobstrusive? Overall, how is this aspect usually handled in standalone frameworks that require configuration?
That all depends on how you identify the file type. From your question I would assume that it's not a process as trivial as parsing for the file extension...
That said maybe you could just use an external XML file, or INI, or db table etc. that maps file types and just have the class read that data and return whatever... (You would actually want to use a few classes to keep things clean.) That way only the external data would need to be updated and the class remain unchanged.
Try with a chain of responsibility.
Each instance in the chain is from a different class that manages a single file type. The file is passed down in the chain, and as soon as an instance decides to manage it, the chain stops and the results are returned back.
Then you just would have to build the chain in the desired order (maybe with more common file types at the top), provide default classes that manages some file types in your framework. This shoud be also easy to extend in your applications, it's just a matter of writing another subclass of the chain that manages your new user-defined file types.
Of course your base class for the chain (the Handler, as called by dofactory.com) could provide useful protected methods to its subclasses in order to make their work easier.

Categories

Resources