How instantiate classes dynamically based on configuration in Java - 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.

Related

Is there a way to get objects from another .jar-file by using a String database(without using reflection)?

I just got Strings (out of a database), which are not even the names of the objects (but properties of them) and have to work on these classes and objects.
EDIT: To make things clear:
I got 1 jar (the programm core), in which i load/open many different jar-file.
In the core, i got a class which is accessing a database with all classnames and classobject-properties (not the objectnames, but properties of the objects) of all other jar files, saved as Strings.
Now i want to get access to the Objects in the jars by using these Strings.
First I call the classloader with the classnames.
Now i want to open/load another jar out of this jar and transfere data to it. Like jumping from one jar to another jar.
There are many problems in it, which are confusing me. For example i cant edit the contructors(/or create new ones), because it would destroy the functionality of our software.
Question: Is there a way to get the real objects with just using Strings?
Would love to find a way around Reflections.
I think you main choices are to:
Use reflection
Access the Dog instance object by referring to it as an Animal object (your base class), and override the desired methods in Dog.
Make all classes such as Dog implement an interface
The base class method and the interface method both mean you will have to plan out your desired properties, and then make each implementing class fit into that model.
If you do add the methods to Animal or a new interface, you would want to convert your object fields (eg., hairLength) to getters (int getHairLength();) and setters.
In your code, you can always use the instanceof operator to see if the unknown object implements or derives from your known class.

Why would a framework implement factory methods to create simple primitive objects?

I'm working with a Java framework that uses factory methods to instantiate simple objects. For example they have their own Double object that you must instantiate using syntax like Double.make(). I'm not too familiar with factories but aren't they supposed to be used with more complex objects? Why have a factory method that's going to make me the same object every time? Am I missing something here?
One reason I can think of to use factory method pattern in this scenario is to be able to control the object creation for class Double. I.e. it may return a new Double object everytime a call is made by invoking api Double.make() or it can choose to reuse an existing object and return that (even like a singleton pattern). Essentially this way you keep the control of object generation in the Double class and clients of that class don't need to know how the object is getting created that they are using.
You can use a factory method regardless of the complexity of the object, as you are finding here. Without seeing any code or even knowing what framework you are using, or what project you are working on, I can't deduce why the original designer did what they did. But assuming you must use the framework, then getting used to it should be your best course I guess.

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).

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

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.

What is the prefered way to manage and distribute configurations to many different class instances of differing class types (in Java)?

What is the prefered way to manage and distribute configurations to many different class instances of differing class types (in Java)?
In other words, I have an Application class that stores config options in a Configuration class in a static variable. This allows all the other classes in the application to simply call Application.config to fetch config values.
I'd like to allow there to be multiple instances of Application with associated Configuration's per Application instance. This is were I am lost... Is my only option to cascade a Configuration reference to every other class (via constructors and setters)? Or is there another way?
Seems like a single configuration for an Application instance and all it's supporting instances isn't unreasonable, but the requirement to cascade the single configuration reference just seems like such a burden.
Thanks,
Chenz
It sounds like you just found out that what you thought was global state is not really global.
There are several solutions,
the one you outlined,
use a dependency injection framework like Guice to scope configuration.
use ClassLoader voodoo to create multiple "global" configurations in the same VM.
The best solution is really to thread your configuration through manually or via DI, but since you asked for other options, the third solution is to change your main class to create a UrlClassLoader per-instance of the application that points to your jars. This allows you to have multiple different versions of the Application class and its associated Condiguration class side-by-side in the same VM.
EDIT:
To do the classloader voodoo, you main looks something like this
URLClassLoader application1Loader = new ClassLoader(/* URLs to common Jars and the config files for instance 1*/);
URLClassLoader application2Loader = new ClassLoader(/* URLs to common Jars and the config files for instance 2*/);
// Assuming you have a wrapper for your application that you can run() to get it going
// in its own thread via reflection.
Class<? extends Runnable> app1Class = application1Loader.loadClass("my.pkg.MyApplicaion")
.asSubclass(Runnable.class);
// newInstance() is problematic but I want this code to be brief.
app1Class.newInstance().run();
Class<? extends Runnable> app2Class = application2Loader.loadClass("my.pkg.MyApplicaion")
.asSubclass(Runnable.class);
app2Class.newInstance().run();
UPDATE: The my.pkg.MyApplicaion class must not be in the JVM's classpath.
I generally use Spring and define my config in associated XML files, which I load wherever needed using the spring API's.
A quick and dirty method to pass around app config without rewriting all your API's would be to use the singleton pattern. You could get a reference to the config using AppConfig.getInstance() where ever required.
if your objects know what Application they belong to, no problem: just make configuration be non-static.
If your Application instances are separate threads, no problem: put configuration on ThreadLocal
If there is some kind of namespace associated with each Application, and child objects know about it, no problem: store a static Map somewhere
if none of the above holds, you're kinda screwed...

Categories

Resources