3

Is there a way to specify a managed bean used in EL at runtime and not design time? E.g. actionListener="#{myBean.method}" such that myBean part can have different values depending on the JSF page the code is invoked from (on condition that any object used instead of myBean is derived from a common parent implementing the "method").

Bharat Sinha
  • 13,973
  • 6
  • 39
  • 63
azerIO
  • 519
  • 1
  • 9
  • 19

2 Answers2

5

If you know the bean scope beforehand and the bean is already created beforehand, then yes, it's possible using the following syntax:

actionListener="#{requestScope[beanName].method}"

where #{requestScope} represents the request scope map (same maps are available for view, session and application scopes) and #{beanName} represents the variable holding the managed bean name.

If you don't know the bean scope beforehand and/or when the bean isn't created beforehand, then you'd need to create an utility EL function which does an Application#evaluateExpressionGet(), so that it can be used something like as follows:

actionListener="#{util:getBean(beanName).method}"
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • My scope is "ViewScoped", so I guess the second part of your answer might suite better. The trouble is that I do not know the name of the bean at runtime. You wrote {util:getBean(beanName).method} assuming that I know "beanName". However, I need to get the bean (whatever its name is) associated with a given page under conditions: 1) there is only one ViewScoped bean associated with a page and 2) This bean is inherited from "Parent" bean. – azerIO Aug 28 '12 at 13:17
  • 1
    As answered, same maps are available for view, session and application scopes. Use `#{viewScope[beanName].method}`. You can maybe use the view ID as bean name. You can use `#{view.viewId}` to get the view ID. You probably only need to split the path `/` and parent folders from it. You can use JSTL functions for this. – BalusC Aug 28 '12 at 13:18
  • Thank you, I'll dig into the literature try it out now and write back. – azerIO Aug 28 '12 at 13:21
  • I put this in my code: . WF_M_2 is the actual name of the bean (just wanted to try out the approach). I get the "Target Unreachable, 'project.modules.dev2.managedBeans.miniwf.WF_M_2@6215db' returned null" when pressing the button. – azerIO Aug 28 '12 at 16:24
  • 1
    Sorry, I forgot to mention an important prerequirement: the bean must be already created beforehand (this is usually done by explicitly specifying `#{beanName}` in the view beforehand). I updated the answer. Your best bet seems really to use some EL utility function (or when using EL 2.2, even some helper method of an application scoped managed bean). You can find in this answer how to create a custom EL function: http://stackoverflow.com/questions/7079978/how-to-create-a-custom-el-function/7080174#7080174 – BalusC Aug 28 '12 at 16:48
  • PS. For those who look for a way to parse using JSTL, see here: http://stackoverflow.com/questions/7017346/how-do-i-parse-through-a-url-path-get-the-filename-then-replace-the-file-exten Also, for the whole solution to work your bean name must match the name of the JSF page (e.g. bean with name Step1 for page with name Step1.xhtml) – azerIO Aug 28 '12 at 17:45
0

If your question refers to generating a set of pages for a number of subclasses with common elements you can also use page composition to achieve this.

For example if Resident and NonResident are managed beans for subclasses of Person:

eg. in 'non-resident.xhtml'

<ui:define name="body">
    <ui:param name="Controller" value="#{NonResident}"/>
    <ui:include src="anyone.xhtml"/>
</ui:define>

and in 'resident.xhtml'

<ui:define name="body">
    <ui:param name="Controller" value="#{Resident}"/>
    <ui:include src="anyone.xhtml"/>
</ui:define>

then 'anyone.xhtml' can define the common elements using 'Controller' for the bean name.

This approach also enables you to eliminate duplicate page definition.

RJA
  • 1