1
votes

I am developing a new JSF 2.2 application.

I have an eagerly created, application scope managed bean that loads up some configuration data from an external file, at startup, and stores it as state.

I have a FacesComponent and FacesRenderer that I have working statically.

I would like to be able to get the configuration data stored in the managed bean into the FacesComponent. Is there a standard way to do this.

As far as I am aware, the managed bean cannot be injected into the component - is that correct?

I can try to get data into the custom component using attributes and el in the .xhtml file that uses the custom component e.g.

<my:customComponent data="#{managedBean.loadedData}"/> 

but this seems like a really backwards way to do things and actually exposes internal implementation of the component to the component user.

Please let me know if there is another way, or if you need any more information.

Update: @BalsusC I have tried what you suggested

I have a loader that puts the loaded data into a holder object

@Named
@ApplicationScoped
public class Loader implements Serializable {

    @Inject
    private Holder holder

    @PostConstruct
    public void init() {
        // Load data into the holder here
    }

}

The holder is another application scoped bean

@Named
@ApplicationScope
public class Holder {...}

When loading the data the Holder instance is injected correctly into the Loader.

However when I they the following

@Named    //Makes no difference if this is here or not
@FacesComponent(value="family", createTag=true, namespace="...namespace...", tagName="tag")
public class Component extends UIComponentBase {

    @Inject
    public class Holder holder;

    @Override
    public void encodeBegin(FacesContext context) {
        holder.getData();
    }
}

when the component comes to render, the holder is not injected and I get a null pointer exception. I have tried to do this with our without the @Named annotation with the same result.

Am I doing something wrong? Can you please advise.

1
Clarification: by 'working statically' I mean that the component works with fixed data. I am trying to make it dynamic by using the configuration loaded at startup. - Conrad Winchester

1 Answers

2
votes

Application scoped JSF managed beans are internally stored in the application map with the managed bean name as key.

So, the below inside any of UIComponent methods should do:

ManagedBean managedBean = (ManagedBean) getFacesContext().getExternalContext()
    .getApplicationMap().get("managedBean");
// ...

This only makes the component tight coupled to the managed bean. I.e. the component can't exist without the managed bean. This should be clearly documented if the component is intented to be reusable in other webapps. Another option is to tie the managed bean exclusively to the component (perhaps in form of a composite component) and use another application scoped bean for "unrelated" application data.