Агент вызова PostSaveDocument асинхронно

У меня есть страница Xpage с одним источником данных документа Notes.

После сохранения документа я хочу (условно) запустить агент. Агенту требуется некоторое время для обработки, и мы не хотим, чтобы пользователю приходилось ждать результата, поэтому он должен выполняться асинхронно.

Мне удалось заставить его работать с JS на стороне клиента, используя XHR для URL-адреса агента, но я хотел бы сделать это на стороне сервера, чтобы лучше контролировать «Следующую страницу». При использовании .run() или .runonserver() клиент ожидает завершения работы агента.

Любая идея, как я могу запустить агент (из SSJS) в PostSaveDocument, чтобы клиент не ждал результата?


person BvG013    schedule 04.06.2012    source источник


Ответы (4)


Попробуйте посмотреть приложение Thread and Jobs на OpenNTF.org. Есть хорошие демонстрации выполнения задачи в фоновом режиме, посмотрите здесь

person Martin Jinoch    schedule 12.06.2012
comment
Я использовал код JobScheduler и изменил его в соответствии со своими потребностями. Кажется, работает. - person BvG013; 20.06.2012

Как предложил Мартин, я использовал пример JobScheduler на OpenNtf и модифицировал его в соответствии со своими потребностями. Полученный код можно найти ниже. Любые комментарии или улучшения приветствуются.

import java.security.AccessController;
import java.security.PrivilegedAction;

import lotus.domino.Agent;
import lotus.domino.Database;

import lotus.domino.NotesException;
import lotus.domino.Session;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;

import com.ibm.domino.xsp.module.nsf.ThreadSessionExecutor;

public class JobRunner {

public static void start(String dbPath, String agentName, String paramDocId) {

    synchronized (JobRunner.class) {

        runningJob = new ISPJob(dbPath, agentName, paramDocId);
        runningJob.addJobChangeListener(new JobChangeAdapter() {
            public void done(IJobChangeEvent event) {
                System.out.println("Done event");
                runningJob = null;
            }
        });
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                runningJob.schedule();
                return null;
            }
        });

    }
}

private static ISPJob runningJob;

private static final class ISPJob extends Job {

    private ThreadSessionExecutor<IStatus> executor;

    private String docId;
    private String dbPath;
    private String agentName;

    public ISPJob(String paramDbPath, String paramAgentName, String paramDocId) {
        super(paramDocId);

        this.docId = paramDocId;
        this.dbPath = paramDbPath;
        this.agentName = paramAgentName;

        this.executor = new ThreadSessionExecutor<IStatus>() {
            @Override
            protected IStatus run(Session session) throws NotesException {

                System.out.println("Job started" + docId);
                System.out.println("   >> Session created: "
                        + session.getUserName() + ", Effective User:"
                        + session.getEffectiveUserName());

                    Database db = session.getDatabase(null,dbPath);

                    if (db != null) {
                        try {
                            if (!db.isOpen()) db.open();
                            if (db.isOpen()) {
                                System.out.println("   >> Database opened: "
                                        + db.getTitle());
                                Agent agent = db.getAgent(agentName);
                                try {
                                    System.out.println("   >> Agent Started: " + agent.getName());
                                    agent.run(docId);
                                    System.out.println("   >> Agent Ran: " + agent.getName());
                                } finally {
                                    agent.recycle();
                                }

                            }
                        } finally {
                            db.recycle();                           
                        }

                }
                System.out.println("Job completed");

                return Status.OK_STATUS;
            }
        };

    }

    protected IStatus run(IProgressMonitor monitor) {
        try {
            return executor.run();
        } catch (Exception ex) {
            return Status.CANCEL_STATUS;
        }
    }
};
}
person BvG013    schedule 20.06.2012
comment
Как вы называете класс? В сеансовом компоненте? - person stwissel; 26.06.2012
comment
Я вызываю его из функции SSJS, используя importPackage. - person BvG013; 23.07.2012

Вы можете использовать сеансовый компонент (чтобы он не был уничтожен), который запускает поток Java. Или вы можете ввести в коде консольную команду сервера. Или вы реализуете прослушиватель DOTS.

person stwissel    schedule 04.06.2012
comment
Спасибо за ваш ответ. Буду дальше рассматривать варианты 1 и 3. - person BvG013; 04.06.2012
comment
Или старый добрый агент, срабатывающий при изменении документов. - person D.Bugger; 06.06.2012

Это может быть/не быть вариантом в зависимости от требований вашего приложения, но я успешно вызываю функцию в событии onClientLoad, которое по существу запускает процесс после полной загрузки XPage.

person Russell Maher    schedule 07.06.2012