can BeanUtils.setProperty() set value without setter? - java

I'm currently taking an example from here to map my ResultSet to custom Object. I've tested BeanUtils.setProperty() and it seems like the object would need setters to work. Is there any way to map values like what Gson does? I don't want to have public setters.

No it can't.
As the name implies the BeanUtils deal with Java Beans
They are serializable, have a zero-argument constructor, and allow access to properties using getter and setter methods.
(Emphasis mine.)
Though the Javadoc of the BeanUtils methods is quite vague clues can also be found in the source code of BeanUtilsBean.setProperty() and PropertyUtilsBean.setSimpleProperty().
See the documentation too:
The Java language provides classes like java.beans.Introspector, which can examine a Java class at runtime and identify for you the names of the property getter and setter methods, [...]. The APIs in the BeanUtils package are intended to simplify getting and setting bean properties dynamically, [...].
(Emphasis mine.)

You can use #Data annoation from Lombok library in the Entities.

Related

Why default constructor written here, when we already have a parameterized constructor? [duplicate]

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.

Is it possible to have a Java annotation that doesn't apply to any class, method, field, etc. Just the annotation itself generating code

Are there such things as Java annotations that aren't tied to any class, method, field, etc.?
Like just writing
#MyAnnotation(someParameter=value, ...)
by itself, and it generates code.
It seems like ExecutableType might define what kinds of "elements" an annotation can annotate, but I'm not sure. If that's true, then ExecutableType derives from TypeMirror, one of whose members are NoType. So maybe it's possible? But I cannot find an example of this.
You cannot have a stand-alone annotation in Java.
Annotations can be applied to different things, for example: types, methods, fields, local variables, packages, method parameters and also on annotation definitions.
One annotation that is meant to be used on annotation definitions (therefore it's called a "meta-annotation") is #Target, which you use to indicate on what things the annotation you are defining is allowed to be used. You do this by specifying one or more element types as an argument to the #Target annotation - see the API docs of java.lang.annotation.ElementType.
The Java Language Specification paragraph 9.6.4.1 explains what annotations can be used on in more detail.

CopyPartRequest class of Amazon S3 - When to use this Design?

I went through the CopyPartRequest class file of Amazon S3 (Package: com.amazonaws.services.s3.model)
CopyPartRequest copyRequest = new CopyPartRequest()
.withDestinationBucketName()
.withDestinationKey()
.withSourceBucketName()
.withSourceKey()
.withUploadId()
.withFirstByte()
.withLastByte()
.withPartNumber();
This class have all setter methods (ex: setDestinationBucketName) and also has methods which returns the same object itself which are used as above.
Reference URL:
http://www.lookatsrc.com/source/com/amazonaws/services/s3/model/CopyPartRequest.java?a=com.amazonaws:aws-java-sdk-s3
I'm trying understand the pattern when to use this kind of pattern
When we need to have setter methods (or) With() methods (or) both.
Can we have similar kind of With Methods in entity class along with setter methods so that it will be useful for creating an object
Is it possible have With() methods alone and convert the same via Dozer or ModelMapper instead of having setter methods
Thanks.
Setter methods are part of JavaBeans convention and are often required by some tools (e.g. ORM tools). On the other hand those with methods constitute a fluent API that can improve readability of the code.
Yes.
I don't think so. I do not know Dozer or ModelMapper tools, but I guess that they need objects that conform to JavaBeans convention (so setters would be required).

In Java, is there a better alternative to getter and setter methods?

It is common in Java classes to have lots of getter and setter methods, one each for every data model class variable. I realize that many IDEs will create these for you, but I'm trying to avoid this clutter and not have all these methods in my classes. So, is there any way to access a variable in a read only fashion outside the class (as if it were public final), while retaining write access inside the class or subclass exclusively (as if it were private or protected).
The only pseudo-solution I've come up with is a base class (or interface with default methods) that has a get(String variableName) method which then gets the fields of the class via reflection and returns the appropriate one. The downside is that for that to work, the variables have to be public, so only by convention does it meet my requirements (in that in the extending/implementing class that has the variables I want to access, I only call the get method from outside the class, and don't implement a set method). The main thing I don't like about this is that if a variable name changes, callers of the get methods will not cause compiler errors, since the variable name is just a hardcoded String.
Anyone have a better idea?
Yes - try to design your classes so you don't have getters and setters at all. Typically it's a bad design to have getters and setters on all of your fields because it breaks encapsulation. An exception is the case of Java Beans (where you have a model class/DTO or some class that's mapped to XML/JSON); here you should not mind them because setters and getters are the only methods.
In classes that have logic, inject your dependencies via constructor or directly if you use Spring/CDI and you like it. This is more safe because you won't have objects in inconsistent states; like for example you create an object but forget to call a setter -> NullPointerException. But by using constructors, you avoid the case of forgetting to call the setters.
Of course there might be exceptions, like when setting some optional fields when you don't want all the dependencies in the constructor all the time. This however can be solved with overloading constructors or if the case is more complex the problem can be solved in a more elegant way by using the builder pattern.
See a great article on this: http://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html
You may use lombok - to manually avoid getter and setter method. But it create by itself.
The using of lombok significantly reduces a lot number of code. I found it pretty fine and easy to use. But here you may find some pros and cons of using lombok here.
Hope it will help.
Thanks a lot.
Java FX introduced something similar to what you want: ReadOnlyProperty
Might not be exactly what you are looking for, though. In general, I don't think exposing a variable is a good idea.

how to use #XmlElement in java

I'm trying to learn how to store objects as XML files in java, but I'm having a bit of a problem.
Most tutorials that I have found have said that I should use the #XmlElement annotation with set methods, however is there another way to use them, as my objects would be easier to make using just the constructors I have for them instead of a set for each field.
The #XmlElement can also be used on the property. You will find more information in the javadoc.
The javadoc gives this example:
public class USPrice {
#XmlElement(name="itemprice")
public java.math.BigDecimal price;
}
All public fields and properties (get/set method pairs) will be treated by default as if they were annotated with #XmlElement. You can add #XmlElement on the get or set method. You can also annotate the field (instance variable). If you do you should annotate your class with #XmlAccesorType(XmlAccessType.FIELD).
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
JAXB does not currently support annotating constructors. If you are dealing with immutable objects then the following may help:
http://blog.bdoughan.com/2010/12/jaxb-and-immutable-objects.html

Categories