1

私は最初のJSF2.0Webサイトを作成しているアプリケーションプログラマーであり、JSFについて私がすべきことをあまり知らないことを告白します。私は何ヶ月もドキュメントに苦しんでおり、特にこれらのフォーラムのおかげで、この時点まで立ち往生していません。Webサイトの大部分は完成して機能しており、ここで使用されているバッキングBeanは他の場所でも問題なく使用されています。

サーブレットを介してアプレットからバッキングBeanに送信する必要があるシリアル化された検索条件オブジェクトがあります。次に、バッキングBeanメソッドは、検索基準データを処理して、データベースに保持されている製品のリストに適用し、ランク付けされた製品のリストを新しいJSFページに表示します。

正しいデータで結果ページを開く試みはすべて失敗しました。ナビゲーションケース「return"process_MainSearchResult";」バッキングBeanで何も実行していません(バッキングBeanコードの詳細とfaces-configエントリを参照してください)。appletContext.showDocument(以下を参照)を使用してアプレットから結果ページを開こうとしましたが、新しいページには検索条件オブジェクトが渡されたバッキングBeanがないため、正しいデータがありません。

アプレットのsetRequestMethodにPOSTを設定しても効果がないことに注意してください。常にサービスを使用します。setDoInputとsetDoOutputがtrueに設定されておらず、サーブレットからアプレットに応答が返される場合、送信されたオブジェクトは送信されず、何も起こりません。これが私の問題の核心にあると思いますが、何らかの方法で変更すると、シリアル化されたオブジェクトが正常に送信されなくなります。

現状では、オブジェクトはバッキングBeanに正常に送信されますが、新しいページには正しいデータがロードされません(サーブレットのリダイレクトではなく、アプレットのshowDocumentを使用)。新しいWebページに元のバッキングBeanを設定する方法はありますか、それともこれをすべて間違って行っていますか?

WebサーバーはGlassfish3.x、IDEはNetbeans 7.0.1、システムはWinXPです。バッキングBeanクラスは「ProductSelection」です。サーブレットクラスは「CriteriaServlet」です。

アプレットの「検索基準の送信」ボタンコード:

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

redirect(url)を使用してサーブレットでリダイレクトしようとしましたが、成功しませんでした。

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

現在の応答がすでにコミットされていると思われるため、次のエラーが発生します。

警告:StandardWrapperValve [CriteriaServlet]:PWC1406:サーブレットCriteriaServletのServlet.service()は、com.sun.facesのorg.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:522)で例外java.lang.IllegalStateExceptionをスローしました。 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 )com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)atcom.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)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 )com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)atcom.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)atcom.sun。 grizzly.ContextTask.run(ContextTask.java:69)at com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:330)at com.sun.grizzly.util.AbstractThreadPool $ WorkerThreadPool java:309)at java.lang.Thread.run(Thread.java:619)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)atcom.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)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)atcom.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)76)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)com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:330)at com.sun.grizzly.util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:309)atjava.lang。 Thread.run(Thread.java:619)76)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)com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:330)at com.sun.grizzly.util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:309)atjava.lang。 Thread.run(Thread.java:619)run(AbstractThreadPool.java:309)at java.lang.Thread.run(Thread.java:619)run(AbstractThreadPool.java:309)at java.lang.Thread.run(Thread.java:619)

戻り値"process_MainSearchResult"; バッキング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);
    }

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

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

Faces-config.xmlエントリ:

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

また、バッキングBeanでこれを試し、リダイレクトを強制しました。

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;

また、これはバッキングBeanに含まれています。

        redirectToPage("/MainSearchResult.xhtml");

このメソッドを呼び出すもの:

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

上記のサーブレットの例と同じjava.lang.IllegalStateExceptionエラーが発生します。リダイレクトのドキュメントには、次のように記載されています。

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 
4

2 に答える 2

2

サーブレットでリダイレクトを実行する前に、すでに応答を書き込んでコミットしているため、リダイレクトは失敗しました。1 回のリクエストで複数のレスポンスを送信できると考えているようです。これは実際には正しくありません。HTTP 要求ごとに 1 つの HTTP 応答のみを返すことができます。行から始まるブロック全体を削除しFacesUtil#getFacesContext()ます。それはそこに属していません。

そのサーブレットが何をしているのかわかりませんが、役に立たないようですが、代わりにAppletContext#showDocument()、サーブレットを呼び出した後、アプレット自体に「リダイレクト」を実行させる必要があります。検索条件 (シリアライズしようとしている Java オブジェクト インスタンスのプロパティ) を通常の方法で GET 要求パラメーターとして JSF ページ/Bean に渡し、JSF に or で収集させ、@ManagedPropertyor<f:viewParam>で処理させることが@PostConstructでき<f:event>ます。

例えば

String query = "?param1=" + URLEncoder.encode(param1, "UTF-8")
             + "&param2=" + URLEncoder.encode(param2, "UTF-8")
             + "&param3=" + URLEncoder.encode(param3, "UTF-8");

getAppletContext().showDocument(new URL(getCodeBase(), "MainSearchResult.xhtml" + query), "_SELF");

どちらでも

@ManagedBean
@RequestScoped
public class ProductSelection {

    @ManagedProperty("#{param.param1}")
    private String param1;

    @ManagedProperty("#{param.param2}")
    private String param2;

    @ManagedProperty("#{param.param3}")
    private String param3;

    @PostConstruct
    public void init() {
        // Do your business job based on the submitted request parameters.
    }

    // ...
}

また

<f:metadata>
    <f:viewParam name="param1" value="#{productSelection.param1}" />
    <f:viewParam name="param2" value="#{productSelection.param2}" />
    <f:viewParam name="param3" value="#{productSelection.param3}" />
    <f:event type="preRenderView" listener="#{productSelection.init}" />
</f:metadata>

このように実装する場合、Java シリアライゼーションを伴う不器用なサーブレットの手順はまったく不要だと思います。あなたはそれを取り除くことができます。また、このようにして、アプレット/サーブレットから独立して開くことができる、ブックマーク可能で再利用可能で検索ボットのインデックス付けが可能なページができあがります。

以下も参照してください。

于 2012-09-04T10:48:33.763 に答える
0

BalusC の回答は少量のオブジェクト データには適切な回答ですが、バッキング Bean に送信するオブジェクトは 2.2 メガバイトであり、URL でのエンコードには適していません。さらに、この特定のページをブックマークしたくない人もいます。将来、検索条件ファイルにさらに属性が追加される可能性があり、ブックマークのプロパティが無効になる可能性があるからです。

私が使用しているソリューションは非常にローテクですが、機能します。アプレットはシリアル化されたオブジェクトをサーブレットに送信します。サーブレットはそれをバッキング Bean に渡し、失敗または成功のメッセージをアプレットに返します。送信が成功すると、アプレットは Web ページで JavaScript 関数を呼び出して、結果ページをロードします。これにより、正しいバッキング Bean が保持されます。

最終的なコードは次のとおりです。

アプレットの「検索条件を送信」ボタンのコード:

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

サーブレットで:

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

バッキング 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";
}

アプレットを含むJSFページのヘッダー:

<SCRIPT language="javascript">

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

    </SCRIPT>

BalusC の FacesUtil クラスに基づく FacesUtil (リクエストとレスポンスのタイプに若干の変更が加えられています) サーブレットでバッキング Bean を取得するために使用されます。

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

}
于 2012-09-04T16:31:26.103 に答える