Writing in a document when handling websocket message
I have method like this:
private void addSomeCode() {
ApplicationManager.getApplication().runWriteAction(() -> {
Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
Document document = editor.getDocument();
WriteCommandAction.runWriteCommandAction(project, () -> document.insertString(15, "lol"));
});
}
That method works as expected - it adds "lol" at some point of the document (if a document is opened).
However, I have a websocket connection and I want to add some code after receiving the message from the server. I have a class with a decorator `javax.websocket.ClientEndpoint and a method with decorator `javax.websocket.onMessage`. I use `tyrus-standalone-client` for websocket communication. When I call `addSomeCode` method from a method that is called by `onMessage`, then I get the following exception:
```
Aug 29, 2022 3:03:16 PM org.glassfish.tyrus.core.AnnotatedEndpoint onError
INFO: Unhandled exception in endpoint com.example.plugin.extension.ClientEndpoint.
com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments: EventQueue.isDispatchThread()=false Toolkit.getEventQueue()=com.intellij.ide.IdeEventQueue@5c280260
Current thread: Thread[Grizzly(1),5,main] 762364072
Write thread: Thread[AWT-EventQueue-0,6,main] 2053884691
at com.intellij.openapi.application.impl.ApplicationImpl.assertIsWriteThread(ApplicationImpl.java:1041)
at com.intellij.openapi.application.impl.ApplicationImpl.startWrite(ApplicationImpl.java:1123)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:934)
at com.example.plugin.extension.Window.addSomeCode(Window.java:52)
at com.example.plugin.extension.Window$1.handleMessage(Window.java:69)
at com.example.plugin.extension.ClientEndpoint.onMessage(ClientEndpoint.java:43)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.glassfish.tyrus.core.AnnotatedEndpoint.callMethod(AnnotatedEndpoint.java:477)
at org.glassfish.tyrus.core.AnnotatedEndpoint.access$100(AnnotatedEndpoint.java:87)
at org.glassfish.tyrus.core.AnnotatedEndpoint$WholeHandler$1.onMessage(AnnotatedEndpoint.java:573)
at org.glassfish.tyrus.core.TyrusSession.notifyMessageHandlers(TyrusSession.java:564)
at org.glassfish.tyrus.core.TyrusEndpointWrapper.onMessage(TyrusEndpointWrapper.java:819)
at org.glassfish.tyrus.core.TyrusWebSocket.onMessage(TyrusWebSocket.java:206)
at org.glassfish.tyrus.core.frame.TextFrame.respond(TextFrame.java:135)
at org.glassfish.tyrus.core.ProtocolHandler.process(ProtocolHandler.java:658)
at org.glassfish.tyrus.client.TyrusClientEngine$TyrusReadHandler.handle(TyrusClientEngine.java:668)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter$ProcessTask.execute(GrizzlyClientFilter.java:472)
at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:114)
at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:91)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleRead(GrizzlyClientFilter.java:270)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.base/java.lang.Thread.run(Thread.java:829)
```
I can read in the documentation that "Writing data is only allowed from the UI thread". Probably that is why my code doesn't work. Is there a way to write to the document when handling websocket message then?
请先登录再写评论。
Hi Damian,
You may try wrapping the part responsible for writing with invokeLater or invokeAndWait.
See: https://plugins.jetbrains.com/docs/intellij/general-threading-rules.html#modality-and-invokelater