Creating immutable objects from javabean - java

I am involved in this project where we are building on good bit of legacy code. I have a particular situation about one big java bean object which has to be transferred over wire. So my first thought was to make it immutable and serializable to do the trick .At this point I am faced with a few difficult choices :-
Ideally I want some way to
automatically generate an immutable,
serializable version of this class.
I dont have the scope to refactor or
alter this class in any way and i
would really really hate to have to
copy paste the class with a
different name ?
Assuming that i gave up on 1 i.e i
actually chose to duplicate code of
the HUGE javabean class , i still
will be in the unsavoury situation
of having to write a constructor
with some 20-25 parameters to make
this class immutable. what is a
better way to make a class immutable
other than constructor injection ?
Thanks and Regards,

To make it truly immutable, you need to initialize the members at construction time.
One way (and I ain't sayin' it's pretty!) to do this and avoid a huge parameter list in the constructor is to have a mutable type that has the same properties. Set the the properties on the mutable type one at a time, through "setters", then pass the mutable object to the constructor of the immutable type as a single argument. The immutable object then copies the properties from the mutable source to it's own (final) members.
You might also consider "effective immutability". That is, even though immutability is not enforced by the system, you use coding practices that clearly separate the initialization phase from the usage phase. After all, immutability is not required for serialization.
You can take this a step further, creating an implementation-hiding wrapper for the interface that doesn't expose the properties of the implementation. The wrapper only implements the methods in the interface, by delegating to the "real" implementation. The setters and getters from the implementation are not present in the wrapper. This will stop clients from simply down-casting from the interface to the implementation class and manipulating the properties.

Joshua Bloch's "Effective Java" illustrates the Builder pattern, where simple Builder objects are used to construct a complex object with a long constructor argument list. I'd recommend it.
http://www.drdobbs.com/java/208403883;jsessionid=PJWS41F5DJ4QRQE1GHRSKH4ATMY32JVN?pgno=2

20-25 properties is not huge for a one off, particularly if you are using a half-decent editor.
If you already have a mutable instance when constructing the immutable version, just pass that to the constructor.
If you want to be really evil hacky, use java.beans to create a serialisable Map for the mutable class or subclass implementing Externalizable. Alternatively you could use java.beans XML serialisation (the XML than can be sent over Java serialisation...).

What about a simple read only interface cotaining the getters?
If the bean class is your own, let it simpley implement the interface and use just the interface after creation.
If you have no control over the bean class, you can also create a getter interface and implement it by creating a proxy for the getter interface with an invokation handler delegating all method calls to the bean.

Step 1: Create a new class and give it instance variables with the exact same names as the instance variables of your 'big java bean object'. That new class should not have setters (but getters only) to make it immutable.
Step 2: Use Apache Commons BeanUtils.copyProperties to copy all the properties (i.e. instance variables) from your 'big java bean object' to your new object.

A few ideas:
Protected setters and factory methods
You can define beans with protected setter methods and in the same package, a factory class that takes all the parameters and calls those setters. The bean is immutable outside that package. To enforce this, be sure to seal your jar so end users cannot create new classes in the same package.
Note: You can use my JavaDude Bean annotations to make the creation simpler:
http://code.google.com/p/javadude/wiki/Annotations
For example:
#Bean(writer=Access.PROTECTED, // all setXXX methods will be protected
properties={
#Property(name="name"),
#Property(name="age", type=int.class)
})
public class Person extends PersonGen {
}
Creating getters and a constructor in eclipse
Eclipse has some nice tools to make this fast:
Create the bean class
Add the fields you want
Right-click in the editor window
Choose Source->Generate Getters and Setters
Press the "Select getters" button
Press ok
Right-click in the editor window
Choose Source->Generate Constructors from fields
Pick and order the fields you want in the constructor
Press ok
Immutability Decorator
Another idea is to define your bean with getters and setters (you can use the above technique but include setters), then you can create a wrapper class for it that only has the getters.

Related

Can a Java Bean contain one or more parameterized constructors?

I'm new to java and I have a question. According to my knowledge, Java beans have the following properties.
They should be serializable, i.e. they should implement the serialization interface.
They should have a no-argument constructor.
What is the meaning of have a no-argument constructor? Does it mean that there can only be a no-argument constructor? Can't they have parameterized constructors? Does that mean that bean classes cannot have constructor overloading?
It means that the bean class must have a no-argument constructor. It can have as many constructors as you want, but it must have one no-argument constructor.
Take into account that any java class without defined constructor will have a default no-argument constructor, but if you add any constructor with arguments, you need to explicitly define a no-argument constructor in this case.
A Java Bean may have parameterized constructors, but they won't be used for the purposes that the original Java Beans specifications were intended to serve: frameworks that use reflection to instantiate objects.
Java Beans were devised to enable tools like UI designers. By following conventions for constructors and accessors, tools can create and manipulate objects in a consistent manner at "design time", without knowing anything about the particular class involved. The resulting object instance with its configured properties could be reconstructed later at runtime, using generated code or deserialization.
Over time, the Java Beans concept was used in more and more contexts, but most rely on similar conventions: a public, no-arg constructor, and public accessors with special names.
These don't stop you from adding additional constructors and methods, but they won't be usable by most Java-Beans–oriented frameworks. They will be available to your hand-written code though, and that can be quite useful.
For example, a dependency injection framework can use the Java Beans conventions to construct and configure an object that also implements an interface that doesn't follow JavaBeans conventions. You write code ("by hand") that depends on an instance of that interface to do its job. You don't care where the object came from (constructor) or its properties (accessors); you just use the interface methods.

Is there a way to get all of the non-null members of a class without reflection or getters?

I have a class that that can potentially assign values to 50+ plus variables. I don't want to write getters for all of these fields. I would rather have some way that can report which fields have had a value assigned to them and, what that value is.
I had originally made these private and, I know that reflection basically breaks private. Additionally, Securecoding.org states this about reflection:
In particular, reflection must not be used to provide access to classes, methods, and fields unless these items are already accessible without the use of reflection. For example, the use of reflection to access or modify fields is not allowed unless those fields are already accessible and modifiable by other means, such as through getter and setter methods.
My main concern is mucking up my code by declaring dozens of instance variables(and possibly getters). Later in this project, I will have two more large sets of instance variables that need to be declared as well. I know that I can reduce the use of getters with some clever maps and enums but, that still takes parsing dozens ofnull values. Could anyone suggest another way?
I know only 4 ways to access field of class
directly unless field is private
Using method, e.g. getter.
Using constructor.
Using reflection
The ways 1 and 4 are beyond the discussion.
Constructor usage is not convenient here because huge number of fields.
So, methods the possibility.
It is up to you whether you want to use bean convention or for example builder pattern, but if you need this class for persistency or for serialization into XML or JSON etc you need at least getters.
Now, if you just want to validate the instance after its creation you can declare your interface Validatable that declares method validate() and call it when your object should be ready. You have to however implement and maintain this method for each class.
Alternative way is to use one of available validation frameworks. In this case you validation can be done using annotations. You should remember however that behind the scene such frameworks use reflection.
Here are some links for further reading:
http://commons.apache.org/proper/commons-validator/
http://java-source.net/open-source/validation
http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html

Is Object deserialization a proper way to implement Prototype pattern in Java?

TL;DR
Can I use Java serialization/deserialization using Serializable interface, ObjectOutputStream and ObjectInputStream classes, and probably adding readObject and writeObject in the classes implementing Serializable as a valid implementation for Prototype pattern or not?
Note
This question is not to discuss if using copy constructor is better than serialization/deserialization or not.
I'm aware of the Prototype Pattern concept (from Wikipedia, emphasis mine):
The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to:
avoid subclasses of an object creator in the client application, like the abstract factory pattern does.
avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) when it is prohibitively expensive for a given application.
And from this Q/A: Examples of GoF Design Patterns in Java's core libraries, BalusC explains that prototype pattern in Java is implemented by Object#clone only if the class implements Cloneable interface (marker interface similar to Serializable to serialize/deserialize objects). The problem using this approach is noted in blog posts/related Q/As like these:
Copy Constructor versus Cloning
Java: recommended solution for deep cloning/copying an instance
So, another alternative is using a copy constructor to clone your objects (the DIY way), but this fails to implement the prototype pattern for the text I emphasized above:
avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword)
AFAIK the only way to create an object without invoking its constructor is by deserialization, as noted in the example of the accepted answer of this question: How are constructors called during serialization and deserialization?
So, I'm just asking if using object deserialization through ObjectOutputStream (and knowing what you're doing, marking necessary fields as transient and understanding all the implications of this process) or a similar approach would be a proper implementation of Prototype Pattern.
Note: I don't think unmarshalling XML documents is a right implementation of this pattern because invokes the class constructor. Probably this also happens when unmarshalling JSON content as well.
People would advise using object constructor, and I would mind that option when working with simple objects. This question is more oriented to deep copying complex objects, where I may have 5 levels of objects to clone. For example:
//fields is an abbreviation for primitive type and String type fields
//that can vary between 1 and 20 (or more) declared fields in the class
//and all of them will be filled during application execution
class CustomerType {
//fields...
}
class Customer {
CustomerType customerType;
//fields
}
class Product {
//fields
}
class Order {
List<Product> productList;
Customer customer;
//fields
}
class InvoiceStatus {
//fields
}
class Invoice {
List<Order> orderList;
InvoiceStatus invoiceStatus;
//fields
}
//class to communicate invoice data for external systems
class InvoiceOutboundMessage {
List<Invoice> invoice;
//fields
}
Let's say, I want/need to copy a instance of InvoiceOutboundMessage. I don't think a copy constructor would apply in this case. IMO having a lot of copy constructors doesn't seem like a good design in this case.
Using Java object serialization directly is not quite the Prototype pattern, but serialization can be used to implement the pattern.
The Prototype pattern puts the responsibility of copying on the object to be copied. If you use serialization directly, the client needs to provide the deserialization and serialization code. If you own, or plan to write, all of the classes that are to be copied, it is easy to move the responsibility to those classes:
define a Prototype interface which extends Serializable and adds an instance method copy
define a concrete class PrototypeUtility with a static method copy that implements the serialization and deserialization in one place
define an abstract class AbstractPrototype that implements Prototype. Make its copy method delegate to PrototypeUtility.copy.
A class which needs to be a Prototype can either implement Prototype itself and use PrototypeUtility to do the work, or can just extend AbstractPrototype. By doing so it also advertises that it is safely Serializable.
If you don't own the classes whose instances are to be copied, you can't follow the Prototype pattern exactly, because you can't move the responsibility for copying to those classes. However, if those classes implement Serializable, you can still get the job done by using serialization directly.
Regarding copy constructors, those are a fine way to copy Java objects whose classes you know, but they don't meet the requirement that the Prototype pattern does that the client should not need to know the class of the object instance that it is copying. A client which doesn't know an instance's class but wants to use its copy constructor would have to use reflection to find a constructor whose only argument has the same class as the class it belongs to. That's ugly, and the client couldn't be sure that the constructor it found was a copy constructor. Implementing an interface addresses those issues cleanly.
Wikipedia's comment that the Prototype pattern avoids the cost of creating a new object seems misguided to me. (I see nothing about that in the Gang of Four description.) Wikipedia's example of an object that is expensive to create is an object which lists the occurrences of a word in a text, which of course are expensive to find. But it would be foolish to design your program so that the only way to get an instance of WordOccurrences was to actually analyze a text, especially if you then needed to copy that instance for some reason. Just give it a constructor with parameters that describe the entire state of the instance and assigns them to its fields, or a copy constructor.
So unless you're working with a third-party library that hides its reasonable constructors, forget about that performance canard. The important points of Prototype are that
it allows the client to copy an object instance without knowing its class, and
it accomplishes that goal without creating a hierarchy of factories, as meeting the same goal with the AbstractFactory pattern would.
I'm puzzled by this part of your requirements:
Note: I don't think unmarshalling XML documents is a right
implementation of this pattern because invokes the class constructor.
Probably this also happens when unmarshalling JSON content as well.
I understand that you might not want to implement a copy constructor, but you will always have a regular constructor. If this constructor is invoked by a library then what does it matter? Furthermore object creation in Java is cheap. I've used Jackson for marshalling/unmarshalling Java objects with great success. It is performant and has a number of awesome features that might be very helpful in your case. You could implement a deep copier as follows:
import com.fasterxml.jackson.databind.ObjectMapper;
public class MyCloner {
private ObjectMapper cloner; // with getter and setter
public <T> clone(T toClone){
String stringCopy = mapper.writeValueAsString(toClone);
T deepClone = mapper.readValue(stringCopy, toClone.getClass());
return deepClone;
}
}
Note that Jackson will work automatically with Beans (getter + setter pairs, no-arg constructor). For classes that break that pattern it needs additional configuration. One nice thing about this configuration is that it won't require you to edit your existing classes, so you can clone using JSON without any other part of your code knowing that JSON is being used.
Another reason I like this approach vs. serialization is it is more human debuggable (just look at the string to see what the data is). Additionally, there are tons of tools out there for working with JSON:
Online JSON formatter
Veiw JSON as HTML based webpage
Whereas tools for Java serialization isn't great.
One drawback to this approach is that by default duplicate references in the original object will be made unique in the copied object by default. Here is an example:
public class CloneTest {
public class MyObject { }
public class MyObjectContainer {
MyObject refA;
MyObject refB;
// Getters and Setters omitted
}
public static void runTest(){
MyCloner cloner = new MyCloner();
cloner.setCloner(new ObjectMapper());
MyObjectContainer container = new MyObjectContainer();
MyObject duplicateReference = new MyObject();
MyObjectContainer.setRefA(duplicateReference);
MyObjectContainer.setRefB(duplicateReference);
MyObjectContainer cloned = cloner.clone(container);
System.out.println(cloned.getRefA() == cloned.getRefB()); // Will print false
System.out.println(container.getRefA() == container.getRefB()); // Will print true
}
}
Given that there are several approaches to this problem each with their own pros and cons, I would claim there isn't a 'proper' way to implement the prototype pattern in Java. The right approach depends heavily on the environment you find yourself coding in. If you have constructors which do heavy computation (and can't circumvent them) then I suppose you don't have much option but to use Deserialization. Otherwise, I would prefer the JSON/XML approach. If external libraries weren't allowed and I could modify my beans, then I'd use Dave's approach.
Your question is really interesting Luiggi (I voted for it because the idea is great), it's a pitty you don't say what you are really concerned about. So I'll try to answer what I know and let you choose what you find arguable:
Advantages :
In terms of memory use, you will get a very good memory consumption by using serialization since it serializes your objects in binary format (and not in text as json or worse: xml). You may have to choose a strategy to keep your objects "pattern" in memory as long as you need it, and persist it in a "less used first persisted" strategy, or "first used first persisted"
Coding it is pretty direct. There are some rules to respect, but it you don't have many complex structures, this remains maintainable
No need for external libraries, this is pretty an advantage in institutions with strict security/legal rules (validations for each library to be used in a program)
If you don't need to maintain your objects between versions of the program/ versions of the JVM. You can profit from each JVM update as speed is a real concern for java programs, and it's very related to io operations (JMX, memory read/writes, nio, etc...). So there are big chances that new versions will have optimized io/memory usage/serialization algos and you will find you're writing/reading faster with no code change.
Disadvantages :
You loose all your prototypes if you change any object in the tree. Serialization works only with the same object definition
You need to deserialize an object to see what is inside it: as opposed to the prototype pattern that is 'self documenting' if you take it from a Spring / Guice configuration file. The binary objects saved to disk are pretty opaque
If you're planning to do a reusable library, you're imposing to your library users a pretty strict pattern (implementing Serializable on each object, or using transient for dields that are not serializable). In addition this constraints cannot be checked by the compiler, you have to run the program to see if there's something wrong (which might not be visible immediately if an object in the tree is null for the tests). Naturally, I'm comparing it to other prototyping technologies (Guice for example had the main feature of being compile time checked, Spring did it lately too)
I think it's all what comes to my mind for now, I'll add a comment if any new aspect raises suddenly :)
Naturally I don't know how fast is writing an object as bytes compared to invoking a constructor. The answer to this should be mass write/read tests
But the question is worth thinking.
There are cases where creating new object using copy constructor is different from creating new object "in a standard way". One example is explained in the Wikipedia link in your question. In that example, to create new WordOccurrences using the constructor WordOccurrences(text, word), we need to perform heavyweight computation. If we use copy constructor WordOccurrences(wordOccurences) instead, we can immediately get the result of that computation (in the Wikipedia, clone method is used, but the principle is the same).

AbstractClass.getInstance() method is this an anti-pattern

In some places where a class hierarchy is present and the top most base class is an abstract class there is a static getInstance() method in the abstract class. This will be responsible for creating the correct sub-class and returning it to the caller. For example consider the below code.
public class abstract Product {
public static Product getInstance(String aCode) {
if ("a".equals(aCode) {
return new ProductA();
}
return ProductDefault();
}
// product behaviour methods
}
public class ProductA extends Product {}
public class ProductDefault extends Product {}
In Java, java.util.Calendar.getInstance() is one place this pattern has been followed. However this means each time a new subclass is introduced one has to modify the base class. i.e: Product class has to be modified in the above example. This seems to violate the ocp principle. Also the base class is aware about the sub class details which is again questionable.
My question is...
is the above pattern an anti-pattern ?
what are the draw-backs of using the above pattern ?
what alternatives can be followed instead ?
The interface is not an anti-pattern. But the way you've implemented it is rather poor ... for the reason you identified. A better idea would be to have some mechanism for registering factory objects for each code:
The Java class libraries do this kind of thing using SPIs and code that looks reflectively for "provider" classes to be dynamically loaded.
A simpler approach is to have a "registry" object, and populate it using dependency injection, or static initializers in the factory object classes, or a startup method that reads class names from a properties file, etcetera.
No it's not. It's more like factory method pattern http://en.wikipedia.org/wiki/Factory_method_pattern. E.g. Calendar.getInstance();. JDK is full of such examples. Also reminds of Effective Java Item 1: Consider static factory methods instead of constructors
There are a number of separate issues here.
getInstance is probably going to be a bad name. You explicitly want a new object you can play around with. "Create", "make", "new" or just leave that word out. "Instance" is also a pretty vacuous word in this context. If there is sufficient context from the class name leave it out, otherwise say what it is even if that is just a type name. If the method returns an immutable object, of is the convention (valueOf in olden times).
Putting it in an abstract base class (or in an interface if that were possible) is, as identified, not the best idea. In some cases an enumeration of all possible subtypes is appropriate - an enum obviously and really not that bad if you are going to use visitors anyway. Better to put it in a new file.
Anything to do with mutable statics is wrong. Whether it is reusing the same mutable instance, registration or doing something disgusting with the current thread. Don't do it or depend (direct or indirectly) on anything that does.
Based on the feedback i introduced a new ProductFactory class that took care of creating the correct Product. In my case the creation of the correct product instance depends on an external context (i've put the product code for the purpose of simplicity.. in the actual case it might be based on several parameters.. these could change over time). So having a Product.getInstance() method is not that suited because of the reasons outlined in the question. Also having a different ProductFactory means in the future.. Product class can become an interface if required. It just gives more extensibility.
I think when the creation of the object doesn't depend on an external context.. like in the case of Calendar.getInstance() it's perfectly ok to have such a method. In these situations the logic of finding the correct instance is internal to that particular module/class and doesn't depend on any externally provided information..

Why does Hibernate require no argument constructor?

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.

Categories

Resources