Guice 3.0 - Purpose of Constructor Bindings? - java

I've just read the chapter about Constructor Bindings in Guice's User Guide but don't really understand when to use Constructor bindings.
As far as I understand, they provide the same functionality as #Provider methods, except instances created with Constructor Bindings participate in AOP. Is this correct? Can anyone give a better example than the one in the doc?

As far as I understand, they provide the same functionality as #Provider methods, except instances created with Constructor Bindings participate in AOP.
That's more or less correct, though there are some advantages that constructor binding has. Basically, it's a way of binding to a class as if it had an #Inject on a specific constructor even if it doesn't and you can't add the annotation yourself. Unlike #Provides methods, you could write utilities to allow you to do more interesting things. For instance, you could have a utilitiy method that returns the only constructor of a class, throwing an exception if there are more than one:
bind(Foo.class).toConstructor(getOnlyConstructor(FooImpl.class));
You could also use some other annotation (besides #Inject) if you wanted for some reason and have a utility method that gets the constructor that's annotated with that for binding.

Related

Is contructor overloading possible with dagger?

I have two data source class, LocalDataSource and RemoteDataSource. In DataRepository, I need both the classes but on need basis. I don't want to inject both the classes in DataRepository constructor. Instead want to overload constructor with single data source class. How to implement this with dagger?
To directly answer the question: Dagger supports one #Inject constructor at most. You can use a #Provides method to call any constructor or factory method you'd like, but if you want Dagger to manage your dependencies it will only read the single constructor you specify with #Inject. That said, that's not quite the right solution here in any case.
If your class needs a LocalDataSource or a RemoteDataSource, and you don't know which one until runtime, inject a Provider<LocalDataSource> and Provider<RemoteDataSource> (or Lazy<LocalDataSource> and Lazy<RemoteDataSource>). These objects are inexpensive Dagger-implemented abstractions over your LocalDataSource and RemoteDataSource constructors, which Dagger automatically allows you to inject: For any T available in your graph, you can inject Provider<T> and Lazy<T> (or even Provider<Lazy<T>>, as described in the documentation).
In this way, Provider and Lazy can help you avoid creating either DataSource instance until you know which one you need.
The difference between them is that Lazy<T> will locally cache the object instance, acting like a field in your class. Provider<T> will always consult your Dagger Component, which will in most cases will return you a newly-allocated object unless you've applied a scope like #Singleton. If your objects are expensive to construct, Lazy is a good choice, since you'll only request one instance across the lifetime of your consumer; if they are cheap to construct, then you might even choose to use a Provider within a method and letting your object be garbage-collected as soon as it is no longer needed.
Of course, as Steven and AlphaOne point out in the comments, you might also consider a design where your DataRepository consumer accepts an arbitrary DataSource that you or Dagger can provide. This generally makes sense, as DataSource is likely a useful interface and DataRepository might not need to know implementation details of the source it consults. However, if you need to handle an arbitrary source specification at runtime, at some point you'll still need to inject both a #Local DataRepository and #Remote DataRepository (assuming you've created #Qualifier annotations #Local and #Remote), and at that point it makes even more sense to use a Provider/Lazy instead of creating both DataRepository objects and their respective DataSources.

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.

Why aren't javabean features built into the root JAVA object?

I'm having a hard time understanding why javabeans are necessary and why they didn't just place the javabean features directly into the object class(root class) in java?
My understanding is you turn an object(instance) into a java bean and that way you get all the benefits like serializable and so on for all the objects in the bean. But if that is the case, why even have a separate bean class for this, why not just have built into the root object class?
Or am I not understand this?
You are not understanding it correctly.
There is no actual Java class or interface that is a bean. It is merely a pattern, a convention.
The bean convention is basically that a class will publicly expose some or all of its properties via public getXxx and setXxx methods, where XXX is the name of the property.
Beans generally should be serializable, but any class can be serializable, and does not need to follow the bean convention.
Besides that answer by Grey: even if there would be a Bean interface or method - not every fruit is an apple!
Meaning: there are zillions of classes that are just fine NOT being beans.
Beyond that: serialization as java does it was often found to be not that helpful. There are good reasons why we mostly serialize into JSON nowadays. In other words: we are pretty happy now that not all classes implement Serializeable by default; because Object being a Bean.
Just to talk about the no-argument constructor part of the bean pattern: A class does have a no argument constructor by default, but as soon as you create another constructor, that effectively removes it, as you probably know. But if you were forced to always have a no-argument constructor, this would be really annoying if you had a class which had a final field which is assigned by an argument in the constructor. You would then need to have some no argument constructor which either assigns everything to null, or throws an exception to tell other developers not to use the no argument so, which is just ugly.

Java: How to listen on methods invocation without registering each object explicitely?

I want to listen on method calls in order to attach additional behavior dynamically around the call. I've already done it on JUnit methods with a custom annotation and runner. I'm trying to do it on a standard java application.
The main idea is to do:
#Override
public void beforeInvoke (Object self, Method m, Object[] args){
Object[] newargs = modifyArgs (args);
m.invoke (self, newargs);
}
It's just an abstract idea, I don't have any concrete example, but I'm curious if it's possible in java.
I've found some approaches:
java.lang.reflect.Proxy.newProxyInstance(...)
where a proxy is defined for an interface only (but not used to decorate concrete classes). It seems similar to injection pattern and it's a different concern.
Another approach here using a factory pattern with the ProxyFactory class. This other solution requires explicit calls to create() method to produce object proxies listening on method invocations. So, if you bypass it by using natural constructors of your classes, it's not working. It's very constraining if you must explicit a call to a factory each time you have to create an object.
There is a way to do it with transparency ?
Like Proxy.newProxyInstance() but working also on concrete classes ?
Thanks.
Well,this is commonly seen with Spring Framework and Aspect Oriented Programming. Since you delegate your constructor calls to Spring, it is quite easy for Spring to put a proxy in place to intercept calls to the actual objects.
As far as I can tell, the only way to intercept calls is to use a proxy. Either in the way you mentioned or using Spring and AOP.
I think cglib let you instrument concrete classes.
As far as I know there is no easy way to intercept method calls that are called on a concrete class.
As mentioned you could manipulate the bytecode during compilation (as Used in AOP) or at class loading time (as used from cglib).
Another product to instrument Classes would be jmockit (http://jmockit.org/). Usually I would use this special kind of black magic only in testing environments and not in an productive environment.
Another way you could go is Annotation Processing. It work's during compiling process. You have to write a Processor which will walk through your source code and generate source-code that contains the original code plus the enhanced method-calls you need.
Depending on how much source-code you have to enhance, this method might be a good idea, but in general it is a lot of work.
Here's a link (https://deors.wordpress.com/2011/10/08/annotation-processors/).
Despite usually it's used in combination with annotations, this is not a strict requirement.

Is there a way to inject final class with guice?

I have provider which should inject javax.mail.Session (provider looks it up in env. context of tomcat) as singleton. There is a problem when I use field injection somewhere in code:
java.lang.IllegalArgumentException: Cannot subclass final class class javax.mail.Session
Is there a way to go round this? Only clues that I've found point to Spring AOP/Proxies.
Thanks && regards
Look at this http://code.google.com/p/google-guice/wiki/AOP. It seems that there is some limitations:
Limitations
Behind the scenes, method interception is implemented by generating
bytecode at runtime. Guice dynamically creates a subclass that applies
interceptors by overriding methods. If you are on a platform that
doesn't support bytecode generation (such as Android), you should use
Guice without AOP support.
This approach imposes limits on what classes and methods can be
intercepted:
Classes must be public or package-private. Classes must be non-final
Methods must be public, package-private or protected Methods must be
non-final Instances must be created by Guice by an #Inject-annotated
or no-argument constructor

Categories