From 390685b8ba3e0f3f65a1ff30701d41a750d15491 Mon Sep 17 00:00:00 2001 From: Ziheng Sun Date: Sun, 22 Oct 2023 01:54:52 -0400 Subject: [PATCH] fix the multi user logging out problem --- pom.xml | 2 +- .../java/com/gw/GeoweaverApplication.java | 2 - .../com/gw/local/LocalSessionNixImpl.java | 6 ++- .../java/com/gw/local/LocalSessionOutput.java | 42 +++++++-------- .../java/com/gw/server/CommandServlet.java | 4 +- src/main/java/com/gw/tools/ExecutionTool.java | 24 ++++----- src/main/java/com/gw/tools/LocalhostTool.java | 11 ++-- src/main/java/com/gw/tools/WorkflowTool.java | 2 +- src/main/java/com/gw/utils/BeanTool.java | 53 +++++++++++++------ src/main/resources/static/js/gw.js | 2 +- 10 files changed, 81 insertions(+), 67 deletions(-) diff --git a/pom.xml b/pom.xml index 3fea18704..97b13306f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.gw geoweaver - 1.2.0 + 1.2.1 geoweaver A lightweight workflow management software for organizing data analysis workflows, preserving history of every workflow run, and improving scientist producitvity and workflow FAIRness, diff --git a/src/main/java/com/gw/GeoweaverApplication.java b/src/main/java/com/gw/GeoweaverApplication.java index b11e1b623..a581f17cb 100644 --- a/src/main/java/com/gw/GeoweaverApplication.java +++ b/src/main/java/com/gw/GeoweaverApplication.java @@ -188,8 +188,6 @@ public static void addDefaultPublicUser(){ } - logger.debug("test what is going on"); - //set everything that doesn't have an owner to this user ut.belongToPublicUser(); diff --git a/src/main/java/com/gw/local/LocalSessionNixImpl.java b/src/main/java/com/gw/local/LocalSessionNixImpl.java index 447c610f8..7416ba8ed 100644 --- a/src/main/java/com/gw/local/LocalSessionNixImpl.java +++ b/src/main/java/com/gw/local/LocalSessionNixImpl.java @@ -28,6 +28,7 @@ import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @@ -93,6 +94,7 @@ public class LocalSessionNixImpl implements LocalSession { public LocalSessionNixImpl() { //this is for spring + log.info("localsessionniximpl object is created for " + token); } @@ -112,10 +114,10 @@ public void initHistory(String history_id, String script, String processid, bool this.isClose = false; history = history_tool.initProcessHistory(history_id, processid, script); + + // this.sender = createLocalSessionOutput(); } - - /** * If the process ends with error diff --git a/src/main/java/com/gw/local/LocalSessionOutput.java b/src/main/java/com/gw/local/LocalSessionOutput.java index a8c77671d..7284e8667 100644 --- a/src/main/java/com/gw/local/LocalSessionOutput.java +++ b/src/main/java/com/gw/local/LocalSessionOutput.java @@ -1,6 +1,7 @@ package com.gw.local; import java.io.BufferedReader; +import java.io.IOException; import javax.websocket.Session; @@ -73,7 +74,7 @@ public LocalSessionOutput() { * @param jupyterfilepath The Jupyter file path, if applicable. */ public void init(BufferedReader in, String token, String history_id, String lang, String jupyterfilepath) { - log.info("LocalSessionOutput created"); + log.info("LocalSessionOutput created for token "+ token); this.in = in; this.token = token; this.run = true; @@ -96,21 +97,19 @@ public void stop() { * @param msg The message to be sent to the WebSocket. */ public void sendMessage2WebSocket(String msg) { - if (!BaseTool.isNull(wsout)) { - synchronized (wsout) { - try { - if (wsout.isOpen()) { - wsout.getBasicRemote().sendText(msg); - } else { - log.debug("WebSocket is closed, message didn't send: " + msg); - } - } catch (Exception e) { - e.printStackTrace(); - log.debug("Exception happens, message didn't send: " + msg); + try { + this.wsout = CommandServlet.findSessionById(token); + if (!BaseTool.isNull(wsout)){ + if(wsout.isOpen()) { + wsout.getBasicRemote().sendText(msg); + }else{ + CommandServlet.removeSessionById(token); } + }else{ + log.warn(String.format("cannot find websocket for token %s", token)); } - } else { - log.debug("WebSocket is null, message didn't send: " + msg); + } catch (IOException e1) { + e1.printStackTrace(); } } @@ -162,7 +161,7 @@ public void endWithCode(String token, int exitvalue) { ht.saveHistory(h); - CommandServlet.sendMessageToSocket(token, "Exit Code: " + exitvalue); + this.sendMessage2WebSocket("Exit Code: " + exitvalue); } /** @@ -248,7 +247,7 @@ public void run() { this.updateStatus("Running", "Running"); // Send a message to the WebSocket indicating that the process has started - CommandServlet.sendMessageToSocket(token, "Process " + this.history_id + " Started"); + this.sendMessage2WebSocket("Process " + this.history_id + " Started"); String line = null; // Initialize a variable to store each line of output @@ -265,7 +264,7 @@ public void run() { } linenumber++; // Increment the line number - + if(linenumber%1==0){ this.updateStatus(logs.toString(), "Running"); } @@ -297,7 +296,7 @@ public void run() { } else if (line.contains("==== Geoweaver Bash Output Finished ====")) { // Handle specific marker lines if present } else { - log.info("Local thread output >> " + line); // Log each line of output + log.info("Local thread output >> " + line + " - token: " + token); // Log each line of output logs.append(line).append("\n"); // Append the line to the logs if (!BaseTool.isNull(wsout) && wsout.isOpen()) { @@ -305,8 +304,7 @@ public void run() { line = prelog.toString() + line; prelog = new StringBuffer(); } - //this.sendMessage2WebSocket(line); // Send the line to the WebSocket - CommandServlet.sendMessageToSocket(token, line); + this.sendMessage2WebSocket(line); } else { prelog.append(line).append("\n"); // Append to the prelog if WebSocket isn't available } @@ -344,7 +342,7 @@ public void run() { } // Send a message to the WebSocket indicating that the process has finished - CommandServlet.sendMessageToSocket(token, "The process " + history_id + " is finished."); + this.sendMessage2WebSocket("The process " + history_id + " is finished."); // This thread will end by itself when the task is finished; you don't have to close it manually GeoweaverController.sessionManager.closeByToken(token); // Close the session by token @@ -355,7 +353,7 @@ public void run() { // Depending on the language, update the status to "Failed" this.updateStatus(logs.toString() + "\n" + e.getLocalizedMessage(), "Failed"); } finally { - CommandServlet.sendMessageToSocket(token, "======= Process " + this.history_id + " ended"); + this.sendMessage2WebSocket("======= Process " + this.history_id + " ended"); } } diff --git a/src/main/java/com/gw/server/CommandServlet.java b/src/main/java/com/gw/server/CommandServlet.java index f55e2dba9..aec2825c3 100644 --- a/src/main/java/com/gw/server/CommandServlet.java +++ b/src/main/java/com/gw/server/CommandServlet.java @@ -241,7 +241,7 @@ public static javax.websocket.Session findSessionById(String token) { * @param token The token of the target WebSocket session. * @param message The message to be sent. */ - public static void sendMessageToSocket(String token, String message) { + public static Session sendMessageToSocket(String token, String message) { try { Session wsout = CommandServlet.findSessionById(token); if (!BaseTool.isNull(wsout)){ @@ -253,9 +253,11 @@ public static void sendMessageToSocket(String token, String message) { }else{ logger.warn(String.format("cannot find websocket for token %s", token)); } + return wsout; } catch (IOException e1) { e1.printStackTrace(); } + return null; } /** diff --git a/src/main/java/com/gw/tools/ExecutionTool.java b/src/main/java/com/gw/tools/ExecutionTool.java index ea321043a..96822753f 100644 --- a/src/main/java/com/gw/tools/ExecutionTool.java +++ b/src/main/java/com/gw/tools/ExecutionTool.java @@ -1,9 +1,11 @@ package com.gw.tools; import com.gw.utils.BaseTool; +import com.gw.utils.BeanTool; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @@ -14,20 +16,8 @@ @Scope("prototype") public class ExecutionTool { - @Autowired - ProcessTool pt; - - @Autowired - LocalhostTool lt; - - @Autowired - RemotehostTool rt; - @Autowired BaseTool bt; - - @Autowired - EnvironmentTool envt; @Autowired TaskManager tm; @@ -51,6 +41,8 @@ public String executeProcess(String history_id, String id, String hid, String ps String bin = null, pyenv = null, basedir = null; + EnvironmentTool envt = BeanTool.getBean(EnvironmentTool.class); + Environment envobj = envt.getEnvironmentById(envid); if(!BaseTool.isNull(envobj)){ @@ -85,6 +77,7 @@ public String executeProcess(String history_id, String id, String hid, String ps public String executeProcess(String history_id, String id, String hid, String pswd, String httpsessionid, boolean isjoin, String bin, String pyenv, String basedir) { + ProcessTool pt = BeanTool.getBean(ProcessTool.class); String category = pt.getTypeById(id); @@ -95,6 +88,8 @@ public String executeProcess(String history_id, String id, String hid, String ps if(BaseTool.isNull(basedir)) basedir = "~"; if(bt.islocal(hid)) { + + LocalhostTool lt = BeanTool.getBean(LocalhostTool.class); //localhost if("shell".equals(category)) { @@ -123,6 +118,7 @@ public String executeProcess(String history_id, String id, String hid, String ps }else { //non-local remote server + RemotehostTool rt = BeanTool.getBean(RemotehostTool.class); if("shell".equals(category)) { @@ -166,10 +162,14 @@ public String readEnvironment(String hid, String password){ if(bt.islocal(hid)){ + LocalhostTool lt = BeanTool.getBean(LocalhostTool.class); + resp = lt.readPythonEnvironment(hid, password); }else{ + RemotehostTool rt = BeanTool.getBean(RemotehostTool.class); + resp = rt.readPythonEnvironment(hid, password); } diff --git a/src/main/java/com/gw/tools/LocalhostTool.java b/src/main/java/com/gw/tools/LocalhostTool.java index 11b654fdb..b6666c159 100644 --- a/src/main/java/com/gw/tools/LocalhostTool.java +++ b/src/main/java/com/gw/tools/LocalhostTool.java @@ -13,6 +13,7 @@ import com.gw.tasks.GeoweaverProcessTask; import com.gw.tasks.TaskManager; import com.gw.utils.BaseTool; +import com.gw.utils.BeanTool; import com.gw.utils.OSValidator; import com.gw.web.GeoweaverController; @@ -62,12 +63,6 @@ public class LocalhostTool { @Autowired ProcessRepository processrepository; - @Autowired - LocalSessionNixImpl nixsession; - - @Autowired - LocalSessionWinImpl winsession; - public void saveHistory(String processid, String script, String history_id){ History history = histool.getHistoryById(history_id); @@ -182,11 +177,11 @@ public LocalSession getLocalSession() { if(OSValidator.isWindows()) { - session = winsession; + session = BeanTool.getBean(LocalSessionWinImpl.class); }else if(OSValidator.isMac() || OSValidator.isUnix()) { - session = nixsession; + session = BeanTool.getBean(LocalSessionNixImpl.class); }else { diff --git a/src/main/java/com/gw/tools/WorkflowTool.java b/src/main/java/com/gw/tools/WorkflowTool.java index a3f961eea..0a4d611b8 100644 --- a/src/main/java/com/gw/tools/WorkflowTool.java +++ b/src/main/java/com/gw/tools/WorkflowTool.java @@ -340,7 +340,7 @@ public String execute(String history_id, String wid, String mode, try { task.initialize(history_id, wid, mode, hosts, pswds, envs, token); - + task.execute(); resp = "{\"history_id\": \""+task.getHistory_id()+ diff --git a/src/main/java/com/gw/utils/BeanTool.java b/src/main/java/com/gw/utils/BeanTool.java index 0b38147af..2e3d479ac 100644 --- a/src/main/java/com/gw/utils/BeanTool.java +++ b/src/main/java/com/gw/utils/BeanTool.java @@ -5,26 +5,45 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; +/** + * BeanTool is a utility class designed to interact with Spring Application Context for bean management. + * It provides methods to access beans and the application context within a Spring application. + */ @Component public class BeanTool implements ApplicationContextAware { - - private static ApplicationContext context; + + // The application context is set by Spring when this class is ApplicationContextAware. + private static ApplicationContext context; - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - - context = applicationContext; - - } - - public static ApplicationContext getApplicationContext() { - return context; - } - - public static T getBean(Class beanClass) { - - return context.getBean(beanClass); + /** + * Called by Spring to set the application context for this class. + * + * @param applicationContext The Spring application context. + * @throws BeansException If an error occurs while setting the application context. + */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + context = applicationContext; } - + /** + * Get the current Spring Application Context. + * + * @return The Spring Application Context. + */ + public static ApplicationContext getApplicationContext() { + return context; + } + + /** + * Get a bean of the specified class from the Spring Application Context. + * + * @param The type of the bean to retrieve. + * @param beanClass The class of the bean to retrieve. + * @return An instance of the specified bean class. + */ + public static T getBean(Class beanClass) { + return context.getBean(beanClass); + } } + diff --git a/src/main/resources/static/js/gw.js b/src/main/resources/static/js/gw.js index 99e1641c3..50e436120 100644 --- a/src/main/resources/static/js/gw.js +++ b/src/main/resources/static/js/gw.js @@ -9,7 +9,7 @@ edu = { sponsor: "ESIPLab incubator project, NASA ACCESS project, NSF Geoinformatics project, NSF Cybertraining project", - version: "1.2.0", + version: "1.2.1", author: "open source contributors",