我将首先说:
我还要补充说,如果我只准备一个执行以下操作的简单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>
想法?
答案 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之外的实施,因此涉及更多会话类型。)