InlineFrameがILinkListenerを実装している件

はじめに

 org.apache.wicket.markup.html.link.InlineFrameがorg.apache.wicket.markup.html.link.ILinkListenerを実装していることに気づきました。InlineFrameクラスはIFRAMEに対応するクラスです。
 で、ILinkListenerはonLinkClicked()というクリックに応答するメソッドを持っています。

 不思議に思いませんか。「なぜIFRAMEにクリックに応答するメソッドが必要なのか」と。
 私は思いました。これはそんなメモ。

環境


オチを言いますと

 IFRAMEを含むページを表示した際に、「クリックされたとみなして、ページを読み込む」という仕組みになっていることが解析の結果わかりました。
 生成されたHTMLを見てみます。下記はIFRAMEを含むページのレンダリング例です。

<html>
    <head>
        <title>Wicket Quickstart Archetype Homepage</title>
    </head>
    <body>
        <iframe src=";jsessionid=79F45E054A51CA810886D135F7690789?wicket:interface=:0:iframe::ILinkListener::" wicket:id="iframe"></iframe>
    </body>
</html>


 src属性内の正確な書式は知らないのですが、「iframeコンポーネントのILinkListenerに要求を投げる」と言うことをこのsrc属性は指示しています。
 Wicketは、org.apache.wicket.request.AbstractRequestCycleProcessorクラスのresolveRenderedPageメソッドでこのURLをJavaの世界にマッピングします。

 今回はrequestParameters.getInterfaceName()(呼び出しタイミングは下記ソースを参照)を実行した際に、「ILinkListener」という文字列が取得できます。
 その結果生成されるIRequestTargetインターフェースのインスタンスが、イベント(今回はonLinkClicked)の処理の仕方を知っているインスタンスとなります。
 このインスタンスを後工程で使用し、イベントに応答する仕組みになっています。

 resolveRenderedPageメソッドが、どのようなメソッドなのか引用します。

protected IRequestTarget resolveRenderedPage(final RequestCycle requestCycle,
    final RequestParameters requestParameters)
{
    final String componentPath = requestParameters.getComponentPath();
    final Session session = requestCycle.getSession();
    final Page page = session.getPage(requestParameters.getPageMapName(), componentPath,
        requestParameters.getVersionNumber());

    // Does page exist?
    if (page != null)
    {
        // Set page on request
        requestCycle.getRequest().setPage(page);

        // see whether this resolves to a component call or just the page
        final String interfaceName = requestParameters.getInterfaceName();
        if (interfaceName != null)
        {
            return resolveListenerInterfaceTarget(requestCycle, page, componentPath,
                interfaceName, requestParameters);
        }
        else
        {
            return new PageRequestTarget(page);
        }
    }
    // just return null here and let it be handled further down the road.
    return null;
}


なんか不思議

 仕組みは分かったのですが、少し不思議なクラス設計です。ILinkListener以外に適当なのが無かったのでしょうか。
 ちなみに、「イベント発生時にサーバがレスポンスを返す」といういう挙動をするコントロールで、org.apache.wicket.markup.html.link.ResourceLinkと言うのが存在します。
 こちらは、ILinkListener.onLinkClickedではなく、IResourceListener.onResourceRequestedで応答します。