Попытка запустить SSJS из Javascript с помощью executeOnServer на XPage - PullRequest
0 голосов
/ 23 мая 2018

У меня довольно длинная форма XPage с вкладками для заполнения посетителями, и я хочу автоматически сохранять ее в бэкэнде каждые несколько минут.

Вся форма представляет собой управляемый компонент, и яЯ могу заполнить / сохранить документ Domino из значений bean-компонентов, используя кнопку вручную, просто позвонив ...

portfolio.save(sessionScope.unid,false)

Я нашел этот превосходный пост Джереми Ходжа (прекрасно, что старые советы выдержали испытание временем!) который объясняет технику ...

http://xpages.info/XPagesHome.nsf/Entry.xsp?documentId=88065536729EA065852578CB0066ADEC

Затем я нашел ответ на форуме от Пола Кэлхуна, в котором описывается использование этой техники с таймером для запуска регулярных сохранений документов ...

https://www -10.lotus.com / ldd / xpagesforum.nsf / xpTopicThread.xsp? DocumentId = B5ECAEC50241A3EE85257B32008248FC

Я реализовал эту технику в моем XPageНо SSJS просто не стреляет.Я даже разместил события onStart и onComplete, чтобы проверить, что все работает как положено.Счетчик работает, консоль показывает таймер, и предупреждения появляются каждые 5 секунд или около того ... но SSJS просто не запускается.

Мой eventHandler, который выполняет работу ...

<xp:eventHandler event="onfubar" id="autoSave" submit="false">
    <xp:this.action><![CDATA[#{javascript:portfolio.save(sessionScope.unid,false);}]]>
    </xp:this.action>
</xp:eventHandler>

... и обработчик событий, который запускает обычное сохранение (да, я знаю, что я вырезал команду 'executeOnServer' и вручную добавил дополнительные параметры - просто пытаясь изолировать проблему) ...

    <xp:eventHandler event="onClientLoad" submit="false">
        <xp:this.script><![CDATA[
var executeOnServer = function () {
    // must supply event handler id or we're outta here....
    if (!arguments[0])
        return false;

    // the ID of the event handler we want to execute
    var functionName = arguments[0];

    // OPTIONAL - The Client Side ID that you want to partial refresh after executing the event handler
    var refreshId = (arguments[1]) ? arguments[1] : "@none";
    var form = (arguments[1]) ? XSP.findForm(arguments[1]) : dojo.query('form')[0];

    // OPTIONAL - Options object contianing onStart, onComplete and onError functions for the call to the 
    // handler and subsequent partial refresh
    var options = (arguments[2]) ? arguments[2] : {};

    // Set the ID in $$xspsubmitid of the event handler to execute
    dojo.query('[name="$$xspsubmitid"]')[0].value = form.id + ':' + functionName;
    XSP._partialRefresh("post", form, refreshId, options);
}

var x = 0;
var form = document.forms[0];

t = new dojox.timing.Timer(3600);
t.onTick = function() {
    x+=1;
    console.info(x);
    if(x > 4){
        x = 0;
        console.info("reset");
        executeOnServer('autoSave','@none',{
            onStart: function() { alert('starting!'); },
            onComplete: function() { alert('complete!'); },
            onError: function() { alert('DANGER WILL ROBINSON!'); }
        });
    }
}

t.onStart = function() {
 console.info("Starting timer");
}

t.start();]]></xp:this.script>
    </xp:eventHandler>

Я знаю, что, должно быть, что-то упустил, и я, вероятно, смотрю прямо на это, но я просто не могу понять, где я ошибся.

Большое спасибодля любого понимания вопроса (и точки в правильном направлении!).

Ответы [ 3 ]

0 голосов
/ 24 мая 2018

Убедитесь, что вы указали правильный идентификатор.Вот простой рабочий пример (без функции executeOnServer и вашей логики таймера).Код запускается после завершения загрузки страницы:

<xp:scriptBlock id="scriptBlockAutoSave">
    <xp:this.value><![CDATA[
        XSP.addOnLoad(function(){
            executeOnServer('#{javascript:getComponent('autoSave').getClientId(facesContext)}');
        });
    ]]></xp:this.value>
</xp:scriptBlock>
0 голосов
/ 24 мая 2018

Это на самом деле может быть намного проще, чем найденные вами фрагменты (вы можете отбросить все это) ... Рассмотрим следующий компонент:

public class PortfolioBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private Map<String, Object> data = new HashMap<String, Object>();

    public Map<String, Object> getData() {
        return data;
    }

    public void autoSave(String unid, Boolean something) {
        System.out.println("The unid is " + unid + " and something is " + something);

        data.put("stamp", "autosave at " + new Date());
    }

}

И следующий источник xsp:

<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

    <xp:div id="myForm" style="padding: 20px;">
        <xp:eventHandler event="onautosave" id="eventAutoSave"
            submit="false" action="#{javascript:portfolio.autoSave(sessionScope.unid, false)}" />

        <p>Stamp</p>

        <xp:inputText id="inputStamp" value="#{portfolio.data.stamp}" size="60" />
    </xp:div>

    <xp:scriptBlock value="
        XSP.addOnLoad(function() {
            window.setInterval(function() {
                XSP.partialRefreshPost('#{id:inputStamp}', {
                    execId: '#{id:myForm}',
                    params: { '$$xspsubmitid' : '#{id:eventAutoSave}' },
                    onComplete: function() { console.log('complete at ' + new Date()); }
                });
            }, 5000);
        });" />

</xp:view>

Я создал контейнер myForm для создания «якоря» и сужения части страницы, которая оценивается, читается, отправляется или выполняется (наилучшая практика с учетом лучших показателей).myForm, следовательно, идентификатор исполнения. Принципиально, что идентификатор выполнения принадлежит элементу, который содержит обработчик события, который вы хотите запустить .Если, например, я поместил событие onautosave за пределами myForm div, событие не будет запущено.Если вам наплевать (плохо!), Вы можете удалить свойство execId: '#{id:myForm}', переданное объекту в вызове метода XSP.partialRefreshPost, и на этом этапе оно будет работать независимо от расположения компонентов xsp.

Кроме того, с помощью XSP.partialRefreshPost вы можете решить, хотите ли вы частично обновить какой-либо элемент страницы или нет.Я поставил #{id:inputStamp}, чтобы вы могли видеть, как поле ввода заполняется текстом, полученным в результате автоматического сохранения.Если вы знаете, что вам не нужно отображать какие-либо изменения DOM, которые могут возникнуть в результате оценки метода на стороне сервера, вы можете указать пустую строку (например, XSP.partialRefreshPost('',), что будет означать norefresh на стороне клиента.Но вы все равно можете что-то сделать по завершении операции, используя свойство onComplete, как вы можете видеть из примера.

В свойстве params идет дополнительный объект со свойством, которое определяет идентификатордействия, которое вы хотите запустить: { '$$xspsubmitid' : '#{id:eventAutoSave}' }.

В заключение, каждые 5 секунд приведенный выше код будет:

  1. печатать на консоли Domino некоторый текст, чтобы показать вамчтобы событие было оценено на стороне сервера
  2. , заполните поле штампом и датой исполнения
  3. напечатайте на консоли браузера время выполнения метода

Никаких дополнительных зависимостей или фрагментов.Он работает так же, как из коробки.

0 голосов
/ 23 мая 2018

Терри, всего лишь совет, вы смотрели на консоль браузера, чтобы увидеть, нет ли каких-либо ошибок (из кода на стороне клиента)?У вас включено ведение журнала ошибок, чтобы увидеть, не генерируются ли ошибки в вашем коде SSJS / Java?

...