4

In a Java EE 6, CDI 1.1.x, Seam 3 etc. environment, we need to find all CDI beans of the current view (@ViewScoped). What I have tried so far is using:

@Named
@ViewScoped
public class ViewHelper
{
    @Inject
    private BeanManager beanManager;

    public doSomethingWithTheBeanInstances()
    {
        Set<Bean<?>> beans = this.getBeanManager().getBeans( 
            Object.class, new AnnotationLiteral<Any>(){}
        );

        // do something
        ...
    }
}

However, this returns all beans it manages.

I need to find only those within the scope of the current view and - that would be ideal - only those that implement a specific interface (inherited over over multiple hierarchy levels).

What's the way to do it?

Note since CDI has no view scope, we're using Seam 3 to be able to annotate all our view-scoped beans like:

@Named
@ViewScoped
public class ResultManagerColumnHandler extends BaseColumnHandler
{
    ....
}

The above would be an instance to look for (the @ViewScoped is a CDI replacement by Seam 3).

How can it be done?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Kawu
  • 13,647
  • 34
  • 123
  • 195
  • Just a quick thought - if all those beans you want implement specific interface, then they have the Type of that interface, so you could perchance do `@Inject Instance instances`. Now, because `Instance` implements Iterable, you should be able to iterate over all the instances. – Siliarus Feb 06 '17 at 07:37
  • The problem still is **HOW** do I get only those within the current view without knowing the specific bean names (EL names and/or class names)...??? – Kawu Feb 06 '17 at 17:01
  • 2
    I'm not familiar with Seam3, but does `Context context = beanManager.getContext(ViewScoped.class);` return a valid `Context`? (i.e. not null nor an exception). If that part works, then I can post an answer how to use it to get the currently active beans. – BalusC Feb 06 '17 at 19:00
  • 2
    Siliarus stole my answer, but if `Context` would be valid, then it basically boils down to the approach as shown in his post. It has been in [OmniFaces](https://github.com/omnifaces/omnifaces/blob/2.6/src/main/java/org/omnifaces/util/BeansLocal.java#L152) for ages (authored by yours truly). – BalusC Feb 07 '17 at 11:47
  • Any luck? I didn't got any feedback on my first comment. At least I remembered this dupe http://stackoverflow.com/q/33478927 – BalusC Feb 12 '17 at 15:22

1 Answers1

3

I am not familiar with Seam, but from CDI standpoint, this is what I would try. However, bean it mind that it will only work if beanManager.getContext(ViewScoped.class); returns a valid context instance for you:

@Inject
BeanManager bm;

public List<Object> getAllViewScoped() {
    List<Object> allBeans = new ArrayList<Object>();
    Set<Bean<?>> beans = bm.getBeans(Object.class);
    // NOTE - context has to be active when you try this
    Context context = bm.getContext(ViewScoped.class);

    for (Bean<?> bean : beans) {
        Object instance = context.get(bean);
        if (instance != null) {
            allBeans.add(instance);
        }
    }

    return allBeans;
}

You also asked to only obtain beans that implement certain interface. For that, simply modify the code line retrieving all beans with desired type:

Set<Bean<?>> beans = bm.getBeans(MyInterface.class);
Kawu
  • 13,647
  • 34
  • 123
  • 195
Siliarus
  • 6,393
  • 1
  • 14
  • 30
  • Yea, thanks. I was trying the code in my IDE for AppScoped and forgot to edit this piece after pasting. – Siliarus Feb 07 '17 at 08:11