使用frostillic.us控制器类

时间:2015-08-28 11:04:12

标签: java jsf xpages

我将首先说:

  • 我使用ODA(godmode,khan,marcel)。
  • 我是唯一的代码签名者。
  • sessionAsSigner在我第一次加载调用它的XPage时工作。
  • sessionAsSigner在我重新加载页面(cmd + R)后变为null,但在我在viewScope生命周期的上下文中的任何操作中随后引用它时都没有。
  • 我正在实施@Gidgerby 's concept of controller classes

我还要补充说,如果我只准备一个执行以下操作的简单XPage,那么 sessionAsSigner的工作原理是一致的

<p>
    <xp:text value="session: #{session.effectiveUserName}" />
</p>

<p>
    <xp:text value="sessionAsSigner: #{sessionAsSigner.effectiveUserName}" />
</p>

现在,我没有使用SSJS。根据我目前的知识,我尽可能地使用JSF / EL。因此,我访问Domino后端的方式对于Domino XPages程序员来说是非常规的。

我无法让getSessionAsSigner始终如一地工作,当我尝试做上述事情时......

这是我的XPage控制器(支持bean):

 public class TestPageController extends StandardXPageController {

 private static final long serialVersionUID = 1L;

 private AnswerDTO answer;

 public TestPageController() {
    loadQuotation();
 }

 private void loadQuotation() {
     AnswerDAO answerDAO = Factory.createAnswerDAO();

     try {
        answer = answerDAO.read("doc_id");

     } catch (Exception e) {
        e.printStackTrace();
     }
 }

 public AnswerDTO getAnswer() {
     return answer;
 }
}

AnswerDTO是一个POJO。我正在使用DAO / DTO设计模式。 AnswerDAO实现 - 使用简化代码(换行方法只是字段的映射) - 如下所示:

public class AnswerDAODominoImpl implements AnswerDAO {

 private transient Session s;
 private transient Database db;

 private Session getSession() {
    if (s == null) {
        s = XSPUtil.getCurrentSessionAsSigner();
    }

    return s;
 }

 private Database getDatabase() throws NotesException {
    if (db == null) {
        db = getSession().getDatabase("server_name", "server_path");
    }

    return db;
 }

 public AnswerDTO read(String id) throws Exception {
    Database db = getDatabase();

    return wrap(db.getDocumentByID(id));
 }
}

这是ViewHandler类:

public class ViewHandler extends ViewHandlerExImpl {

public ViewHandler(final javax.faces.application.ViewHandler delegate) {
    super(delegate);
}

@SuppressWarnings("unchecked")
public UIViewRoot createView(final FacesContext context, final String pageName) {
    try {
        // pageName is the XPage name prefixing the slash (e.g. "/home")
        String pageClassName = pageName.substring(1);
        Class<? extends XPageController> controllerClass = null;

        try {
            controllerClass = (Class<? extends XPageController>) context.getContextClassLoader().loadClass(
                    "com.sea.xsp.controller." + StringUtil.getProperCaseString(pageClassName) + "PageController");
        } catch (ClassNotFoundException cnfe) {
            controllerClass = StandardXPageController.class;
        }

        XPageController controller = controllerClass.newInstance();
        Map<String, Object> requestScope = (Map<String, Object>) context.getApplication().getVariableResolver().resolveVariable(context, "requestScope");
        requestScope.put("controller", controller);
        UIViewRootEx root = (UIViewRootEx) super.createView(context, pageName);
        root.getViewMap().put("controller", controller);
        requestScope.remove("controller");

        //          MethodBinding beforePageLoad = context.getApplication().createMethodBinding("#{controller.beforePageLoad}", new Class[] { PhaseEvent.class });
        //          root.setBeforePageLoad(beforePageLoad);

        return root;
    } catch (Exception e) {
        e.printStackTrace();
    }

    return super.createView(context, pageName);
}
}

基本上,viewhandler所做的是检查java类的存在,前缀是XPage名称本身。

例如。 测试 .xsp = something.something.package。测试 PageController

这种方法让我忘记在faces-config.xml中将特定的XPage相关类声明为通用托管bean 所有XPage都可以轻松处理相应的支持bean,它始终命名为#{controller}

现在,如果我只是在XPage中编写以下内容,那么一切都将在第一次工作,但不是第二次(getSession()没问题,getSessionAsSigner为null),永远不会再次。我需要对数据库进行一次新的更改(在对java代码进行任何更改之后进行设计更新并且 xsp.application.forcefullrefresh = true )并且它将再次起作用,但是,这是第一次页面已加载。

<p>
    <xp:text value="answer doc id: #{controller.answer.id}" />
</p>

想法?

2 个答案:

答案 0 :(得分:6)

这可能是由于我们之前在XPage运行时发现的一个错误,不知何故与ClassLoader#loadClass有关。事实证明,使用它(和我以前一样)会导致sessionAsSigner在第一页加载后停止工作。修复方法是切换为Class.forName(String, true, ClassLoader)https://github.com/jesse-gallagher/XPages-Scaffolding/commit/d65320fd6d98ff2fbaa814a95eb38ce7bad5a81d

答案 1 :(得分:0)

如果在Java调试器中运行会发生什么?是第二次进入XSPUtil.getSessionAsSigner()吗?

如果启用了godmode,我倾向于使用ExtLibUtil.resolveVariable()来获取sessionAsSigner的句柄。或者,有org.openntf.domino.utils.Factory.getSessionAsSigner()。这些会产生不同的结果吗?

(在RC3中仍然可用,但已被标记为已弃用,以支持Factory.getSession(SessionType.SIGNER),因为我们支持XPage之外的实施,因此涉及更多会话类型。)