How do you find CDI beans of/in the current view (scope)?
Asked Answered
L

1

5

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?

Leftwich answered 2/2, 2017 at 17:45 Comment(5)
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<YourInterfaceType> instances. Now, because Instance implements Iterable, you should be able to iterate over all the instances.Ordeal
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)...???Leftwich
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.Melpomene
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 for ages (authored by yours truly).Melpomene
Any luck? I didn't got any feedback on my first comment. At least I remembered this dupe https://mcmap.net/q/24420/-get-list-all-initialized-named-beans-on-runtimeMelpomene
O
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);
Ordeal answered 7/2, 2017 at 7:47 Comment(1)
Yea, thanks. I was trying the code in my IDE for AppScoped and forgot to edit this piece after pasting.Ordeal

© 2022 - 2024 — McMap. All rights reserved.