HttpSession setAttribute并不总是插入新对象

时间:2015-09-29 08:14:53

标签: java weblogic12c httpsession

我正在从WLS10g和JavaEE6升级到WLS12c和JavaEE7。

我注意到HttpSession.setAttribute的工作原理有所不同。在WLS10中,任何已存储在某个键下的对象都将被替换。

在WLS12中,如果newObject.equals(oldObject),则不会替换该对象。

这对我们来说是个问题,因为应用程序有这样的对象:

class ValueObject {
    int key;
    String data;

    @Override
    public int hashCode()
    {
      return key;
    }

    boolean equals(Object o) {
        if (o == null || (o instanceof ValueObject) == false) {
            return false;
        }
        ValueObject otherObject = (ValueObject)o;
        /* Return true if the keys are equal, even though the data may differ */
        return key == otherObject.key;
    }
}

ValueObject通过跨多个网页的工作流程进行修改。中间值存储在HTTPSession中,在工作流结束时,修改后的值将写入数据库。

在servlet中有这样的代码(成员实际上是通过getter / setter修改的,但我正在简化以减少问题中的代码量):

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
    HttpSession session = request.getSession();
    ValueObject newValue = new ValueObject();
    newValue.key = Integer.parseInt(request.getParameter("key"));
    newValue.data = request.getParameter("data");
    session.setAttribute("value", newValue);
    ...

newValue.key未经修改,newValue.data有新值。

WLS12中HttpSession的修改行为打破了这种模式 - 当从会话中检索到对象时,我们从第一步开始获取data,因为当我们没有替换对象时尝试存储更新版本。

我们可以通过更改所有更新来解决此问题:

session.setAttribute("value", newValue);

session.removeAttribute("value");
session.setAttribute("value", newValue);

但是,有超过100个servlet因此需要做很多工作。而且解决方法既丑陋又容易出错,因为程序员在编写代码时需要跟踪另外一件事。

有没有办法配置WLS12c来使用对象总是被HttpSession.setAttribute()替换的旧行为?

更新2015-09-30

向Oracle提交的错误报告。我尝试过wero建议的过滤器构思。似乎Weblogic希望过滤器链中的对象属于类weblogic.server.internal.ServletRequestImpl,因为当我将其包装并将包装器发送到过滤器链时,我从内部Weblogic类获得了ClassCastException。

我还检查了Gimby建议的配置选项。我找不到会议的任何适用选项。我们部署到单个服务器并使用memory作为会话持久性设置。

更新2016-02-03

Oracle已将错误报告关闭为"不是错误"。

2 个答案:

答案 0 :(得分:3)

由于Oracle将错误报告关闭为“不是错误”,我决定实施解决方法。

我经历了对HttpSession.setAttribute的所有调用,并确定哪些调用使用了可能触发错误的对象。

在那些地方,我取代了

session.setAttribute(key, newValue);

session.removeAttribute(key);
session.setAttribute(key, newValue);

以及解释为何需要额外行的评论。

答案 1 :(得分:2)

关于解决方法的问题不是答案,但Session.setAttribute的Javadoc对此行为非常明确:

  

使用指定的名称将对象绑定到此会话。如果   同名的对象已绑定到会话,对象是   的替换

所以你总是可以提交bug报告。

变通方法可以使用过滤器来安装包装的HttpServletRequest,它返回一个包裹的HttpSession,它会覆盖setAttribute并实现replace-then-set-logic。