在Facelet模板中动态加载JSFbean
我在程序中动态加载bean时遇到问题。我的facelet模板如下所示:在Facelet模板中动态加载JSFbean,jsf,facelets,javabeans,Jsf,Facelets,Javabeans,我在程序中动态加载bean时遇到问题。我的facelet模板如下所示: <ui:define name="content"> <f:loadBundle var="Application" basename="start" /> <f:loadBundle var="Messages" basename="#{ApplicationController.bundleName}" /> <h:panelGro
<ui:define name="content">
<f:loadBundle var="Application" basename="start" />
<f:loadBundle var="Messages" basename="#{ApplicationController.bundleName}" />
<h:panelGroup rendered="#{ApplicationController.chosenBean.hasAccess}">
<h:form>
<h:outputText value="Error: #{ApplicationController.chosenBean.errorMessage}" id="outputErrorMessage2" /><br />
<h:outputText value="Report running: #{ApplicationController.chosenBean.runningReport}" /><br />
<ui:insert name="application-content" />
<h:commandButton action="#{ApplicationController.chosenBean.actionRunReport}" value="Create report"/>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{!ApplicationController.chosenBean.hasAccess}">
<h:outputText value="Err" />
</h:panelGroup>
</ui:define>
我所有的Javabeans都是ReportWeb类的子类,它是一个包含访问逻辑和其他方便方法的抽象类。最重要的方法是
public abstract String actionRunReport();
我所有的报告都实现了这一点。但是,在我的模板中,我无法通过以下操作调用此方法:
<h:commandButton action="#{ApplicationController.chosenBean.actionRunReport}" value="Create report"/>
我没有收到任何错误消息,但它就是不工作。我必须像这样硬编码Javabean名称:
<h:commandButton action="#{AntallHenvendelser.actionRunReport}" value="Create report"/>
一个女人知道为什么我的技术不起作用吗
编辑:
从不从动态加载bean的操作按钮调用该方法。根本原因可能是因为在表单提交请求期间,操作组件(或其至少一个父组件)的
rendered
属性已评估false
。这样就不会调用该操作。您需要确保在处理表单提交请求时,rendered
属性不会计算false
有关未调用操作组件的可能原因的概述,请参见
不管怎样,您所展示的方法显然是低效的。我将使
ApplicationController
请求的作用域限定,并按如下方式加载所选bean:
public class ApplicationController {
private ReportWeb chosenBean;
public ApplicationController() {
chosenBean = findBean(getReportNameFromServletPath(), ReportWeb.class);
}
public static <T> T findBean(String managedBeanName, Class<T> beanClass) {
FacesContext context = FacesContext.getCurrentInstance();
return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", beanClass);
}
// ...
}
公共类应用程序控制器{
私有报告网络chosenBean;
公共应用程序控制器(){
chosenBean=findBean(getReportNameFromServletPath(),ReportWeb.class);
}
公共静态T findBean(字符串managedBeanName,类beanClass){
FacesContext context=FacesContext.getCurrentInstance();
返回beanClass.cast(context.getApplication().evaluateExpressionGet(上下文“{”+managedBeanName+“}”,beanClass);
}
// ...
}
这样,每个请求只加载一次,而不是每个调用getter的EL表达式至少加载一次(在rendered
属性中使用时,可以至少加载两倍)
通过这种方式,您还可以获取实际上由JSF管理的bean,而不是创建它(两次!)在getter中手动创建。如果JSF已经创建了一个实例,那么将返回这个实例。如果JSF还没有创建它,那么将创建一个新实例,并在返回之前将其相应地放入范围中。不确定问题的原因,但是您是否意识到,通过这种方式,EL的每个getter调用都会返回一个不同的实例bean,甚至不是由JSF管理的bean?这是令人震惊的低效…至于故障排除问题,您是如何得出它“不工作”的结论的?
actionRunReport()
方法被调用了吗?谢谢你,巴卢斯克。我没有意识到这个方法效率低下。你对我如何获得托管bean的回报有什么建议吗?我所有的bean都在请求范围内,但我明白你的意思:)我已经发布了答案。顺便说一句,使用@昵称通知其他人关于非他们自己帖子的评论回复。另外,你也可以看到,你依赖于他们的热情来回过头来看这篇文章。这是有效的!因为您的方法通过FacesContext加载bean,所以我也可以通过bean运行操作!我在程序中所做的唯一修改就是采用findBean方法,而不是.newInstance()。非常感谢你!
public class ApplicationController {
private ReportWeb chosenBean;
public ApplicationController() {
chosenBean = findBean(getReportNameFromServletPath(), ReportWeb.class);
}
public static <T> T findBean(String managedBeanName, Class<T> beanClass) {
FacesContext context = FacesContext.getCurrentInstance();
return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", beanClass);
}
// ...
}