I have an application that takes some input and generates configuration files as output. Since the exact input or output format could change over time, I defined two interfaces: Importer and Exporter.
Each concrete importer or exporter could have different parameters that need to be initialized to work. For example, if the import data is coming from a CSV file you only need the path of the file, but if the data is coming from a database then you need a connection string, username, password, etc. Same thing for exporters.
My implementation currently is:
public interface Importer {
public void setup(Map<String,String> params);
public List<ConfigEntry> getList();
}
public interface Exporter {
public void setup(Map<String,String> params);
public void writeDocument(List<ConfigEntry> entries) throws IOException;
}
The setup method needs to be called before getList() or writeDocument() can be called. I use a Map to keep parameters because each child class can have different parameters.
Is using JavaBean style parameter initialization a preferred way? That means, adding setConnnectionString(), setCSVFilePath(), setX() to each child class.
What are the advantages, disadvantages of these approaches?
There are two obvious downsides to map-based approach:
Absence of well-defined parameter names. Yes, you could define them as constants somewhere but you'd still need to check that parameter name is valid as passed.
Absence of well-defined parameter types. Even worse then above - if I need to pass an integer I'd have to convert it to String and you'll have to parse it (and deal with possible errors). Can be somewhat mitigated by using Map<String,Object> and auto-bounding but then you'd still need to validate appropriate types.
Setter-based approach has only one downside - it can't be done. That is, it can't be reliably done by using setters ALONE - you need to supplement it with some kind of init() or afterPropertiesSet() method that will be called after all setters and will allow you to perform additional (co-dependent) validation and initialization steps.
Also, something like this practically begs for some kind of Dependency Injection framework. Like Spring, for example.
I wouldn't say that passing a Map (or Properties) object in the constructor is necessarily preferred over child class specific setter, or vice versa. Which approach is best depends on how you are going to instantiate the classes.
If you are going to instantiate the classes directly from Java then the Map approach tends to be neater, especially if you have a good way to assemble the maps. (For example, loading a Properties object from a property file.) The 'setters' approach forces you to write code against each of the child class APIs.
On the other hand, if you are going to instantiate the classes using some container framework that supports "wiring", "inversion of control" or the like (e.g. Spring, PicoContainer, JavaBeans, etc), then setters are generally better. The framework typically takes care of when and how to instantiate the classes and call the setters, using reflection under the hood to do the work.
So the answer is ... it depends ...
Related
The no-argument constructor is a
requirement (tools like Hibernate use
reflection on this constructor to
instantiate objects).
I got this hand-wavy answer but could somebody explain further? Thanks
Hibernate, and code in general that creates objects via reflection use Class<T>.newInstance() to create a new instance of your classes. This method requires a public no-arg constructor to be able to instantiate the object. For most use cases, providing a no-arg constructor is not a problem.
There are hacks based on serialization that can work around not having a no-arg constructor, since serialization uses jvm magic to create objects without invoking the constructor. But this is not available across all VMs. For example, XStream can create instances of objects that don't have a public no-arg constructor, but only by running in a so-called "enhanced" mode which is available only on certain VMs. (See the link for details.) Hibernate's designers surely chose to maintain compatibility with all VMs and so avoids such tricks, and uses the officially supported reflection method Class<T>.newInstance() requiring a no-arg constructor.
Erm, sorry everyone, but Hibernate does not require that your classes must have a parameterless constructor. The JPA 2.0 specification requires it, and this is very lame on behalf of JPA. Other frameworks like JAXB also require it, which is also very lame on behalf of those frameworks.
(Actually, JAXB supposedly allows entity factories, but it insists on instantiating these factories by itself, requiring them to have a --guess what-- parameterless constructor, which in my book is exactly as good as not allowing factories; how lame is that!)
But Hibernate does not require such a thing.
Hibernate supports an interception mechanism, (see "Interceptor" in the documentation,) which allows you to instantiate your objects with whatever constructor parameters they need.
Basically, what you do is that when you setup hibernate you pass it an object implementing the org.hibernate.Interceptor interface, and hibernate will then be invoking the instantiate() method of that interface whenever it needs a new instance of an object of yours, so your implementation of that method can new your objects in whatever way you like.
I have done it in a project and it works like a charm. In this project I do things via JPA whenever possible, and I only use Hibernate features like the interceptor when I have no other option.
Hibernate seems to be somewhat insecure about it, as during startup it issues an info message for each of my entity classes, telling me INFO: HHH000182: No default (no-argument) constructor for class and class must be instantiated by Interceptor, but then later on I do instantiate them by interceptor, and it is happy with that.
To answer the "why" part of the question for tools other than Hibernate, the answer is "for absolutely no good reason", and this is proven by the existence of the hibernate interceptor. There are many tools out there that could have been supporting some similar mechanism for client object instantiation, but they don't, so they create the objects by themselves, so they have to require parameterless constructors. I am tempted to believe that this is happening because the creators of these tools think of themselves as ninja systems programmers who create frameworks full of magic to be used by ignorant application programmers, who (so they think) would never in their wildest dreams have a need for such advanced constructs as the... Factory Pattern. (Okay, I am tempted to think so. I don't actually think so. I am joking.)
Hibernate instantiates your objects. So it needs to be able to instantiate them. If there isn't a no-arg constructor, Hibernate won't know how to instantiate it, i.e. what argument to pass.
The hibernate documentation says:
4.1.1. Implement a no-argument constructor
All persistent classes must have a default constructor (which can be non-public) so that Hibernate can instantiate them using Constructor.newInstance(). It is recommended that you have a default constructor with at least package visibility for runtime proxy generation in Hibernate.
The hibernate is an ORM framework which supports field or property access strategy. However, it does not support constructor-based mapping - maybe what you would like ? - because of some issues like
1º What happens whether your class contains a lot of constructors
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) { ... }
public Person(String name) { ... }
public Person(Integer age) { ... }
}
As you can see, you deal with a issue of inconsistency because Hibernate cannot suppose which constructor should be called. For instance, suppose you need to retrieve a stored Person object
Person person = (Person) session.get(Person.class, <IDENTIFIER>);
Which constructor should Hibernate call to retrieve a Person object ? Can you see ?
2º And finally, by using reflection, Hibernate can instantiate a class through its no-arg constructor. So when you call
Person person = (Person) session.get(Person.class, <IDENTIFIER>);
Hibernate will instantiate your Person object as follows
Person.class.newInstance();
Which according to API documentation
The class is instantiated as if by a new expression with an empty argument list
Moral of the story
Person.class.newInstance();
is similar To
new Person();
Nothing else
Hibernate needs to create instances as result of your queries (via reflection), Hibernate relies on the no-arg constructor of entities for that, so you need to provide a no-arg constructor. What is not clear?
Actually, you can instantiate classes which have no 0-args constructor; you can get a list of a class' constructors, pick one and invoke it with bogus parameters.
While this is possible, and I guess it would work and wouldn't be problematic, you'll have to agree that is pretty weird.
Constructing objects the way Hibernate does (I believe it invokes the 0-arg constructor and then it probably modifies the instance's fields directly via Reflection. Perhaps it knows how to call setters) goes a little bit against how is an object supposed to be constructed in Java- invoke the constructor with the appropriate parameters so that the new object is the object you want. I believe that instantiating an object and then mutating it is somewhat "anti-Java" (or I would say, anti pure theoretical Java)- and definitely, if you do this via direct field manipulation, it goes encapsulation and all that fancy encapsulation stuff.
I think that the proper way to do this would be to define in the Hibernate mapping how an object should be instantiated from the info in the database row using the proper constructor... but this would be more complex- meaning both Hibernate would be even more complex, the mapping would be more complex... and all to be more "pure"; and I don't think this would have an advantage over the current approach (other than feeling good about doing things "the proper way").
Having said that, and seeing that the Hibernate approach is not very "clean", the obligation to have a 0-arg constructor is not strictly necessary, but I can understand somewhat the requirement, although I believe they did it on purely "proper way" grounds, when they strayed from the "proper way" (albeit for reasonable reasons) much before that.
It is much easier to create object with a parameterless constructor through reflection, and then fill its properties with data through reflection, than to try and match data to arbitrary parameters of a parameterized constructor, with changing names/naming conflicts, undefined logic inside constructor, parameter sets not matching properties of an object, et cetera.
Many ORMs and serializers require parameterless constructors, because paramterized constructors through reflection are very fragile, and parameterless constructors provide both stability to the application and control over the object behavior to the developer.
Hibernate uses proxies for lazy loading. If you do no define a constructor or make it private a few things may still work - the ones that do not depend on proxy mechanism. For example, loading the object (with no constructor) directly using query API.
But, if you use session.load method() you'll face InstantiationException from proxy generator lib due to non-availability of constructor.
This guy reported a similar situation:
http://kristian-domagala.blogspot.com/2008/10/proxy-instantiation-problem-from.html
Check out this section of the Java language spec that explains the difference between static and non-static inner classes: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3
A static inner class is conceptually no different than a regular general class declared in a .java file.
Since Hibernate needs to instantiate ProjectPK independantly of the Project instance, ProjectPK either needs to be a static inner class, or declared in it's own .java file.
reference org.hibernate.InstantiationException: No default constructor
In my case, I had to hide my no-arg constructor, but because Hibernate I couldn't do it. So I solved the problem in another way.
/**
* #deprecated (Hibernate's exclusive constructor)
*/
public ObjectConstructor (){ }
Summarizing of what is below. It matters if you want to be JPA compatible or strictly Hibernate
Just look at official documentation: https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html#entity-pojo
Section 2.1 The Entity Class of the JPA 2.1 specification defines its requirements for an entity class. Applications that wish to remain portable across JPA providers should adhere to these requirements:
One point says:
The entity class must have a public or protected no-argument
constructor. It may define additional constructors as well.
However, hibernate is less strict in this:
Hibernate, however, is not as strict in its requirements. The differences from the list above include:
One point says:
The entity class must have a no-argument constructor, which may be
public, protected or package visibility. It may define additional
constructors as well.
More on that is right below:
https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html#entity-pojo-constructor
JPA requires that this constructor be defined as public or protected. Hibernate, for the most part, does not care about the constructor visibility, as long as the system SecurityManager allows overriding the visibility setting. That said, the constructor should be defined with at least package visibility if you wish to leverage runtime proxy generation.
What is best practice to restrict instantiation of the classes to only one class? Something like this but in Java.
Let's say there is Main class, then there are User, Admin, View, Data, Client etc. classes. Only 'Main' class should be able to instantiate all other classes.
So if 'User' need to call 'getUser' method in 'Data' class, it can't instantiate 'Data' class and call method, but it has to call 'Main' class, and then 'Main' will instantiate 'Data' class and pass arguments to its 'getUser' method.
What I am thinking is using private constructor, Factory Pattern etc., but not sure if this will result in what I need. Due to the complexity I don't think inner classes would be good solution.
Any advice on this?
A distinct answer on the conceptual level (as there are already good answers on the technical "how to do it"):
Let's say there is Main class, then there are User, Admin, View, Data, Client etc. classes. Only 'Main' class should be able to instantiate all other classes.
I don't think this is a good starting point. Of course, when one follows Domain Driven Design, using factories is well established.
But there is one subtle point to add: you still want to cut your "boundaries" in reasonable ways. Meaning: don't force all objects into a single factory. Your objects should somehow resemble their domains, and be separated where needed.
Meaning: using factories is fine, but don't force yourself into the wrong corner by enforcing that there is exactly one factory that is supposed to handle all kinds of objects you deal with. Instead: try to reasonably partition your object model, and have as many factories as it makes conceptually sense to have.
Also note that you probably should distinguish between objects that mainly provide data/information, and "behavior" on the end. Thus it might be worth looking into the idea of having a service registry (for example what you do with the netflix Eureka framework, see here).
And finally, to quote an excellent comment given by tucuxi here: For small applications, factories are over-engineering. For larger applications, I find it questionable to have a single factory called "Main", instead of splitting responsibilities in a more orthodox way.
You can use a subclass with a private constructor:
With this, only InstantiatonClass can create InstantiatonClass.ArgClass and the constructor of ProtectedClass.
public class ProtectedClass{
//constructor that can only be invoked with an instance of ArgClass
public ProtectedClass(InstantiatonClass.ArgClass checkArg){}
}
public class InstantiatonClass{
public static class ArgClass{
//constructor that can only be invoked from InstantiatonClass
private ArgClass(){}
}
}
You should be able to get caller's class in a Class's constructor:
How to get the name of the calling class in Java?
Then in the classes where you only want to be instantiated by Main, simply check the caller class is Main in its constructor, if not throw a RuntimeException.
I have a set of DAOs (Data access objects) that need to be fetched from a DAOFactory (using the factory-method pattern).
Now we have the case that DAOs must always be initialized with parameters e.g.: (with String params)
MyDataDAO myDAO = new myDAO("myProject", "myProjectWallName");
Now, having a bunch of DAOs has required us to refactor (using the factory pattern) and here are the conflicting forces:
If we refactor our DAOs to NOT use any default arguments (probably a good thing) we may land up having setters/getters for the mandatory members that MUST be initialized. Implying probably null checks/assertions littered all throughout (bad thing IMO)
The other way is to force every method of the DAO to carry the corresponding mandatory arguments along with what they already have (too much data/long parameter list - probably bad but maybe the only choice?)
Use Spring! Well we do for some of the purely stateless DAOs which really don't require any defaults to be set up. But I don't think Spring really supports run-time constructor-parameter initialization, since it creates and caches the objects at start-up. So back to square one (Spring may support this but I really haven't been able to find anything about this as yet. Help? :)
So how should one go about designing a 'good' interface for the classes that are to be instantiated using a factory i.e., best practices to follow in this regard. I've always encountered the non-parameterized constructor case up until now where I do feel a valid need/reason for having the parameters. I personally feel it's bad OO to have a default constructor only and set everything through setters-getters, defeating the very purpose constructors exist to solve!
Confused...
I don't see any reason why a factory always has to use the default-constructor. The create-method is completely free to take arguments that it passes through to the constructor it calls. Alternatively, the factory can store the arguments in member-variables. This way, you can make sure that all objects created with this factory are created with the same parameters.
A Factory pattern is used to create an object and make sure that it is in a valid state when it's returned to the caller.
If your object has required properties, returning it with a default constructor and not initialized properties, won't return a valid state to the caller. In such a case, everywhere you call the factory, the code should also know which fields are required and initialize them after the factory call. That way you duplicate initialize code (and knowledge) and the whole idea of the factory pattern is to remove such duplication.
So required fields should be passed as parameters to a factory method.
Can a class add a method to itself at runtime (like from a static block), so that if someone is performing reflection on this class, they'll see the new method, even though it wasn't defined at compile time?
Background:
A framework I'm using expects Action classes to be defined that have a doAction(...) method, by convention. The framework inspects these classes at runtime to see what type of parameters are available in their doAction() method. For example: doAction(String a, Integer b)
I'd like each class to be able to programatically generate its doAction() method with various parameters, just-in-time when it is inspected. The body of the method can be empty.
It's not simple. Once a class is loaded by a classloader, there is no way to change the methods of loaded classes. When a class is requested, a classloader will load it and link it. And there is no way (with Java) to change the linked code or to add/remove methods.
The only trick that comes to my mind is playing with classloaders. If we delete a custom classloader, then the classes loaded by that classloader should be deleted or inaccessible too. The idea that comes to my mind is to
implement one custom classloader
load the dynamic class with that custom classloader
if we have an updated version of this class,
remove the custom classloader and
load the new version of this class with a new instance of the custom classloader
I leave that as food for thought, can't prove, if this leads to a solution or if we have pitfalls.
As a simple answer to the question: No, we can't change a loaded class like we can change the content of fields with reflection. (we can't add or remove fields too).
Andres_D is right, we can very well do so using custom class loading, here is a detailed guide on how to do this: http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html?page=1
The article explains how to write dynamic Java code. It discusses runtime source code compilation, class reloading, and the use of the Proxy design pattern to make modifications to a dynamic class transparent to its caller.
In fact researcher in Austria have written a JVM that even allows reloading classes with different type hierarchies. They have achieved this by using existing thread save points to generate a complete 'side universe' of an object and all it's related references and referenced content and then once fully reshuffled with all required changes simply swap in all changed classes. [1] Here a link to their project http://ssw.jku.at/dcevm/ the oracle sponsorship certainly makes for interesting speculations on future plans.
Less intrusive changes to method bodies and fields are already possible in the standard java VM using the Hot Swap capabilities of the JPDA as introduced in Java 1.4:
docs.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap
I'm not sure whether it was the first one but this Sun employee's paper from 2001 appears to be one of the early proposals mentioning the capabilities of the HotSpot to Hot Swap. [2]
REFERENCE
[1] T. Würthinger, C. Wimmer, and L. Stadler, “Dynamic Code Evolution for Java,” presented at the 8th International Conference on the Principles and Practice of Programming in Java, Vienna, 2010.
[2] M. Dmitriev, “Towards flexible and safe technology for runtime evolution of java language applications,” in OOPSLA Workshop on Engineering Complex Object-Oriented Systems for Evolution, 2001.
I've never tried anything quite like that myself, but you should have a look at ASM, cglib, and Javassist.
No, that is not (easily) possible in Java.
It sounds like you are trying to use Java as if it is a dynamic programming language. For example, Ruby has open classes: you can add and remove methods from Ruby classes at runtime. In Ruby, you can also have a "method missing" method in your class, that will be called when you try to call a method that doesn't exist in the class. Such a thing also doesn't exist in Java.
There is a version of Ruby that runs on the JVM, JRuby, and it has to do very difficult tricks to make open classes work on the JVM.
You can have a doAction method which does whatever you would like the generated method to do. Is there a reason it needs to be generated or can it be dynamic?
It looks like there is no way to add method dynamically. But you can prepare an class with a list of Methods or an hash like:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
public class GenericClass {
private HashMap<String, Method> methodMap = new HashMap<String, Method>();
public Object call(String methodName,Object ...args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method method = methodMap.get(methodName);
return method.invoke(null, args);
}
public void add(String name,Method method){
if(Modifier.isStatic(method.getModifiers()))
methodMap.put(name, method);
}
public static void main(String[] args) {
try {
GenericClass task = new GenericClass();
task.add("Name",Object.class.getMethod("Name", new Class<?>[0]));
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
}
Than, using reflections you can set or unset the attribute.
I believe you need some byte code altering tool/framework, such as asm, cglib or javassist.
You can achieve this via aspects/weaving like it's done Spring, but I believe you still need to have the method defined first.
Proxy may help. But have to instantiate a Proxy every time you want to add or remove a method.
What I suggest should work for your situation:
1. You have an existing class MyClass with n methods
2. You want to include (n+1) th method which is not in the class while compiling in another .java source file
My way to solve it is Inheritance. Create a new .java source file for a Class MyClassPlusOne extending the first class MyClass. Compile this class and use the object. How can I compile and deploy a java class at runtime?
class MyClassPlusOne extends MyClass
{
void doAction(String a, Integer b)
{
int myNPlus1 = a+b;
//add whatever you want before compiling this code
}
}
I'm not sure that is possible. However, you could use AspectJ, ASM, etc. and weave these methods into the appropriate classes.
The other alternative is to use composition to wrap the target class and provide the doAction method. You would end up delegating to the target class in this case.
This is a rather old question, but I still found myself looking at it today so, just in case, I'll add my two cents.
If you are using Java 8+, you can define "default" implementations of an interface method, so you can just define the interface with all the extra methods with empty default implementations, and add the implements clause in the desired classes. This approach, in some cases, may be the easiest one.
If you don't have control over the definition of the classes, or you need compatibility with older Java versions, you can still define an interface containing all the required extra methods; but in this case, implement a "Decorator" class with a method that receives the object to "decorate" as parameter, and returns a DynamicProxy instance, wrapping the passed object with this interface.
If you are using Spring, the decorator can be added to the context as a #Component, so you can inject it wherever you need to use it. If any of the objects you need to inject are Spring Beans, you could implement a FactoryBean that uses the decorator to return the instances, so you can just forget about calling the decorator explicitly for them.
I am working with a Class that contains constants or parameter values that all classes can reference for example;
public class Parameters {
public static final String JUMP_TO_VALUE = "Parameters.JUMP_TO_VALUE";
public static final String EXCEPTION_ID = "Parameters.EXCEPTION_ID";
}
Some of the foundation classes in my application will use the parameter values in the Parameters class like so:
mapOfValues.put( Parameters.JUMP_TO_VALUE, "some_value")
This is simple enough I have some basic values in Parameters that most of my base classes will use them. There will be many situations where I will need to add addition parameters to the Parameters class, but I don't want to over populate or pollute the Parameters class ever time a new parameter is identified. I would rather create some subclass of Parameters like:
public class NetworkParameters extends Parameters {
public static final String HOST_NAME = "NetworkParameters.HOST_NAME";
public static final String POST_NUM = "NetworkParameters.PORT_NUM";
}
Some of my specific classes will use the values that are contained in this class versus putting them in the Parameters class.
These specific classes that need HOST_NAME for example I don't want them to reference the NetworkParameters class but rather the Parameters class.
I am sure people have done this before but I am looking for advice on how best to implement this design.
It is simply not possible, in the exact way you describe it.
When you reference static objects, you refer to the class that those objects are declared in. Quite simply, if you declare a constant in the NetworkParameters class, it does not exist in the Parameters class and is not accessible as such.
Separating vast numbers of parameters into different containing classes (which don't need to be subtypes of each other as this achieves nothing) is quite good practice and often used. Why do you have such an aversion to just using NetworkParameters.POST_NUM, as this is the name of the parameter and sounds completely sensible to me?
One thing that may help you (depending on your own tastes) is to use Java 5's static import feature. If, at the top of a class file, you declare
import static the.package.name.Parameters.*;
import static other.package.NetworkParameters.*;
then you will be able to use all of the constant names from both classes without any prefix at all. This is often quite nice when it's obvious what comes from where - but it can become a nightmare if you're statically importing from a few classes, especially if you don't have an IDE to work out the reference for you.
But again - why do you want to reference them as Parameters.FOO, but want them to live in a separate class? Either approach (everything in one file, different constants in different files) is good and fine if you do it completely, but you can't magically change the laws of Java references because you don't like the look of them. :-)
I don't think you would be overdoing it by putting a lot of constants in a single file. Just keep it well organized with good formatting and documentation. I dont think subclassing is want here. A subclass implies a certain relationship among objects. First off, you aren't really creating an object, so creating a subclass does not really fit the model here. Also, using a subclass here may just complicate things. For example, you will have to import multiple java files if you want to use several types of constants in another class.
Are you sure you want to be embedding these values in your code?
They sound to me like the kind of data you want to place in a configuration file, so they can be change easily without the code needing to be recompiled. A simple hash of name-value pairs from a configuration file, wrapped to be accessible in the way you need them to, might be a more flexible approach to the same problem.