0

直到最近,我一直在 servlet 中使用以下代码来定位会话支持 bean(如 BalusC 所建议的)而没有问题。现在它只适用于 Internet Explorer。Chrome 和 Firefox 似乎正在获得一个全新的支持 bean,而不是原来的支持 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 更改了其代码中的某些内容(不太可能)。其他人有类似的问题吗?我不知道从哪里开始,因为似乎没有任何与找不到支持 bean 相关的错误,而且我对 java lib 代码的调试技能也不是很好(他们没有评论他们的代码很好,很难理解);任何建议将不胜感激。

我正在使用 Netbeans 7.01、JSF 2.0、Glassfish 3.1 和一个 Derby 数据库。我在我的塔式电脑和笔记本电脑上对其进行了测试,并且在两者(Win XP 和 Win 7)上都可以做到。JRE 是 7 update 40 build 1.7.0_40-b43。JDK 是 1.6.0_04。Chrome 版本为 29.0.1547.76 m。火狐是 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);
        }
    }
}

提前谢谢...

4

1 回答 1

0

解决方法:由于某种原因,当从小程序调用 servlet 时,Firefox 和 Chrome 上的会话 ID 会发生变化。我最终存储了会话 ID 并将其设置在与 servlet 的 HttpURLConnection 连接上,这会强制 servlet 获取正确的支持 bean。

在 productSelection 支持 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>

在小程序按钮代码中,为了通过servelet 将修改后的条件文件提交回支持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();
于 2013-10-09T08:31:19.017 回答