6

Is it possible to manually Inject a bean into a CDI context? With the JBoss Seam framework, I could always do something like Contexts.getConversationContext().set("foo", bar); and the Bean would become part of that context. Is it possible to do something like this in Java EE 6 CDI?

Shadowman
  • 11,150
  • 19
  • 100
  • 198

3 Answers3

4

With CDI you have to slightly change the way you think about the scoped beans. In Seam2 the contexts are just maps that are held in a specific scope and you have access to these maps. In CDI the container gets the control over the contexts and allows you only to declare beans in a concrete scope and everything gets managed behind the scene without access to the scope maps. This is done because CDI philosophy is to keep the things type-safe and just setting things in a map with a string as a value and injecting them by their string key isn't type-safe at all.

To achieve the goal you want create a "holder" bean in the concrete scope and hold your values there.

@Named
@ConversationScoped
public class UserManager {

  private User currentUser;

  //getters and setters for currentUser

}

In this sample the a User instance is held in the conversation scope by setting it in the conversation-scoped bean. This is completely type-safe as you can inject the UserManager anywhere you want just by using @Inject (actually it's bean type gets used) avoiding string keys (as in Seam2) that are unsafe when doing refactoring.

Adrian Mitev
  • 4,722
  • 3
  • 31
  • 53
3

Isn't that possible using Producer methods?

http://docs.jboss.org/weld/reference/1.0.0/en-US/html/producermethods.html

I've done this to create the objects that get injected into my beans.

While I haven't used this, there is also the BeanManager interface

http://docs.jboss.org/weld/reference/1.0.0/en-US/html/extend.html

Or are you after something specific in the Conversation scope?

EdH
  • 4,918
  • 4
  • 24
  • 34
  • Ideally, I'd like to be able to Inject into whatever scope I need. Currently, I have a need to Inject into a Request scope, but I can see use cases where we'll need to Inject into Conversation or Session scopes, as well. – Shadowman Feb 03 '14 at 23:07
  • 1
    Well, I've defined a Producer, which I then use via the \@Inject annotation. The specific example is a Faces application. I've defined a FacesContextProducer class that allows ManagedBeans to inject the current FacesContext (so I don't have to repeat all the boilerplate code to get at the FacesContext via the static getInstance() method). I can use that no matter what scope the bean using the \@Inject annotation is running. I found that quite flexible and cleared up a lot of repetitive code in my application. – EdH Feb 04 '14 at 00:15
  • 3
    Plus if you don't define a scope, it'll implicitly be `Dependent`, and inherit the scope of the bean being injected to. – John Ament Feb 04 '14 at 00:54
  • John, "inherit"? Dependent is a pseudo-scope meaning it isn't even a scope. Type-level metadata (the actual bean defining scope annotation) is another thing (see CDI 1.1, section 4.1). To be clear for other readers; `@Dependent` mean that the container will create a new instance (CDI 1.1 actually make @Dependent replace @New) for each injection point (@Inject). No two injection points will ever share the same instance. After creation, the container then forget about the bean; thus making it dependent on the life cycle of the enclosing object instance. – Martin Andersson Feb 06 '15 at 22:00
-2

There is no way to do this in an implementation agnostic way. You'd have to dig into the implementation, find the scope objects, pull them out via a BeanManager and figure out how to add them. Not all of them (quite possibly none of them) are as easy to set as maps.

LightGuard
  • 5,298
  • 19
  • 19