3

I have a CDI bean, and a interceptor is added to one method of this bean. If this bean doesn't have a default constructor(I use the Constructor Injection). At runtime, I get the exception

java.lang.Class.newInstance0(Class.java:357)
java.lang.Class.newInstance(Class.java:325)
org.apache.webbeans.proxy.javassist.JavassistFactory.createProxy(JavassistFactory.java:79)
org.apache.webbeans.proxy.ProxyFactory.createProxy(ProxyFactory.java:241)
org.apache.webbeans.proxy.ProxyFactory.createDependentScopedBeanProxy(ProxyFactory.java:412)
org.apache.webbeans.component.AbstractInjectionTargetBean.createDefaultInstance(AbstractInjectionTargetBean.java:140)
org.apache.webbeans.component.AbstractInjectionTargetBean.createInstance(AbstractInjectionTargetBean.java:116)
org.apache.webbeans.component.AbstractOwbBean.createNewInstance(AbstractOwbBean.java:233)
org.apache.webbeans.portable.creation.AbstractProducer.produce(AbstractProducer.java:77)
org.apache.webbeans.component.InjectionTargetWrapper.produce(InjectionTargetWrapper.java:136)

If I add a default constructor in this bean, or remove the interceptor, it will be OK. In fact, I can use the field injection to handle this question.

But I want to know: if I add a default constructor, that means this bean has two constructors -- one is non-parametric, the other with @Injected parameters. In this case (with interceptor), will The container create the instance twice?

Edit: I use Tomee1.5, and WebShpere8.5 is same as Tomee1.5 and it seems that GlassFish3.1.2 does not have this issue.

Edit: i found an answer in Tomee User Forum that is The CDI container will invoke the @Inject annotated ct for your bean but will use the default ct for creating the proxies. So, I think that means if you want to use constructor injection, u also need a default constructor for being proxyable.

Edit:

  1. According to http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#d0e1443 unless a bean has the default scope @Dependent, the container must indirect all injected references to the bean through a proxy object.

  2. According to //openejb.979440.n4.nabble.com/RequestScoped-CDI-constructor-td4661541.html The CDI container will invoke the @Inject annotated constructor for your bean but will use the default constructor for creating the proxies. Therefor The default constructor is needed for all 'NormalScoped' (@RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped) beans because they will always get proxied.

  3. If a bean uses interceptor, according to the error message, OpenWebBean uses Proxy to deal with interceptor, so the intercepted classes must have the default construct. But Weld uses subclasses for interceptors and decorators. https://issues.jboss.org/browse/WELD-437?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel The subclassing solution is superior to proxification, since it avoids dealing with a number of issues such as: intercepted classes without a no-arg constructor and field access on proxified instances. So, if I use Tomee and Websphere, it needs a default ct, but GlassFish doesn't.

    Thanks brandizzi, It is my first question here. Thank you for your help. And it seems I can not answer my own question and post more than two links without 10 reputation, so I edited here.

  • About the question in the title, I have posted an [answer](http://stackoverflow.com/questions/7583871/injecting-a-named-string-using-cdi/7584762#7584762) which can be useful. – brandizzi Mar 26 '13 at 12:57
  • BTW, when you add the default constructor, do you remove the injected constructor? – brandizzi Mar 26 '13 at 12:58
  • I do not remove the injected constructor. – user2211527 Mar 26 '13 at 13:05
  • I have read the answer you have posted and it makes me confused. If a proxyable Bean must have a default constructor, then when should we use the injected constructor? – user2211527 Mar 26 '13 at 13:16
  • thanks brandizzi. yes you are right. I have edited the question. – user2211527 Mar 26 '13 at 13:46
  • _If a proxyable Bean must have a default constructor, then when should we use the injected constructor?_ Well, beans are proxiable mostly in function of its scope. Request-scoped beans, application-scoped beans, singletons and _some_ dependent beans need not be proxiable, for example, since they need not to be passivated (that is, saved in persistent memory, such as disk) and so do not require a default constructor. – brandizzi Mar 26 '13 at 14:31
  • Also, a suggestion: your second edit seems to be the exact answer to your own question. Post it as the answer and accept it! It eases the reading for future readers and nonetheless you sure deserve the upvote for the question _and_ the answer :) – brandizzi Mar 26 '13 at 14:32

1 Answers1

0

As documented in the CDI specification, a CDI bean that has a bound interceptor must be proxyable, as defined in unproxyable bean types, which states in addition that proxyble beans are classes which have a non-private constructor with no parameters.

Antonin Stefanutti
  • 1,061
  • 6
  • 6