Why CDI beans don't support final methods - java

I just incurred in the infamous JavaEE CDI error under GlassFish server:
org.glassfish.deployment.common.DeploymentException: CDI deployment failure:Exception List with 2 exceptions:
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001437 Normal scoped bean class ASController is not proxyable because the type is final or it contains a final method public final void ASController.selectPath(org.primefaces.event.NodeSelectEvent) - Managed Bean [class ASController] with qualifiers [#Default #Any #Named].
the error is quite explicative in the fact that he doesn't like final methods inside a CDI bean, however I can't grasp why.
At this link
http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html_single/#d0e1429
they explain it is something to do with serialization but I can't see why serializing a class with a final method should be any harder than one with non final methods.

Well, there is several ways in which you can implement a proxy object. But since you expect the proxy to have the "same" type as the proxied bean, you'll have to use inheritance (or demand interfaces which you then could implement, but this would not be an approach where every POJO could be a bean for CDI).
That is, they internally extend from the class you want to inject, generate some proxy code around that and give you that sub class.
This proxy then is handling all the magic to make sure you always have a bean fitting your context (and this bean has all the members variable beans pointing to the just right beans).
So you are not really receiving the type of the bean you want to inject, but a proxy subclass of that bean. This does not work very well with final methods and classes and private constructors.
If the class is not final, the proxy can extend this class, it however cannot easily overwrite the final method of yours. This however may be needed (if e.g your bean is serialized, the proxy needs to deserialize it).
There is, more complicated ways, around that. One could inject this functionality by manipulating the byte code of your class via an agent (e.g removing the final modifiers, inject a default constructor, ...) and maybe even mix this with inheritance, but this is just not implemented, yet (and also non trivial to support over several JVM implementations).
From the linked resource a note indicating that this is planned for a future release:
Note
A future release of Weld will likely support a non-standard workaround
for this limitation, using non-portable JVM APIs:
Sun, IcedTea, Mac: Unsafe.allocateInstance() (The most efficient)
IBM, JRockit: ReflectionFactory.newConstructorForSerialization()
But we didn't get around to implementing this yet.

Container create proxy object for injected classes. So, container doesn't use your classes, but those classes extends. Java prohibit extends final classes, so you cannot use final classes in CDI.

Related

CDI beans and producers

I have three questions
Generally, a bean is just a Pojo that is managed by a container (like Ejb container or CDI container), right? As for when a bean is considered an EJB is quite clear. You will have something like #Stateless or #Stateful. But I don't understand fully when a bean is considered CDI bean. Defining the scope (e.g. #RequestScope) is an indication but what about other classes? In short, when I create and write my own classes, how can I make them CDI bean instead of make them plain Java classes? The only thing I have found about this is https://docs.oracle.com/javaee/6/tutorial/doc/gjfzi.html
Related to above, in this tutorial
https://dzone.com/articles/cdi-and-the-produces-annotation-for-factory
in step 4 says that "CDI does not know how to inject the SpecialLogger object", because of LogConfiguration, so why LogConfiguration is not considered a CDI bean and cannot be injected, and needed to create a producer method ?
I don't understand when we use a producer method, in this example we use it to create a SpecialLogger object but why, we shouldn't just inject SpecialLogger?
Firstly, EJB and CDI are two different specifications with different limitations and goals. Later on in Java/Jakarta EE evolution, CDI created a bridge between the two where it considers all EJB beans to also be CDI beans (the internals of which are more complex and I won't go into now) but otherwise they are still different specs so don't conflate them.
In CDI, beans can be either managed beans or producer methods/fields. Managed beans are typically a java class which can (or in some cases must) have certain annotations to be picked up as a bean. There are some limitations as to how a managed bean looks. See this section of specification (CDI 4, Jakarta EE 10) for further information. Producer methods/fields are a way to declare a bean while also providing an instance of the bean yourself instead of letting CDI create it. In both cases, CDI then manages the bean for its lifecycle, which is typically controlled by the scope of the bean (i.e. #RequestScoped).
However, that's not all there is to it. You mentioned discovery and that's part of the process. There are three discovery modes - none, all, annotated - which can be declared in beans.xml. These control which beans will be found and if they need any kind of annotation to be recognized as beans. none simply means no beans, all means that all classes will be picked up as potential beans, even without annotations. And lastly, annotated will only pick up beans that have a so called bean defining annotation. These include scope annotations, stereotypes, and interceptor annotation. See this part of spec (CDI 4).
Note that prior to CDI 4, default discovery mode was all. With CDI 4 and onwards, it is annotated!
To your second question - SpecialLogger has no no-args constructor and has one constructor with parameters (LogConfiguration) and this constructor isn't annotated with #Inject. Therefore, CDI doesn't know how to create an instance of this object. Note that annotating the constructor with #Inject effectively tells CDI that all of its parameters are also CDI beans that it should know how to instantiate which is not going to be the case in this example.
This brings me to your last question. A producer is typically useful for when it isn't easy or even possible to have an instance of the class created automatically by CDI, but there is still value in handling the instance as a CDI bean. Once you define a producer for SpecialLogger, you can then normally #Inject SpecialLogger in your code. In the end, user won't know if their bean is a product of CDI class instantiation or a producer method. Since bean types of producer method are governed by transitive closure on method's return type, you can also choose to return one of several subclasses based on some config options etc. Overall, it gives you more control over how to create and initialize an object before you hand it over to CDI but at the cost of not having this object injected (since it is you who creates it and not CDI).

Spring 4 not automatically qualifying generic types on autowire

PROBLEM HAS BEEN IDENTIFIED, POST UPDATED (Scroll to bottom)
I am developing a desktop application currently using Spring (spring-context, 4.1.6.RELEASE) for IoC and dependency injection. I am using an annotation configuration, using #ComponentScan. The issue I am experiencing is supposed to be implemented as a feature in 4.X.X, as it states here and here, but I am getting the old 3.X.X exception.
I have a parameterised interface that represents a generic repository:
public interface DomainRepository<T> {
T add(T entity) throws ServiceException, IllegalArgumentException;
// ...etc
}
I then have two concrete implementations of this, ChunkRepositoryImpl and ProjectRepositoryImpl, which are parameterised accordingly. They share some common implementation from an abstract class, but are declared like so:
#Repository
public class ChunkRepositoryImpl extends AbstractRepositoryImpl<Chunk> implements DomainRepository<Chunk> {
// ...+ various method implementations
}
#Repository
public class ProjectRepositoryImpl extends AbstractRepositoryImpl<Project> implements DomainRepository<Project> {
// ...+ various method implementations
}
My understanding of the above links leads me to believe that I should be able to autowire these without needing to manually specify the beans via #Qualifier. However, when I do so:
#Autowired
private DomainRepository<Project> repository;
I get the following exception (preceded by a long stack trace of course):
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.foo.bar.repositories.DomainRepository] is defined: expected single matching bean but found 2: chunkRepositoryImpl,projectRepositoryImpl
Can anybody shine a light as to why this might be happening? I would expect this exception in 3.X.X, but it should not happen in 4.X.X. What is the difference between my situation, and the one described here?
UPDATE
I have discovered the source of the problem. One of the methods in my DomainRepository<T> interface is marked as #Async, and makes use of Spring's asynchronous capabilities. Removing this means that the beans are correctly qualified. I hypothesize that Spring transforms classes with #Async methods under the hood into some other class, and this process strips the type information, meaning that it can't tell the beans apart.
This means I now have two questions:
Is this intended behaviour?
Can anybody suggest a workaround?
Here is a project demonstrating the problem. Simply remove the #Async annotation from the DomainRepository<T> interface, and the problem dissappears.
I hypothesize that Spring transforms classes with #Async methods under
the hood into some other class, and this process strips the type
information, meaning that it can't tell the beans apart.
Yes. That's exactly what happens.
Spring 4 supports injecting beans by their full generic signature. Given the injection target
#Autowired
private DomainRepository<Project> repository;
and a bean of type ProjectRepositoryImpl, Spring will properly resolve and inject that bean into the field (or method argument, or constructor argument).
However, in your code, you don't actually have a bean of type ProjectRepositoryImpl, not even of type DomainRepository<Project>. You actually have a bean of type java.lang.Proxy (actually a dynamic subclass of it) that implements DomainRepository, org.springframework.aop.SpringProxy, and org.springframework.aop.framework.Advised.
With #Async, Spring needs to proxy your bean to add the asynchronous dispatching behavior. This proxy, by default, is a JDK proxy. JDK proxies can only inherit the interfaces of the target type. JDK proxies are produced with the factory method Proxy#newProxyInstance(...). Notice how it only accepts Class arguments, not Type. So it can only receive a type descriptor for DomainRepository, not for DomainRepository<Chunk>.
Therefore, you have no bean that implements your parameterized target type DocumentRepository<Project>. Spring will fall back to the raw type DocumentRepository and find two candidate beans. It's an ambiguous match so it fails.
The solution is to use CGLIB proxies with
#EnableAsync(proxyTargetClass = true)
CGLIB proxies allow Spring to get the full type information, not just interfaces. So your proxy will actually have a type that is a subtype of ProjectRepositoryImpl, for example, which carries with it the DocumentRepository<Project> type information.
A lot of the above are implementation details and defined in many separate places, official documentation, javadoc, comments, etc. Use them carefully.

Spring Internal - Member instance injection clarification

Spring creates the class objects by Java dynamic proxies (java.lang.reflect.Proxy). i.e
#Component
public class NewsService implements Service{
}
But how the member variables are injected by Spring? ie
#Autowired
private EntityManager em;
Java dynamic proxies uses interface (i.e Service) to create the objects. But how member variables are injected? The instance variables are not known by interface.
Also when member instances are injected? Load time?(When containing class object is created?) or Lazy loading? (when object is used first?)
Few facts for you:
Spring instantiates specific classes, not interfaces. Dependency injection is done on the original bean instance.
When a proxy is created, Spring registers both the original bean and its proxy in the application context. JDK proxy is created for all interfaces implemented by the original bean.
Proxies are not created if they are not necessary (i.e. no aspect is applied on the target bean).
All beans are eagerly initialized by default. If you want some bean to be instantiated in a lazy fashion, you need to specify it explicitly.
Dependency injection happens right after the bean is instantiated. Some dependencies are injected based on the bean definition, other dependencies might be injected by various bean post processors (but they are executed right away as well).
How is dependency injection realized:
When using XML configuration or autowiring , dependency injection is done via Reflection API. Spring is able to either call property setter (setFoo(...)) or set field value directly (reflection allows setting private members).
When using #Bean methods in Java configuration, dependency injection is done by your method.
A bit on proxies:
JDK proxies and CGLIB proxies are two different proxying mechanisms. JDK creates artificial class based on provided interfaces, whereas CGLIB creates artificial subclass of the target class.
Which proxying mechanism is used depends on your Spring configuration (JDK is the default one). For obvious reasons JDK proxy can be used only in cases when your dependencies are referenced only by interface. From the other side you can not use CGLIB proxying for final classes.

Guice eager/lazy singleton instantiations

I'm having some troubles understanding how Guice's singleton instantiations works. I've read the available documentation (here - http://code.google.com/p/google-guice/wiki/Scopes ), but I still can't figure out some things:
I've integrated Guice with Tomcat, and I've set up some bindings in a ServletModule:
bind(MyServlet.class).asEagerSingleton();
serve("myUrl").with(MyServlet.class);
serve("myOtherUrl").with(MyOtherServlet.class);
(where MyOtherServlet class has a #Singleton annotation above it)
My intention here was to have two servlets, where one is eagerly instantiated, while the other isn't. However it seems like the "serve... with..." line automatically instantiates servlets objects, even though that class is not bound as an eager singleton.
The link I attached above mentions difference between Guice running under Stage.Development and Stage.Production - however this still happened even when I explicitly used Stage.Development (which is the default one anyway).
Is there any way to avoid this?
(continues 1) Trying to ensure that MyServlet gets instantiated first even though all servlets instantiate eagerly now, I've modified the order of modules (and binding statements) when creating an Injector, so that the binding for MyServlet appears first. However, I found that it still gets instantiated later than some other bindings (of non-servlet classes), which were of the form:
bind(MyInterface.class).to(MyClass.class).asEagerSingleton()
even though those other bindings appeared later in the modules/bindings order.
I've looked into it, and found that Guice simply instantiates eager singletons which were bound by the form of "bind... to... asEagerSingleton()" before it does ones of "bind... asEagerSingleton()", and so I solved it by modifying the line:
bind(MyServlet.class).asEagerSingleton();
into:
bind(MyServletDummyInterface.class).to(MyServlet.class).asEagerSingleton()
and that actually worked. Still, I'd rather avoid having a dummy interface just to solve this, so I was wondering if anyone had a better solution for this..?
I have two Guice modules - one ServletModule and one AbstractModule.
The ServletModule configureServlets() has the following binding in it:
serve("aUrl").with(SomeServlet.class);
The AbstractModule's configure() has the following bindings:
bind(SomeImpl.class).asEagerSingleton();
bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class);
Additionally, The SomeServlet class has an injected field of type SomeInterface, and has a #Singleton annotation on top of the class.
Now, one would expect that upon creating an injector, the SomeImpl class will get instantiated, and the same instance will be injected into the SomeServlet instance. As mentioned before, servlets bounded with a "serve... with..." statement also seem to get eagerly instantiated, but either way there should still be only one SomeImpl object instantiated. Yet for some reason, I got two SomeImpl objects instantiated when doing this.
To get around it, I mixed the two lines in configure() a bit, and instead of the above I had there the following lines:
bind(SomeImpl.class).in(Singleton.class)
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton();
and then it worked fine, and I got only one instance of SomeImpl instantiated. I don't really get why the switch should matter - I can see how the latter way is "better", but I'd expect both to work correctly, so I'm just wondering if I'm getting something wrong here...
1) There is no way to avoid this, since Guice calls the init() method of all servlets on initialization of its own filter pipeline and thus constructs them all. If you really need such lazy initialization logic, you should place it into the servlet itself (or use a decoupled helper class, or... there are many ways, depending on your use case).
2) Generally said, the modules of Guice declare bindings, there are not designed to be bootstrap definitions with precise instantiation orders. If you need such a defined instantiation order, create the objects yourself in the desired order and bind them via bind(...).toInstance(...). If you need injection in the self constructed instances you may use requestInjection(...) (if field/method injection is sufficient, it's more cumbersome for constructor injection).
3) The scope of Guice applies to the binding key, not the binding value, Applying Scopes describes why only your second example is working as intended.

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