Что означает это предупреждение в Vaadin: Игнорирование вызова RPC для отключенного коннектора com.vaadin.ui.Window?

Я попытался найти в Google некоторые подсказки и посмотреть веб-сайт Vaadin, но я не нашел ничего, связанного с этим королем проблемы:

В консоли при запуске приложения несколько раз вижу это предупреждение:

Игнорирование вызова RPC для отключенного коннектора com.vaadin.ui.Window, caption=заголовок окна

Я использую надстройку Refresher, которая опрашивает мой сервер с интервалом в 2000 миллисекунд. и аддон ICEPush, который реализует отправку в пользовательский интерфейс Vaadin.

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

Вот код:

package com.example.events;

import java.util.ArrayList;
import java.util.List;

import com.github.wolfie.refresher.Refresher;
import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.event.LayoutEvents.LayoutClickNotifier;
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
import com.vaadin.ui.Button;

import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

public class Noticeboard extends VerticalLayout {

    /**
     * 
     */
    private static final long serialVersionUID = -6023888496081433464L;

    private static List<Note> notes = new ArrayList<Note>();
    private List<Window> windows = new ArrayList<Window>();
    private static int userCount;
    private int userId;
    private static int noteId;
    private Refresher refresher = new Refresher();
    private static final int UPDATE_INTERVAL = 2000;
    private Note currentlyFocusedNote;

    public class NoticeboardUpdater extends Thread {

        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(UPDATE_INTERVAL);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                getUI().getSession().getLockInstance().lock();
                try {
                    updateNoticeboard();
                } finally {
                    getUI().getSession().getLockInstance().unlock();
                }
            }
        }

    }

    public Noticeboard() {
        refresher.setRefreshInterval(UPDATE_INTERVAL);
        userId = ++userCount;
        setSpacing(true);
        setMargin(true);
        addComponent(new Label("Logged in as User " + userId));
        Button addNoteButton = new Button("Add note");

        addNoteButton.addClickListener(new ClickListener() {

            /**
             * 
             */
            private static final long serialVersionUID = -4927018162887570343L;

            @Override
            public void buttonClick(ClickEvent event) {
                Note note = new Note(++noteId);
                note.setCaption("Note " + note.getId());
                notes.add(note);

                Window window = createWindow(note);
                windows.add(window);

                UI.getCurrent().addWindow(window);
            }
        });

        addComponent(addNoteButton);
        addExtension(refresher);        
        new NoticeboardUpdater().start();
    }

    private Window createWindow(final Note note) {
        final Window window = new Window(note.getCaption());
        VerticalLayout layout = new VerticalLayout();
        layout.addComponent(createContentNote(note, window));
        window.setContent(layout);
        window.setWidth(300, Unit.PIXELS);
        window.setResizable(false);
        window.setPositionX(note.getPositionX());
        window.setPositionY(note.getPositionY());
        window.setData(note);
        window.addBlurListener(createBlurListener(window));
        window.addFocusListener(createFocusListener(window));

        LayoutClickNotifier mainLayout = (LayoutClickNotifier) getUI().getContent();
        mainLayout.addLayoutClickListener(e -> {
            if (note.isNoteFocusedWindow() || note.isNoteFocusedTextArea()) {               
                if (note.getLockedByUser() > -1 && note.getLockedByUser() == userId) {                  
                    unlockNote(getWindow(currentlyFocusedNote));
                    note.setNoteFocusedWindow(false);
                    note.setNoteBlurredWindow(false);
                    note.setNoteFocusedTextArea(false);
                    note.setNoteBlurredTextArea(false);                 

                    currentlyFocusedNote = null;
                }
            }
        });

        return window;
    }

    private TextArea createContentNote(final Note note, final Window window) {
        TextArea contentNote = new TextArea();
        contentNote.setSizeFull();
        contentNote.setValue(note.getText());
        contentNote.setImmediate(true);
        contentNote.setTextChangeEventMode(TextChangeEventMode.EAGER);
        contentNote.addBlurListener(createBlurListener(window));
        contentNote.addFocusListener(createFocusListener(window));
        contentNote.addTextChangeListener(new TextChangeListener() {

            /**
             * 
             */
            private static final long serialVersionUID = 8552875156973567499L;

            @Override
            public void textChange(TextChangeEvent event) {
                note.setText(event.getText());
            }
        });
        return contentNote;
    }

    private BlurListener createBlurListener(Window window) {
        return e -> {
            Component blurredComponent = e.getComponent();

            if (blurredComponent == window)  {
                currentlyFocusedNote.setNoteBlurredWindow(true);
            }
            else if (blurredComponent == (((Layout) window.getContent())).iterator().next()) {
                currentlyFocusedNote.setNoteBlurredTextArea(true);
            }

        };
    }

    private FocusListener createFocusListener(Window window) {
        return e -> {
            Component focusedComponent = e.getComponent();
            Note note = (Note) window.getData();

            if (currentlyFocusedNote != null && currentlyFocusedNote != note) {
                unlockNote(getWindow(currentlyFocusedNote));        
                currentlyFocusedNote.setNoteFocusedWindow(false);
                currentlyFocusedNote.setNoteBlurredWindow(false);
                currentlyFocusedNote.setNoteFocusedTextArea(false);
                currentlyFocusedNote.setNoteBlurredTextArea(false);
            }

            currentlyFocusedNote = note;
            if (focusedComponent == window) {
                Notification.show("Focused Note Window");
                currentlyFocusedNote.setNoteFocusedWindow(true);
            }
            else if (focusedComponent == (((Layout) window.getContent())).iterator().next()) {
                Notification.show("Focused Note TextArea");
                currentlyFocusedNote.setNoteFocusedTextArea(true);
            }

            if (currentlyFocusedNote.isNoteFocusedWindow() && currentlyFocusedNote.isNoteBlurredTextArea() || 
                currentlyFocusedNote.isNoteFocusedTextArea() && currentlyFocusedNote.isNoteBlurredWindow()) {
                // Lock is already set here, skipping
                return;
            }                       
            lockNote(window);
        };
    }

    private void lockNote(Window window) {
        Note note = (Note) window.getData();
        note.setLockedByUser(userId);
        String caption = "Locked by User " + userId;
        note.setCaption(caption);
        window.setCaption(caption);
    }

    private void unlockNote(Window window) {
        Note note = (Note) window.getData();
        note.setLockedByUser(-1);
        note.setPositionX(window.getPositionX());
        note.setPositionY(window.getPositionY());
        note.setCaption("Note " + note.getId());
        window.setCaption("Note " + note.getId());
    }

    private void updateNoticeboard() {
        for (Note note : notes) {
            Window window = getWindow(note);

            if (window == null) {
                window = createWindow(note);
                windows.add(window);
                UI.getCurrent().addWindow(window);
            }

            if (note.getLockedByUser() > -1) {
                if (note.getLockedByUser() != userId) {
                    // If the note is locked by another user, then we disable this window. 
                    window.setEnabled(false);

                    updateTextArea(window, note);                   
                    updateWindowPosition(window, note);
                }
                else {                  
                    // Otherwise the window is enabled.
                    window.setEnabled(true);
                    Note focusedNote = (Note) window.getData();

                    updateFocusedNotePosition(focusedNote, window);
                }
            }           
            else {
                window.setEnabled(true);
                updateTextArea(window, note);
                updateWindowPosition(window, note);
            }           
        }
    }

    private void updateTextArea(Window window, Note note) {
        Layout layout = (Layout) window.getContent();
        TextArea area = (TextArea) layout.iterator().next();
        area.setValue(note.getText());
    }

    private Window getWindow(Note note) {
        for (Window window : windows) {
            if (window.getData().equals(note))
                return window;
        }
        return null;
    }

    private void updateWindowPosition(Window window, Note note) {
        window.setPositionX(note.getPositionX());
        window.setPositionY(note.getPositionY());
        window.setCaption(note.getCaption());
    }

    private void updateFocusedNotePosition(Note focusedNote, Window window) {       
        focusedNote.setPositionX(window.getPositionX());
        focusedNote.setPositionY(window.getPositionY());
        focusedNote.setCaption(window.getCaption());
    }
}

И внутри метода инициализации пользовательского интерфейса я просто использую этот класс доски объявлений:

@Override
protected void init(VaadinRequest request) {
    setContent(new Noticeboard());
}

Когда я перемещаю окно, созданное с помощью кнопки «Добавить заметку», или меняю фокус с окна на другое, я получаю предупреждение.

Что может быть причиной такой проблемы?

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


person tonix    schedule 17.02.2015    source источник
comment
Побочный комментарий: поскольку вы используете Vaadin 7, я бы не рекомендовал вам использовать ICEPush (поскольку это экспериментальное дополнение) и Refresher. Обе функции встроены в фреймворк. Аннотируйте свой пользовательский интерфейс с помощью @Push, чтобы заменить функциональность ICEPush, и используйте ui.setPollInterval(..) / ui.addPollListener(..) для замены Refresher.   -  person Kim L    schedule 18.02.2015
comment
Да, я знал это. Я нашел интеграцию с атмосферой Vaadin хорошей функцией, в любом случае есть некоторые проблемы, когда вам нужно нажать все пользовательские интерфейсы, открытые пользователем в браузере. Существует метод VaadinSession.getCurrent().getUIs(), который, похоже, не возвращает коллекцию UI только с одним UI (фактически текущим, странно, да?), а не со всеми. Я также открыл тему на форуме Vaadin vaadin.com/forum#!/thread/ 8792945/8792944. В любом случае это не относится к теме вопроса. Как вы думаете, это связано с использованием старого аддона Refresher?   -  person tonix    schedule 18.02.2015


Ответы (1)


Когда вы отключаете компонент, отключенное состояние обрабатывается как на стороне клиента, так и на стороне сервера, то есть компонент не только визуально отключен, но и сервер отказывается обрабатывать любые запросы к отключенному компоненту.

Предупреждение, которое вы видите, означает, что существует запрос RPC (HTTP-запрос со стороны клиента), предназначенный для отключенного компонента. Поскольку компонент отключен, запрос RPC будет проигнорирован.

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

person Kim L    schedule 18.02.2015
comment
Спасибо за разъяснение! - person tonix; 18.02.2015
comment
Кроме того, с Vaadin 13.0.3 обсуждается аналогичное предупреждающее сообщение WARN com.vaadin.flow.server.communication.rpc.MapSyncRpcHandler — со стороны клиента получен запрос на обновление свойства для отключенного элемента. Свойство является «недействительным». Запрос игнорируется. здесь: github.com/vaadin/vaadin-text-field-flow/ вопросы/169 - person S. Doe; 22.01.2020
comment
Вот дополнительное обсуждение этого вопроса на форуме Vaadin: vaadin.com/forum/thread/18034776 - person Jonathan Hult; 07.08.2020