3

Env:

Wildfly 8.2.0 Final
JDK 8
Java EE 7

Please note that by 'POJO' i am referring to the classes that serve the other classes i.e other than value objects, entities.

This question was on back of my head for some time. Just wanted to put it out.

Based on CDI and Managed Beans specs and various other books/articles, its pretty clear that CDI injection starts with a 'managed' bean instance. By 'managed' i mean servlet, EJBs etc. which are managed by a container. From there, it injects POJOs (kind of crawl through layers) till every bean gets its dependencies. This all makes very sense to me and i see very little reason why developers ever need to use "new" to create an instance of their dependent POJO's.

  1. One scenario that comes to my mind is when developer would like to have logic similar to
if(something) { 
 use-heavy-weight-A-instance
} else {
 use-heavy-weight-B-instance
}

But, that also can be achieved via @Produces.

  1. Here is one scenario that i verified to be true in wildfly 8.2.0 Final i.e. CDI is not able to inject bean when the JSP has
<%!
  @Inject
  BeanIntf bean;
%>

But, the alternative to use a servlet works fine.

That said, would like to know if there is any scenario(s) where a developer has to use 'new'. As i understand, by using 'new', developer owns the responsibility of fulfilling dependencies into that bean and all its dependent beans, and their dependent beans etc..

Thanks in advance,

Rakesh

Community
  • 1
  • 1
  • 1
    *"But, the alternative to use a servlet works fine with a glitch. The injected bean becomes kind of singleton and associated to the servlet (single instance per VM) lifecycle."* How exactly did you came to this assumption/observation/conclusion? Namely, this is completely wrong and thus likely the root of all your confusion. – BalusC Oct 02 '15 at 11:15
  • Interesting to hear that. From servlet spec "For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration." Just to defend my point, it was verified via code and it makes sense logically too. Basically, the dependent bean gets injected only once as the servlet gets instantiated once per VM. Any reason why you say it is incorrect ? – Rakesh Kumar Cherukuri Oct 02 '15 at 11:22
  • I was not referring to servlet part. I was referring to the injected bean part. It's a proxy. Related: http://stackoverflow.com/q/8658392 and http://stackoverflow.com/a/29672591 – BalusC Oct 02 '15 at 11:25
  • 1
    Aah. Thats a bummer. Thanks. I see your point. Correcting the post... – Rakesh Kumar Cherukuri Oct 02 '15 at 11:30
  • One thing I don't find exactly clear: does this question only target why you would manually instantiate named beans, or does it refer to using 'new' for any and all object instance of any class? Including VOs, JPA entities, etc. – Gimby Oct 02 '15 at 12:27
  • To be specific 'new' for anything that serves the non-CDI managed beans i.e. as dependency. Also, i believe, in OO world, other than static utility classes everything should be an object with proper responsibilities. In that sense, my answer to your question is 'yes' : 'new' for any and all object instance of any class – Rakesh Kumar Cherukuri Oct 02 '15 at 12:34
  • @Gimby in addition to what my earlier comment says, i kind of get your hint at creation of JPA entities and VOs. But those are not to serve other classes but represent data part of it. Isnt it ? – Rakesh Kumar Cherukuri Oct 02 '15 at 12:42
  • 1
    Correct, and I'm glad you're not going that far :) Its hard to give a definitive answer to this question in any case. Integration projects where frameworks that are not CDI-enabled are involved come to mind. – Gimby Oct 02 '15 at 12:56
  • @Gimby Thanks for bringing that up and its a valid point. Let me correct the post a bit to be specific. – Rakesh Kumar Cherukuri Oct 02 '15 at 12:59

1 Answers1

2

When using CDI or other container you don't use new, because you expect a bunch of service coming from the container.

For CDI these main services are:

  • Injection of dependent beans (get existing instance or create a new instance)
  • Lifecycle callback management (@PostConstruct and @PreDestroy)
  • Lifecycle management of your instance (a @RequestScoped bean will make container produce an instance leaving until the end of request)
  • Applying interceptors and decorators on your instance
  • Registering and managing observers methods
  • Registering and managing producers methods

Now, on some rare occasion, you may want to add a part of these services to a class you instantiate yourself (or that another framework like JPA instantiate for you).

BeanManager bm = CDI.current().getBeanManager();

AnnotatedType<MyClass> type = bm.createAnnotatedType(MyClass.class);
InjectionTarget<MyClass> it = bm.getInjectionTargetFactory(type).createInjectionTarget(null);
CreationalContext<MyClass> ctx = bm.createCreationalContext(null);

MyClass pojo = new MyClass();
injectionTarget.inject(instance, ctx); // will try to satisfied injection points 
injectionTarget.postConstruct(instance); // will call @PostConstruct

With this code you can instantiate your own MyClass containing injection points (@Inject) and lifecycle callbacks (@PostConstruct) and having these two services honored by the container. This feature is used by 3rd party frameworks needing a basic integration with CDI.

The Unmanaged class handle this for you, but still prevent you to do the instantiation ;).

Antoine Sabot-Durand
  • 4,875
  • 17
  • 33