我在Lotus Notes 9.0.1中的View Scope变量有问题。
一个用户报告了我的应用程序出现的错误,其中,视域变量在页面加载时可能变为null-该变量是一个数组,自定义控件中标签的计算值试图访问该数组,从而导致运行时异常。该变量应通过库方法加载,该方法由手风琴窗格的计算标题脚本调用,该脚本包含试图读取它的自定义控件。
就我所测试的而言,整个过程每次都有效,但是该应用程序的一个用户报告了运行时异常。进一步调查后,我证实可以通过构建应用程序并单击打开的页面上的某些链接来重现该错误。通过阅读有关此类问题和服务器日志的信息,我了解到这可能是由于作用域变量的丢失(可能由会话超时触发)引起的,但是我们的应用程序应该能够使用XPages Extension Library中的keepsessionalive控件处理会话超时-但它似乎没有按预期工作。
我希望获得有关该问题其他可能原因/触发的输入(到目前为止,我一直无法重现该问题,因为该问题已由用户报告),另外还有一些方法可以使会话长时间保持活动状态而不会丢失范围变量。
代码如下:
手风琴标题(加载变量的地方,其他标题相似):
viewScope.contadorParecer=carregaContadoresParecer(); //Where the variable should be loaded
if(viewScope.contadorParecer.total>0)
return "Pareceres ("+viewScope.contadorParecer.total+")";
else
return "Pareceres"
Script library method (similar code for the others):
function carregaContadoresProposta() {
try {
contadoresProposta = {};
try {
if (arguments[0])
var totalizar = arguments[0];
else
var totalizar = compositeData.totalizarUnidade;
} catch (e) {
var totalizar = false;
}
if (!totalizar) {
var strView = "vw_proposta_contador";
var filtro = sessionScope.usuarioLogado.nome;
} else {
var strView = "vw_proposta_unidade_contador";
var filtro = sessionScope.usuarioLogado.fk_entidade_funcional;
}
//cria navegador
var nav: NotesViewNavigator = database.getView(strView).createViewNavFromCategory(filtro);
var entry: NotesViewEntry = nav.getFirst();
var total = 0;
while (entry != null) {
var categoria = entry.getColumnValues()[1];
categoria = @UpperCase(categoria);
contadoresProposta[categoria] = entry.getColumnValues()[entry.getColumnValues().size() - 1];
if (!categoria.isEmpty())
total += contadoresProposta[categoria];
var tmpentry: NotesViewEntry = nav.getNextCategory();
entry.recycle();
entry = tmpentry;
}
contadoresProposta["total"] = total;
return contadoresProposta.clone();
} catch (e) {
printError(e, "carregaContadoresProposta", "Script Library ContextualProposta");
}
}
自定义控件(contadorAcompanhamento,contadorProposta和contadorParecer在读取之前为空):
var label=item.split("|")[0];
label=label.indexOf("{")!=-1?label.split("{")[0]:label;
var parecer=compositeData.parecer[0];
var acompanhamento=compositeData.acompanhamento;
if(!parecer){
if(acompanhamento){
var total=viewScope.contadorAcompanhamento[@UpperCase(label)];
}else{
var total=viewScope.contadorProposta[@UpperCase(label)];
}
}else{
var total=viewScope.contadorParecer[@UpperCase(label)];
}
if(total!=undefined)
return label+" ("+ total +")"
else
return label;
运行时错误:
Error while executing JavaScript computed expression
Script interpreter error, line=11, col=37: 'viewScope.contadorProposta' is null and cannot be accessed as an array
在用户服务器日志上发现的第一个错误:(可能是由脚本库中设置的tmpEntry引起的) 调用方法NotesViewNavigator.getNextCategory()发生异常
答案 0 :(得分:0)
正如Paul所解释的:您可能需要进行长期调查。但是,您面临的真正问题是使用范围变量的不幸方法。会话和应用程序范围受超时和到期的限制,因此切勿将其视为理所当然并检查它们的存在。因此,您无需在不相关的位置播种值,而是在脚本函数中检查它们的存在。
大致内容(在SSJS脚本库中):
var carregaContadoresParecer = {
storage : null,
total : function() {
if (storage === null) {
storage = populateStorage();
}
return storage.total;
},
contadorParecer : function(whatSearch) {
if (storage === null) {
storage = populateStorage();
}
// your code here
}
}
沿着这些线。然后,您可以使用carregaContadoresParecer.total()
和carregaContadoresParecer.contadorParecer('someLabel');
因此,您不会将函数存储在范围中,而是存储在JavaLib中,而仅将值存储在范围中并检查该值是否存在。我将使用托管bean,但这是因为我对Java熟悉-可能不是您的事。
答案 1 :(得分:0)
如果用户为应用程序中的不同页面打开了很多选项卡,则可以填充服务器端页面地图(视图,因此viewScope
),并删除先前使用的页面。这在“持久性”选项卡上的“ Xsp属性”中进行处理。周围有各种会议幻灯片,《 Mastering XPages》和《 XPages Portable Command Guide》一书中也有介绍。
这可能是原因,但需要用户进一步的信息来确认或驳斥。
答案 2 :(得分:0)
viewScope变量“ contadorProposta”的初始化位置在哪里?您确定它已初始化吗?当用户重新加载页面时,viewScope丢失-有可能吗?