如何从一个Applet提交序列化对象,通过一个se​​rvlet,到后台bean,然后打开一个结果JSF页面 [英] How to submit a serialised object from an Applet, via a servlet, to a backing bean then open a results JSF page

查看:335
本文介绍了如何从一个Applet提交序列化对象,通过一个se​​rvlet,到后台bean,然后打开一个结果JSF页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名应用程序员做我的第一个JSF 2.0网站,坦白地说,我不知道像我应该关于JSF。我一直在pooring为文档几个月,由于特别是这些论坛,都没有得到坚持了这一点。网站的堆积完成和工作与这里所使用的背衬bean被别处使用没有问题。

我有一个序列化的搜索条件对象需要从一个applet到后台bean提交,通过一个se​​rvlet。 backing bean的方法,然后处理搜索标准数据,并将其应用到产品列表,在一个数据库中保存,然后显示在一个新的JSF页面排名的产品列表中。

所有试图打开一个搜索结果页用正确的数据都失败了。导航案回归process_MainSearchResult;是不是做在后端bean中任何东西(见支持豆code进一步下降和faces-config条目)。我曾尝试使用appletContext.showDocument(见下文),但新的页面不具有的搜索条件的对象传递给后台bean,因此,没有正确的数据,从applet打开一个搜索结果页。

需要注意的是在applet的setRequestMethod设置POST没有影响;它总是使用服务。如果setDoInput和setDoOutput未设置为true,从servlet发送回一个小程序的响应,那么提交的对象不会发送,没有任何反应。我怀疑这是在我的问题的核心,但改变它以任何方式阻止被成功提交的序列化对象。

因为它的立场,对象被成功发送到支持bean但新页面将不会使用正确的数据加载(在小程序,而不是在servlet重定向使用showDocument)。是否有设置原始支持bean的新网页或我在做的一种方式这一切都错了吗?

Web服务器是Glassfish的3.x中,IDE是Netbeans的7.0.1,系统是WinXP的。
支撑类是'ProductSelection'; servlet类是CriteriaServlet。

小程序提交搜索条件按钮,code:

 私人无效jButton8ActionPerformed(java.awt.event.ActionEvent中EVT)
{
    criteriaModel.load codeBase的();
    INT选择= JOptionPane.showConfirmDialog(这一点,
         你确定要提交您的搜索条件,并退出\\自定义搜索条件\\网页?
         确认提交,
         JOptionPane.YES_NO_OPTION,
         JOptionPane.QUESTION_MESSAGE);     如果(选择== 0)
     {
         尝试
         {
             URL网址;             URL =新的URL(criteriaModel.get codeBase的(),CriteriaServlet);             的System.out.println(Servlet的地址是:+网址);            //获取搜索条件对象。
            对象searchSubmitObject = criteriaModel.getObjectSlideData();            HttpURLConnection的连接=(HttpURLConnection类)url.openConnection();
            connection.setDoInput(真);
            connection.setDoOutput(真);
            connection.setUseCaches(假);
            connection.setRequestMethod(POST);
            connection.setRequestProperty(内容类型,应用程序/ x-j​​ava的序列化对象);            ObjectOutputStream的出=新的ObjectOutputStream(connection.getOutputStream());
            out.writeObject(searchSubmitObject);
            了out.flush();
            out.close();
            out.close();            的System.out.println(对象书面);            //如果和相应的servlet响应code被删除
            //则searchSubmitObject失败时发送。
            在ObjectInputStream的=新的ObjectInputStream(connection.getInputStream());
            字符串的响应=(字符串)in.readObject();
            的System.out.println(响应);
            附寄();
         }
         赶上(MalformedURLException的前)
        {
            JOptionPane.showMessageDialog(jPanel8,提交文件的标准URL格式不正确。
                    + ex.toString());
            的System.out.println(MalformedURLException的发生);
            。Logger.getLogger(CriteriaInterfaceView.class.getName())日志(Level.SEVERE,空,前);
        }
        赶上(例外五)
         {
             的System.out.println(提交的标准文件错误异常:+ e.toString());
             JOptionPane.showMessageDialog(jPanel8,提交标准文件错误例外:
                    + e.toString());
         }
     }    //这将打开一个新的网页,但一个新的辅助bean与错误的数据。
    尝试
    {
        appletContext.showDocument(新URL(criteriaModel.get codeBase的()+MainSearchResult.xhtml),_ SELF);
    }
    赶上(MalformedURLException的前)
    {
        。Logger.getLogger(CriteriaInterfaceView.class.getName())日志(Level.SEVERE,空,前);
    }
}

我曾尝试使用重定向(URL),但没有成功在servlet重定向:

  @覆盖
公共无效服务(ServletRequest中REQ,ServletResponse的RES)抛出了ServletException,IOException异常
{
    的System.out.println(服务(ServletRequest中REQ,ServletResponse的水库));    res.setContentType(应用程序/ x-j​​ava的序列化对象);    尝试
    {
        在ObjectInputStream的=新的ObjectInputStream(req.getInputStream());
        slideData =(MultipleSlideDataObject2)in.readObject();
        附寄();        如果(slideData!= NULL)
        {
            的System.out.println(提交滑轨系列的序列号是:+ slideData.getSerialNumber());
        }        字符串TEMP =标准文件收到;
        ObjectOutputStream的outputToApplet =新的ObjectOutputStream(res.getOutputStream());
        outputToApplet.writeObject(临时);
        outputToApplet.flush();
        outputToApplet.close();
    }
    捕捉(ClassNotFoundException的前)
    {
        。Logger.getLogger(CriteriaServlet.class.getName())日志(Level.SEVERE,空,前);
    }    FacesContext中的FacesContext = FacesUtil.getFacesContext(REQ,RES);
    //获取支持bean。
    ProductSelection productSelection =(ProductSelection)facesContext.getApplication()evaluateEx pressionGet(FacesContext中,#{} productSelection,ProductSelection.class)。
    productSelection.submitSearchCriteriaFile(slideData);    //这会引发java.lang.IllegalStateException错误。
    尝试
    {
        FacesContext的上下文= FacesContext.getCurrentInstance();        的ExternalContext extContext = context.getExternalContext();
        串的url = extContext.en codeActionURL(context.getApplication()getViewHandler()getActionURL(上下文中,/MainSearchResult.xhtml)。);        extContext.redirect(URL);
    }
    赶上(IOException异常E)
    {
        抛出新FacesException(E);
    }

因为我怀疑当前的响应已经提交提供了以下错误:


  

警告:StandardWrapperValve [CriteriaServlet]:PWC1406:Servlet.service()进行的servlet CriteriaServlet抛出异常
  java.lang.IllegalStateException
      在org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:522)
      在com.sun.faces.context.ExternalContextImpl.redirect(ExternalContextImpl.java:572)
      在searchselection.CriteriaServlet.service(CriteriaServlet.java:217)
      在org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
      在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
      在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
      在org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
      在com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
      在com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
      在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
      在org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
      在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
      在com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
      在com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
      在com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
      在com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
      在com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
      在com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
      在com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
      在com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
      在com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
      在com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
      在com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
      在com.sun.grizzly.ContextTask.run(ContextTask.java:69)
      在com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:330​​)
      在com.sun.grizzly.util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:309)
      在java.lang.Thread.run(Thread.java:619)


返回process_MainSearchResult在后端bean中不起作用:

 公共字符串submitSearchCriteriaFile(MultipleSlideDataObject2 slideData)抛出IOException异常
{
    的System.out.println(收到滑系列编号:+ slideData.getSerialNumber());    //如果没有幻灯片数据然后...
    如果(slideData == NULL)
    {
        返回process_MainSearchResultFailed
    }
    其他
    {
        rankProducts(slideData);
    }    rowStart = 0;
    currentStartPage = 0;
    currentPageIndex = 0;
    calculateNumberPages();
    SetupPaginationValues​​();    //忽略此...
    返回process_MainSearchResult
}

faces-config.xml中的条目:

 <导航规则>
    <导航功能的情况下,>
        <从-结果> process_MainSearchResult< /从-结果>
        &LT;要-view-id的&GT; /MainSearchResult.xhtml< /为-view-id的&GT;
    &LT; /导航情况&GT;
&LT; /导航规则&GT;

我也试过这个在支持bean强制重定向:

  FacesContext的上下文= FacesContext.getCurrentInstance();
    HttpServletResponse的响应=(HttpServletResponse的)context.getExternalContext()的GetResponse()。    尝试
    {
        response.sendRedirect(MainSearchResult.xhtml);
        //response.redirect(\"http://localhost:8080/SearchEngineServer/faces/MainSearchResult.xhtml);
    }
    赶上(IOException异常E)
    {
        e.printStackTrace();
    }    返回null;

和这也是在支持bean:

  redirectToPage(/ MainSearchResult.xhtml);

调用该方法:

 私人无效redirectToPage(字符串的toURL)
{
    尝试
    {
        FacesContext中CTX = FacesContext.getCurrentInstance();        的ExternalContext extContext = ctx.getExternalContext();
        字符串URL = extContext.en codeActionURL(。ctx.getApplication()getViewHandler()getActionURL(CTX,的toURL));        extContext.redirect(URL);
    }
    赶上(IOException异常E)
    {
        抛出新FacesException(E);
    }
}

所有给出相同java.lang.IllegalStateException误差为上面给出的的servlet例子。对于重定向状态的文档这样的:


  IllegalStateException  - 如果,在Portlet环境中,当前的响应对象是的renderResponse而不是ActionResponse的
IllegalStateException - 如果,在一个servlet环境,当前的响应已经提交



解决方案

BalusC的回答是少量的对象数据的合适的答案,但是,我提交给支持bean对象是2.2兆,不适合在编码该URL。更进一步,我不希望人们收藏到特定的页面,更多的属性可以被添加在未来的搜索条件文件,这将使本书标记属性无效。

我使用的解决方案是什么高科技,但它的工作原理。小程序提交序列化对象到Servlet,这反过来把它传递给后台bean,然后返回一个失败或成功的消息小程序。如果提交成功,则小程序调用网页上的JavaScript函数加载结果页面。这确保了正确的支持bean被保留。

最后code是如下:

小程序提交搜索条件按钮,code:

 私人无效jButton8ActionPerformed(java.awt.event.ActionEvent中EVT)
{
    criteriaModel.load codeBase的();
    INT选择= JOptionPane.showConfirmDialog(这一点,
         你确定要提交您的搜索条件,并退出\\自定义搜索条件\\网页?
         确认提交,
         JOptionPane.YES_NO_OPTION,
         JOptionPane.QUESTION_MESSAGE);     如果(选择== 0)
     {
         尝试
         {
             网址URL =新的URL(criteriaModel.get codeBase的(),CriteriaServlet);             的System.out.println(Servlet的地址是:+网址);            对象searchSubmitObject = criteriaModel.getObjectSlideData();            HttpURLConnection的连接=(HttpURLConnection类)url.openConnection();
            connection.setDoInput(真);
            connection.setDoOutput(真);
            connection.setUseCaches(假);
            connection.setRequestMethod(POST);
            connection.setRequestProperty(内容类型,应用程序/ x-j​​ava的序列化对象);            ObjectOutputStream的出=新的ObjectOutputStream(connection.getOutputStream());
            out.writeObject(searchSubmitObject);
            了out.flush();
            out.close();
            out.close();            的System.out.println(对象书面);            在ObjectInputStream的=新的ObjectInputStream(connection.getInputStream());
            字符串的响应=(字符串)in.readObject();
            的System.out.println(响应);
            附寄();            如果(response.equals(失败))
            {
                JOptionPane.showMessageDialog(jPanel8,提交搜索条件文件失败的服务器\\ n稍后再试。);
            }
            其他
            {
                。getAppletContext()showDocument(新URL(JavaScript的:openResultsPage()));
            }
         }
         赶上(MalformedURLException的前)
        {
            JOptionPane.showMessageDialog(jPanel8,提交文件的标准URL格式不正确。
                    + ex.toString());
            的System.out.println(MalformedURLException的发生);
            。Logger.getLogger(CriteriaInterfaceView.class.getName())日志(Level.SEVERE,空,前);
        }
        赶上(例外五)
         {
             的System.out.println(提交的标准文件错误异常:+ e.toString());
             JOptionPane.showMessageDialog(jPanel8,提交标准文件错误例外:
                    + e.toString());
         }
     }
}

在servlet:

  @覆盖
公共无效服务(ServletRequest中REQ,ServletResponse的RES)抛出了ServletException,IOException异常
{
    的System.out.println(服务(ServletRequest中REQ,ServletResponse的水库));    res.setContentType(text / plain的);    尝试
    {
        在ObjectInputStream的=新的ObjectInputStream(req.getInputStream());
        slideData =(MultipleSlideDataObject2)in.readObject();
        附寄();        字符串的回复=失败;        如果(slideData!= NULL)
        {
            的System.out.println(提交滑轨系列的序列号是:+ slideData.getSerialNumber());            FacesContext中的FacesContext = FacesUtil.getFacesContext(REQ,RES);
            ProductSelection productSelection =(ProductSelection)facesContext.getApplication()evaluateEx pressionGet(FacesContext中,#{} productSelection,ProductSelection.class)。
            productSelection.submitSearchCriteriaFile(slideData);            回复=成功;
        }        ObjectOutputStream的outputToApplet =新的ObjectOutputStream(res.getOutputStream());
        outputToApplet.writeObject(答复);
        outputToApplet.flush();
        outputToApplet.close();
    }
    捕捉(ClassNotFoundException的前)
    {
        。Logger.getLogger(CriteriaServlet.class.getName())日志(Level.SEVERE,空,前);
    }
}

在支撑bean:

 公共字符串submitSearchCriteriaFile(MultipleSlideDataObject2 slideData)抛出IOException异常
{
    的System.out.println(收到滑系列编号:+ slideData.getSerialNumber());    //如果没有幻灯片数据然后...
    如果(slideData == NULL)
    {
        返回process_MainSearchResultFailed
    }
    其他
    {
        rankProducts(slideData);
    }    返回process_MainSearchResult
}

在JSF页面的标题,其中包含小程序:

 &LT; SCRIPT LANGUAGE =JavaScript的&GT;    功能openResultsPage()
    {
        window.location的=MainSearchResult.xhtml;
    }    &LT; / SCRIPT&GT;

根据BalusC的FacesUtil类用于获取servlet的支持bean(几个小的改动请求和响应类型)FacesUtil:

 包searchselection;进口javax.faces.FactoryFinder;
进口javax.faces.component.UIViewRoot;
进口javax.faces.context.FacesContext;
进口javax.faces.context.FacesContextFactory;
进口javax.faces.lifecycle.Lifecycle;
进口javax.faces.lifecycle.LifecycleFactory;
进口javax.servlet.ServletRequest;
进口javax.servlet.ServletResponse;公共类FacesUtil
{
    //吸气剂----------------------------------------------- ------------------------------------    公共静态FacesContext的getFacesContext(
        ServletRequest中的请求,响应的ServletResponse)
    {
        //获取当前的FacesContext。
        FacesContext中的FacesContext = FacesContext.getCurrentInstance();        //检查当前的FacesContext。
        如果(FacesContext的== NULL){            //创建新的生命周期。
            LifecycleFactory lifecycleFactory =(LifecycleFactory)
                FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
            生命周期生命周期= lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);            //创建新的FacesContext。
            的FacesContextFactory contextFactory =(的FacesContextFactory)
                FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
            FacesContext的= contextFactory.getFacesContext(
                request.getServletContext(),请求,响应,生命周期);            //创建新的视图。
            UIViewRoot视图= facesContext.getApplication()。getViewHandler()。CreateView的(
                FacesContext的,);
            facesContext.setViewRoot(视图);            //设置当前的FacesContext。
            FacesContextWrapper.setCurrentInstance(FacesContext的);
        }        返回FacesContext的;
    }    //助手----------------------------------------------- ------------------------------------    //一个内部类的包裹保护FacesContext.setCurrentInstance()。
    私有静态抽象类FacesContextWrapper扩展FacesContext的{
        保护静态无效setCurrentInstance(FacesContext中的FacesContext){
            FacesContext.setCurrentInstance(FacesContext的);
        }
    }}

I am an applications programmer doing my first JSF 2.0 web site and confess that I don't know as much as I should about JSF. I have been pooring over documents for months and, thanks to these forums in particular, have not gotten stuck up to this point. The bulk of the web site is finished and working and the backing bean used here is used elsewhere without problems.

I have a serialised search criteria object that needs to be submitted from an applet to a backing bean, via a servlet. A backing bean method then processes the search criteria data and applies it to a list of products, held in a database, and then displays the list of ranked products in a new JSF page.

All attempts to open a results page with the correct data have failed. The navigation-case "return "process_MainSearchResult";" is not doing anything in the backing bean (see backing bean code down further and faces-config entry). I have tried opening a results page from the applet using appletContext.showDocument (see below) but the new page does not have the backing bean that the search criteria object was passed to and therefore none of the correct data.

Note that setting POST on the setRequestMethod in the applet has no effect; it always uses a service. If setDoInput and setDoOutput are not set to true and a response sent from the servlet back to the applet then the submitted object is not sent and nothing happens. I suspect that this is at the core of my problems but altering it in any way stops the serialised object from being submitted successfully.

As it stands, the object is successfully sent to the backing bean but the new page will not load with the correct data (using the showDocument in the applet rather than the redirect in the servlet). Is there a way of setting the original backing bean on the new web page or am I doing this all wrong?

Web server is Glassfish 3.x, IDE is Netbeans 7.0.1, System is WinXP. Backing bean class is 'ProductSelection'; servlet class is 'CriteriaServlet'.

Applet "Submit Search Criteria" button code:

private void jButton8ActionPerformed(java.awt.event.ActionEvent evt)                                         
{                                             
    criteriaModel.loadCodeBase();
    int choice = JOptionPane.showConfirmDialog(this,
         "Are you sure you want to submit your search criteria and exit the \"Customise Search Criteria\" web page?",
         "Confirm Submit",
         JOptionPane.YES_NO_OPTION,
         JOptionPane.QUESTION_MESSAGE);

     if (choice == 0)
     {
         try 
         {      
             URL url;

             url = new URL(criteriaModel.getCodeBase(), "CriteriaServlet");

             System.out.println("Servlet address is: " + url);

            // Get the search criteria object. 
            Object searchSubmitObject = criteriaModel.getObjectSlideData();

            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");

            ObjectOutputStream out = new ObjectOutputStream(connection.getOutputStream());
            out.writeObject(searchSubmitObject);
            out.flush();
            out.close();
            out.close();

            System.out.println("Object Written");

            // If this and the corresponding servlet response code is removed
            // then the searchSubmitObject fails to be sent.
            ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
            String response = (String)in.readObject();
            System.out.println(response);
            in.close();
         } 
         catch (MalformedURLException ex)
        {
            JOptionPane.showMessageDialog(jPanel8, "Submit criteria file Malformed URL."
                    + ex.toString());
            System.out.println("MalformedURLException occurred");
            Logger.getLogger(CriteriaInterfaceView.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (Exception e) 
         {
             System.out.println("Submit criteria file ERROR exception: " + e.toString());
             JOptionPane.showMessageDialog(jPanel8, "Submit criteria file ERROR exception:"
                    + e.toString());
         }
     }

    // This opens a new page but with a new backing bean with the wrong data.
    try
    {
        appletContext.showDocument(new URL(criteriaModel.getCodeBase()+"MainSearchResult.xhtml"),"_SELF");
    }
    catch (MalformedURLException ex)
    {
        Logger.getLogger(CriteriaInterfaceView.class.getName()).log(Level.SEVERE, null, ex);
    }
}   

I have tried redirecting in the servlet using redirect(url) with no success:

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
    System.out.println("service(ServletRequest req, ServletResponse res)");

    res.setContentType("application/x-java-serialized-object");

    try
    {
        ObjectInputStream in = new ObjectInputStream(req.getInputStream());
        slideData = (MultipleSlideDataObject2)in.readObject();
        in.close();

        if(slideData != null)
        {
            System.out.println("Serial number of submitted slide series is: " + slideData.getSerialNumber());
        }

        String temp = "Criteria file Recieved";
        ObjectOutputStream outputToApplet = new ObjectOutputStream(res.getOutputStream());
        outputToApplet.writeObject(temp);
        outputToApplet.flush();          
        outputToApplet.close();
    }
    catch (ClassNotFoundException ex)
    {
        Logger.getLogger(CriteriaServlet.class.getName()).log(Level.SEVERE, null, ex);
    }

    FacesContext facesContext = FacesUtil.getFacesContext(req, res);
    // Get the backing bean.
    ProductSelection productSelection = (ProductSelection) facesContext.getApplication().evaluateExpressionGet(facesContext, "#{productSelection}", ProductSelection.class);
    productSelection.submitSearchCriteriaFile(slideData);

    // This throws an java.lang.IllegalStateException error.
    try 
    {
        FacesContext context = FacesContext.getCurrentInstance();

        ExternalContext extContext = context.getExternalContext();
        String url = extContext.encodeActionURL(context.getApplication().getViewHandler().getActionURL(context, "/MainSearchResult.xhtml"));

        extContext.redirect(url);
    } 
    catch (IOException e) 
    {
        throw new FacesException(e);
    }

Gives the following error because I suspect the current response has already been committed :

WARNING: StandardWrapperValve[CriteriaServlet]: PWC1406: Servlet.service() for servlet CriteriaServlet threw exception java.lang.IllegalStateException at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:522) at com.sun.faces.context.ExternalContextImpl.redirect(ExternalContextImpl.java:572) at searchselection.CriteriaServlet.service(CriteriaServlet.java:217) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) at java.lang.Thread.run(Thread.java:619)

The return "process_MainSearchResult"; in the backing bean does not work :

public String submitSearchCriteriaFile(MultipleSlideDataObject2 slideData) throws IOException
{
    System.out.println("Recieved slide series with serial number: " + slideData.getSerialNumber());

    // If there is no slide data then...
    if (slideData == null)
    {
        return "process_MainSearchResultFailed";
    }
    else
    {
        rankProducts(slideData);
    }

    rowStart = 0;
    currentStartPage = 0;
    currentPageIndex = 0;
    calculateNumberPages();
    SetupPaginationValues();

    // Ignores this...
    return "process_MainSearchResult";
}

Faces-config.xml entry:

<navigation-rule>
    <navigation-case>
        <from-outcome>process_MainSearchResult</from-outcome>
        <to-view-id>/MainSearchResult.xhtml</to-view-id>
    </navigation-case>
</navigation-rule>

I have also tried this in the backing bean to force a redirect:

FacesContext context = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();

    try
    {
        response.sendRedirect("MainSearchResult.xhtml");
        //response.redirect("http://localhost:8080/SearchEngineServer/faces/MainSearchResult.xhtml");
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

    return null;

and also this in the backing bean:

        redirectToPage("/MainSearchResult.xhtml");

Which calls this method:

private void redirectToPage(String toUrl) 
{
    try 
    {
        FacesContext ctx = FacesContext.getCurrentInstance();

        ExternalContext extContext = ctx.getExternalContext();
        String url = extContext.encodeActionURL(ctx.getApplication().getViewHandler().getActionURL(ctx, toUrl));

        extContext.redirect(url);
    } 
    catch (IOException e) 
    {
        throw new FacesException(e);
    }
}

All give the same java.lang.IllegalStateException error as for the servlet example given above. The documentation for redirect states this:

IllegalStateException - if, in a portlet environment, the current response object is a RenderResponse instead of an ActionResponse 
IllegalStateException - if, in a servlet environment, the current response has already been committed 

解决方案

BalusC's answer is the appropriate answer for small amounts of object data, however, the object I am submitting to the backing bean is 2.2 megabytes and not suitable for encoding in the URL. Further more I don't want people bookmarking this particular page as more attributes may be added to the search criteria file in the future and this would make the book mark properties invalid.

The solution I am using is very low tech but it works. The applet submits the serialised object to the servlet, which in turn passes it to the backing bean, and then returns a fail or succeed message to the applet. If the submission succeeds then the applet calls a javascript function on the web page to load the results page. This ensures that the correct backing bean is retained.

The final code is as follows:

Applet "Submit Search Criteria" button code:

private void jButton8ActionPerformed(java.awt.event.ActionEvent evt)                                         
{                                             
    criteriaModel.loadCodeBase();
    int choice = JOptionPane.showConfirmDialog(this,
         "Are you sure you want to submit your search criteria and exit the \"Customise Search Criteria\" web page?",
         "Confirm Submit",
         JOptionPane.YES_NO_OPTION,
         JOptionPane.QUESTION_MESSAGE);

     if (choice == 0)
     {
         try 
         {      
             URL url = new URL(criteriaModel.getCodeBase(), "CriteriaServlet");

             System.out.println("Servlet address is: " + url);

            Object searchSubmitObject = criteriaModel.getObjectSlideData();

            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");

            ObjectOutputStream out = new ObjectOutputStream(connection.getOutputStream());
            out.writeObject(searchSubmitObject);
            out.flush();
            out.close();
            out.close();

            System.out.println("Object Written");

            ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
            String response = (String)in.readObject();
            System.out.println(response);
            in.close();

            if(response.equals("Failed"))
            {
                JOptionPane.showMessageDialog(jPanel8, "Submit Search criteria file to server failed.\n Try Again later.");
            }
            else
            {
                getAppletContext().showDocument(new URL("javascript:openResultsPage()"));
            }
         } 
         catch (MalformedURLException ex)
        {
            JOptionPane.showMessageDialog(jPanel8, "Submit criteria file Malformed URL."
                    + ex.toString());
            System.out.println("MalformedURLException occurred");
            Logger.getLogger(CriteriaInterfaceView.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (Exception e) 
         {
             System.out.println("Submit criteria file ERROR exception: " + e.toString());
             JOptionPane.showMessageDialog(jPanel8, "Submit criteria file ERROR exception:"
                    + e.toString());
         }
     }         
}      

In the servlet:

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
    System.out.println("service(ServletRequest req, ServletResponse res)");

    res.setContentType("text/plain");

    try
    {
        ObjectInputStream in = new ObjectInputStream(req.getInputStream());
        slideData = (MultipleSlideDataObject2)in.readObject();
        in.close();

        String reply = "Failed";

        if(slideData != null)
        {
            System.out.println("Serial number of submitted slide series is: " + slideData.getSerialNumber());

            FacesContext facesContext = FacesUtil.getFacesContext(req, res);
            ProductSelection productSelection = (ProductSelection) facesContext.getApplication().evaluateExpressionGet(facesContext, "#{productSelection}", ProductSelection.class);
            productSelection.submitSearchCriteriaFile(slideData);

            reply = "Success";
        }

        ObjectOutputStream outputToApplet = new ObjectOutputStream(res.getOutputStream());
        outputToApplet.writeObject(reply);
        outputToApplet.flush();          
        outputToApplet.close();
    }
    catch (ClassNotFoundException ex)
    {
        Logger.getLogger(CriteriaServlet.class.getName()).log(Level.SEVERE, null, ex);
    }
}

In the backing bean:

public String submitSearchCriteriaFile(MultipleSlideDataObject2 slideData) throws IOException
{
    System.out.println("Recieved slide series with serial number: " + slideData.getSerialNumber());

    // If there is no slide data then...
    if (slideData == null)
    {
        return "process_MainSearchResultFailed";
    }
    else
    {
        rankProducts(slideData);
    }

    return "process_MainSearchResult";
}

In the header of the JSF page, which contains the applet:

<SCRIPT language="javascript">

    function openResultsPage()
    {
        window.location = "MainSearchResult.xhtml";
    }

    </SCRIPT>

FacesUtil based on BalusC's FacesUtil class (couple of minor changes to the request and response types) Used to get the backing bean in the servlet:

    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;

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);
        }
    } 

}

这篇关于如何从一个Applet提交序列化对象,通过一个se​​rvlet,到后台bean,然后打开一个结果JSF页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆