直到最近,我一直在 servlet 中使用以下代码来定位支持会话的 bean(如 BalusC 所建议的那样(,没有问题。现在它只适用于Internet Explorer。Chrome和Firefox似乎得到了一个全新的支持Bean,而不是原来的支持bean。在后备 Bean 中调用函数时,对于后备 Bean 中明确在原始中初始化的对象,它会因空指针错误而失败。
FacesContext facesContext = FacesUtil.getFacesContext(req, res);
ProductSelection productSelection = (ProductSelection) facesContext.getApplication().evaluateExpressionGet(facesContext, "#{productSelection}", ProductSelection.class);
if(productSelection.getProductType() == null)
{
System.out.println("Sevlet: product type is NULL; did not get the original backing bean");
}
else
{
System.out.println("Sevlet: product type is: " + productSelection.getProductType().getProductTypeName());
}
自从我测试这段代码以来已经有一段时间了,并且对 Java 进行了几次更新,但我不确定这些是否是原因;我已经更改了配置中的某些内容,或者Chrome和Firefox在其代码中更改了某些内容(不太可能(。还有其他人有类似的问题吗?我不知道从这里开始,因为似乎没有任何与找不到支持豆相关的错误,而且我对 java lib 代码的调试技能不是那么好(他们没有很好地注释他们的代码,很难遵循(;任何建议将不胜感激。
我正在使用Netbeans 7.01,JSF 2.0,Glassfish 3.1和Derby数据库。我在我的塔式和笔记本电脑上测试了它,它正在两者(Win XP和Win 7(上进行测试。JRE 是 7 更新 40 内部版本 1.7.0_40-b43。JDK 是 1.6.0_04。Chrome 版本是 29.0.1547.76 m。Firefox 是 23.0.1。Internet Explorer 是 8.0.6001.18702。
FacesUtil与BalusC的代码略有不同(但它工作正常(:
package searchselection;
import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
// By BalusC http://balusc.blogspot.com
// Utility to get the FacesContext.
// Used by the CriteriaServlet to get the backing bean when the user submits a customised
// search criteria object.
public class FacesUtil
{
// Getters -----------------------------------------------------------------
//
public static FacesContext getFacesContext(ServletRequest request, ServletResponse response)
{
// Get current FacesContext.
FacesContext facesContext = FacesContext.getCurrentInstance();
// Check current FacesContext.
if (facesContext == null)
{
// Create new Lifecycle.
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Create new FacesContext.
FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
facesContext = contextFactory.getFacesContext(
request.getServletContext(), request, response, lifecycle);
// Create new View.
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(
facesContext, "");
facesContext.setViewRoot(view);
// Set current FacesContext.
FacesContextWrapper.setCurrentInstance(facesContext);
}
return facesContext;
}
// Helpers -----------------------------------------------------------------
// Wrap the protected FacesContext.setCurrentInstance() in a inner class.
private static abstract class FacesContextWrapper extends FacesContext
{
protected static void setCurrentInstance(FacesContext facesContext)
{
FacesContext.setCurrentInstance(facesContext);
}
}
}
提前感谢...
Work-a-round:由于某种原因,当从小程序调用servlet时,会话ID在Firefox和Chrome上正在更改。我最终存储了会话 ID 并将其设置在与 servlet 的 HttpURLConnection 连接上,这迫使 servlet 获得正确的后备 bean。
在产品选择背豆中:
private String sessionID = ""; // With getter
.
.
.
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
sessionID = session.getId();
在包含小程序的网页上,我使用 javascript 函数等到小程序完全加载后再告诉它加载一个标准文件,该文件将由用户修改,然后发送回后备 Bean 进行处理。我只是将会话 ID 与标准文件一起传递给小程序:
<SCRIPT language="javascript">
function waitUntilLoaded()
{
if (document.criteriaApplet.isActive())
{
var object = document.getElementById ("criteriaApplet");
criteriaApplet.loadCriteriaFile((object.codeBase + "#{productSelection.productUsage.searchCriteriaObjectUrl}"), "#{productSelection.sessionID}");
}
else
{
settimeout(waitUntilLoaded(),500)
}
}
</SCRIPT>
在小程序按钮代码中,为了通过 servlet 将修改后的标准文件提交回支持Bean,我将会话 ID 添加到 HttpURLConnection 连接中:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-java-serialized-object");
connection.setRequestProperty("Cookie","JSESSIONID=" + sessionID);
ObjectOutputStream out = new ObjectOutputStream(connection.getOutputStream());
out.writeObject(searchSubmitObject);
out.flush();
out.close();