java - Wicket 口 6 : empty PageParameters when recreating a page after expiration

标签 java wicket

我们在使用 Wicket 6(即版本 6.22.0)时遇到了问题。看起来这就是这里修复的内容:https://issues.apache.org/jira/browse/WICKET-5068 简而言之:页面过期后,Wicket 尝试通过调用以页面类和 PageParameters 作为参数的构造函数来重建它,但 PageParameters (错误地)为空,即使一些参数随请求一起发送。

After Wicket session timeout - pageParameters are null似乎与同一个问题有关。

WICKET-5068 已修复 Wicket 7,但我们有 Wicket 6,我们需要对其进行修复。

以下是对我们的发现和一些问题的详细解释。

发生的情况是这样的:

  1. 用户打开一个页面(有状态)并使其在浏览器选项卡中保持打开状态。
  2. 用户打开其他页面
  3. 尽管 session 仍在运行,但第 1 步中的原始页面已从页面存储中逐出(即过期)。
  4. 用户返回到初始浏览器选项卡并单击链接。这是链接的代码:

    AjaxLink<Void> link = new AjaxLink<Void>("link") {
        @Override
        public void onClick(AjaxRequestTarget target) {
            showWindow(dataModel, window, target);
        }
    };
    add(link);
    
  5. BookmarkableMapper 根据请求构建 IRequestHandler 时,会调用以下方法 (AbstractBookmarkableMapper:294):

    protected PageParameters getPageParametersForListener(PageInfo pageInfo, PageParameters pageParameters)
    {
        if (pageInfo.getPageId() != null)
        {
            // WICKET-4594 - ignore the parsed parameters for stateful pages
            return null;
        }
        return pageParameters;
    }
    

    因此,根据请求构建的 ListenerInterfaceRequestHandlerPageParametersnull

  6. Wicket 开始处理点击。它尝试恢复被单击的链接所属的页面,这是通过以下方法完成的(PageProvider,从第 252 行开始):

    private void resolvePageInstance(Integer pageId, Class<? extends IRequestablePage> pageClass,
        PageParameters pageParameters, Integer renderCount)
    {
        IRequestablePage page = null;
    
        boolean freshCreated = false;
    
        if (pageId != null)
        {
            page = getStoredPage(pageId);
        }
    
        if (page == null)
        {
            if (pageClass != null)
            {
                page = getPageSource().newPageInstance(pageClass, pageParameters);
                freshCreated = true;
            }
        }
    
        if (page != null && !freshCreated)
        {
            if (renderCount != null && page.getRenderCount() != renderCount)
            {
                throw new StalePageException(page);
            }
        }
    
        pageInstanceIsFresh = freshCreated;
        pageInstance = page;
    }
    

    当页面从页面存储中逐出时,以下语句的条件成立:

    if (page == null)
    

    因此它尝试从类和页面参数创建页面实例:

    page = getPageSource().newPageInstance(pageClass, pageParameters);
    

    但是 pageParameters 在这里是 null(因为第 5 项中的 getPageParametersForListener())。因此页面构造函数得到空的 PageParameters 并失败,因为它需要一些 id。

以下是从页面构造函数中的 PageParameters 中提取 id 的代码:

pageParameters.get("id").toLong()

这是生成的异常(仅显示顶行,因为其余行不相关):

org.apache.wicket.util.string.StringValueConversionException: Unable to convert 'null' to a long value
    at org.apache.wicket.util.string.StringValue.toLong(StringValue.java:664)

因此,在我们的例子中,getPageParametersForListener() 方法破坏了恢复过期页面处理的可能性。

为了解决这个问题,我们用自定义实现替换了 BookmarkableMapper:

public class BookmarkableMapperThatSavesPageParametersForListener extends BookmarkableMapper {
    @Override
    protected PageParameters getPageParametersForListener(PageInfo pageInfo, PageParameters pageParameters) {
        return pageParameters;
    }
}

我们在WebApplication#init()方法中挂载:

mount(new BookmarkableMapperThatSavesPageParametersForListener());

它似乎解决了我们面临的问题:链接点击不会触发处理程序(onClick() 方法),但至少页面不会爆炸,只是自行刷新。

问题是:

  1. 发生这种情况是因为我们做错了什么还是 Wicket 中的错误?
  2. 我们应用的修复是否合格?我猜想 https://issues.apache.org/jira/browse/WICKET-4594 引入的变化不只是为了好玩
  3. 知道我们只有有状态页面,我们的修复是否会破坏任何内容?

最佳答案

这是 Wicket 6.x 的限制,已在 7.x 中实现。 6.x 没有进行此更改,因为我们不确定它是否不会默默地破坏某人的应用程序。 IIRC 如果升级期间需要,可以重写 7.x 中的方法以恢复到旧的行为。 AFAIK 没有人提示 7.x 中的这一变化,所以我想将其向后移植到 6.x (6.27.0) 是可以的,但是 Wicket 的活跃开发人员不再使用 6.x,而且有人这样做的机会是相当低。 建议您升级到7.x。它很稳定,有许多新功能和错误修复。 在那之前,我猜您的选择是使用此请求映射器的自定义版本。

关于java - Wicket 口 6 : empty PageParameters when recreating a page after expiration,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42751254/

相关文章:

JQuery Mobile 加载 Wicket BookmarkablePageLink 时出错

java - 在dropwizard中授权

java - 比较java中的2个非常大的arraylists

java - 使用 hibernate 将 null 保存为 id

java - 迁移到 Struts 2.5.16 导致 log4 问题

java - 面板使用与父页面相同的模型

html - 是否可以更改 Wicket 口输出?

Java GUI : JLabel as Bullet should fly through Jpanel, 仅给出 "result"

java - 在模棱两可的情况下应该使用哪个 Java 泛型?

java - 如果 Wicket 表单组件设置为 "required"是否可以动态更改?