ending JVM when the browser tab is closed in spring boot application - java

I have a spring-boot web application to be distributed as jar file. The code to start the application is as follows:
private static ConfigurableApplicationContext ctx;
public static void main(String[] args){
if(ctx == null) {
ctx = SpringApplication.run(MyApplication.class, args);
}
try {
openHomePage("http://localhost:8090/");
}catch(Exception e) {
logger.error("Error occured starting the application: ", e);
ctx.close();
}
}
private static void openHomePage(String url) throws IOException, URISyntaxException {
if(Desktop.isDesktopSupported()) {
URI homePage = new URI(url);
Desktop.getDesktop().browse(homePage);
}else {
Runtime runtime = Runtime.getRuntime();
runtime.exec(new String[]{"cmd", "/c","start chrome " + url});
}
}
which opens the home page in Chrome, both when I run it from Eclipse and by double clicking on the jar file.
The problem is when I start the application from the jar file and close the browser tab, the application continues to run in JVM and I have to kill it from the task manager manually which is annoying. If I don't kill the JVM and double click on the jar file again, then the application doesn't start automatically as it does the first time, and I have to manually open a new browser tab and type http://localhost:8090/ in order to use the application.
Is it possible to kill every process after user closes the browser tab so that when they click on the jar file next time they need to use the application, a fresh browser tab opens automatically?
Thanks in advance..

SOLUTION
This might not be the best solution but it works a treat.
*Step 1 - Send heartbeats from the browser
var heartBeatIntervals = null;
$( document ).ready(function() {
//this ajax call will be fired every 2 seconds as long as the browser tab stays open.
// the time intervals can of course be modified
heartBeatIntervals = setInterval(() => {
$.ajax({
type:'POST',
url: 'http://localhost:8090/MyController/checkHeartbeats'
})
}, 2*1000);
});
*Step 2 - Handle the heartbeats in the server
#Controller
#RequestMapping("/MyController")
public class MyController {
//declare an instance variable to store the number of missed heartbeats
private int missedHeartbeats = 0;
//reset the counter to 0 upon receiving the heartbeats
#PostMapping("/checkHeartbeats")
public void checkHeartbeats() {
missedHeartbeats = 0;
}
//increase the missedHeartbeats by one every 3 seconds - or whatever
#Scheduled(fixedRate = 3000)
public void schedule() {
missedHeartbeats++;
//check how many heartbeats are missed and if it reaches to a certain value
if(missedHeartbeats > 5) {
//terminate the JVM (also terminates the servlet context in Eclipse)
System.exit(0);
}
}
}
*Step - 3 Enable scheduling
In order to use any scheduling in spring-boot application you need to add #EnableScheduling annotation in your class where your main method resides.
And that's it.

There's a stop button in Eclipse. And in case it can't be used:
You can send something from javascript to your server continiously and when server haven't recieved it for 1 sec, which means the web page was closed, stop itself.
Solution 1
Use a method in any #Controller to handle heartbeat requests.
Store the most recent heartbeat time in a static field of any class, the initial value could be 0 or -1 indicating the web page has not been opened yet.
Use a #Scheduled task to retrive last heartbeat time and compare with current time. schedule the task once per 2 second or whatever. https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html#scheduling-annotation-support
Stop JVM if needed, maybe by System.exit(0).
Solution 2
It would be easier if you can add a Close button on webpage. being clicked, it signals the server to stop, and afterwards it closes the web page itself. https://stackoverflow.com/a/18776480/9399618

Related

Launch Firefox and Wait until it is Closed

Question
I want to start the Firefox web browser as process to visit a specific website, then wait until it is closed.
A special situation is that the browser may already be open and running, as the user may have visited some website already.
In that case, the browser would probably open a new tab in an existing window and the newly launched process will be terminated immediately. This should not confuse my waiting process: Either, I want a new browser window (if that can somehow be enforced, maybe via command line arguments) and wait until that is closed, or keep the existing browser window and wait until all the tabs resulting from my process are closed.
Environment
I think it doesn't matter, but my programming environment is Java and you can assume that I know the path of the browser.
Example
The only browser for which I can obtain the expected behavior is Internet Explorer (sigh.). Here, I need to basically create a new batch script in a temp folder with something like
start /WAIT "" "C:\Program Files\Internet Explorer\iexplore.exe" -noframemerging http://www.test.com/
I then run the batch script instead of directly the browser and delete it once I am finished with waiting.
Intended Process
To make the intended process clearer:
My program starts.
My program launches the Firefox browser as separate process and provides an URL to visit as argument to that process.
The Firefox browser runs asynchronously, as a new process, and visits the provided URL. So far, this is easy.
After launching the new process (the Firefox browser), my own program should wait for the said process to terminate. This is the hard part, as
Many modern browsers start multiple processes. I would need to wait for all of them.
Many modern browsers may somehow "detach" themselves from the process that I launched. Sorry, I don't know a better word, what I mean is: I start a process which then starts another process and terminates immediately while the other process keeps running. If I wait for the browser process originally started by my program, the waiting will be finished while the browser is still open.
A special case of the above is tabbed browsing as realized in many browsers: If the browser is already open (in a separate process started by the user) when I launch it, my newly started browser process may simple communicate the URL to visit to the existing process and terminate. The user is still on my provided URL while my program thinks she has closed the browser. This issue can maybe be forbidden by specifying a special command line argument, like noframemerging for the IE.
Once the browser has terminated or all tabs related to the URL I provide have been closed, my program will cease to wait and instead continue doing its business.
The use case is that I have a web application which can either run locally or on a server. If it is run locally, it launches a web server, then opens the browser to visit the entry page. Once the browser is closed, that web application should shut down as well. This works reliable for Internet Explorer, for all other cases, the user has to close the browser and then, explicitly, the web application. Thus, if I could wait reliably for Firefox to finish, this would make the user experience much better.
Solution Preferences:
Solutions are prefered in the following order
Anything which ships with the pure Java JRE. This includes special command line arguments to the browser.
Things that require me to, e.g., create a batch script (such as in the IE case.)
Anything that requires 3rd party open source libraries.
Anything that requires 3rth party closed source libraries.
Any platform independent answer (working both Windows and Linux) is prefered over platform-dependent ones.
Reason: In the ideal case, I would like to know what exactly is done and include it into my own code. As I want to support different browsers (see "PS" below), I would like to avoid having to include one library per browser. Finally, I cannot use commercial or closed source libraries, but if no better answer turns up, of course, I will honor any working solution with an accept. I will accept the first (reasonably nice) working answer of type "1". If answers of lower preference turn up, I will wait a few days before accepting the best one among them.
PS
I will launch a couple of similar questions for other browsers. Since I believe that browsers are quite different in the command line arguments they digest, the way the launch threads and sub-processes, I think this makes sense.
Similar question regarding Chrome: Launch Chrome and Wait Until it is Closed
Similar question regarding Opera: Launch Opera and Wait Until it is Closed
Similar question regarding Chromium: Launch Chromium and Wait Until it is Closed
Similar question regarding Edge: Launch Edge Browser and Wait Until it is Closed
Similar question regarding Safari: Launch Safari and Wait Until it is Closed
Here is a sample program that may somehow manages to demonstrate the capability of a selenium library to fulfill what you want. You need to download the selenium library and set it to your IDE first before you can run this program.
The program allows you to click a button. Then the firefox browser automatically opens and launch a website in a few seconds. Please wait while the website is loading. After that you may close the Firefox browser. The program shall also automatically close after 2 seconds.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.net.ConnectException;
import javax.swing.*;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class AnotherTest extends JFrame {
WebDriver driver;
JLabel label;
public AnotherTest() {
super("Test");
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width - 400) / 2, (screenSize.height - 100) / 2, 400, 100);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
quitApplication();
}
});
JButton jButton1 = new javax.swing.JButton();
label = new JLabel("");
JPanel panel = new JPanel(new FlowLayout());
panel.add(jButton1);
add(panel, BorderLayout.CENTER);
add(label, BorderLayout.SOUTH);
jButton1.setText("Open Microsoft");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
label.setText("Loading browser. Please wait..");
java.util.Timer t = new java.util.Timer();
t.schedule(new java.util.TimerTask() {
#Override
public void run() {
openBrowserAndWait();
}
}, 10);
}
});
}
private void openBrowserAndWait() {
driver = new FirefoxDriver();
String baseUrl = "https://www.microsoft.com";
driver.get(baseUrl);
java.util.Timer monitorTimer = new java.util.Timer();
monitorTimer.schedule(new java.util.TimerTask() {
#Override
public void run() {
while (true) {
checkDriver();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
}
}
}
}, 10);
}
private void checkDriver() {
if (driver == null) {
return;
}
boolean shouldExit = false;
try {
label.setText(driver.getTitle());
} catch (NoSuchWindowException e) {
System.out.println("Browser has been closed. Exiting Program");
shouldExit = true;
} catch (Exception e) {
System.out.println("Browser has been closed. Exiting Program");
shouldExit = true;
}
if (shouldExit) {
this.quitApplication();
}
}
private void quitApplication() {
// attempt to close gracefully
if (driver != null) {
try {
driver.quit();
} catch (Exception e) {
}
}
System.exit(0);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new AnotherTest().setVisible(true);
}
});
}
}
Selenium is primarily used for testing automation of web applications. It can directly open browsers and read the html contents in it. See http://www.seleniumhq.org/ for additional information.

Launch Opera and Wait Until it is Closed [duplicate]

Question
I want to start the Firefox web browser as process to visit a specific website, then wait until it is closed.
A special situation is that the browser may already be open and running, as the user may have visited some website already.
In that case, the browser would probably open a new tab in an existing window and the newly launched process will be terminated immediately. This should not confuse my waiting process: Either, I want a new browser window (if that can somehow be enforced, maybe via command line arguments) and wait until that is closed, or keep the existing browser window and wait until all the tabs resulting from my process are closed.
Environment
I think it doesn't matter, but my programming environment is Java and you can assume that I know the path of the browser.
Example
The only browser for which I can obtain the expected behavior is Internet Explorer (sigh.). Here, I need to basically create a new batch script in a temp folder with something like
start /WAIT "" "C:\Program Files\Internet Explorer\iexplore.exe" -noframemerging http://www.test.com/
I then run the batch script instead of directly the browser and delete it once I am finished with waiting.
Intended Process
To make the intended process clearer:
My program starts.
My program launches the Firefox browser as separate process and provides an URL to visit as argument to that process.
The Firefox browser runs asynchronously, as a new process, and visits the provided URL. So far, this is easy.
After launching the new process (the Firefox browser), my own program should wait for the said process to terminate. This is the hard part, as
Many modern browsers start multiple processes. I would need to wait for all of them.
Many modern browsers may somehow "detach" themselves from the process that I launched. Sorry, I don't know a better word, what I mean is: I start a process which then starts another process and terminates immediately while the other process keeps running. If I wait for the browser process originally started by my program, the waiting will be finished while the browser is still open.
A special case of the above is tabbed browsing as realized in many browsers: If the browser is already open (in a separate process started by the user) when I launch it, my newly started browser process may simple communicate the URL to visit to the existing process and terminate. The user is still on my provided URL while my program thinks she has closed the browser. This issue can maybe be forbidden by specifying a special command line argument, like noframemerging for the IE.
Once the browser has terminated or all tabs related to the URL I provide have been closed, my program will cease to wait and instead continue doing its business.
The use case is that I have a web application which can either run locally or on a server. If it is run locally, it launches a web server, then opens the browser to visit the entry page. Once the browser is closed, that web application should shut down as well. This works reliable for Internet Explorer, for all other cases, the user has to close the browser and then, explicitly, the web application. Thus, if I could wait reliably for Firefox to finish, this would make the user experience much better.
Solution Preferences:
Solutions are prefered in the following order
Anything which ships with the pure Java JRE. This includes special command line arguments to the browser.
Things that require me to, e.g., create a batch script (such as in the IE case.)
Anything that requires 3rd party open source libraries.
Anything that requires 3rth party closed source libraries.
Any platform independent answer (working both Windows and Linux) is prefered over platform-dependent ones.
Reason: In the ideal case, I would like to know what exactly is done and include it into my own code. As I want to support different browsers (see "PS" below), I would like to avoid having to include one library per browser. Finally, I cannot use commercial or closed source libraries, but if no better answer turns up, of course, I will honor any working solution with an accept. I will accept the first (reasonably nice) working answer of type "1". If answers of lower preference turn up, I will wait a few days before accepting the best one among them.
PS
I will launch a couple of similar questions for other browsers. Since I believe that browsers are quite different in the command line arguments they digest, the way the launch threads and sub-processes, I think this makes sense.
Similar question regarding Chrome: Launch Chrome and Wait Until it is Closed
Similar question regarding Opera: Launch Opera and Wait Until it is Closed
Similar question regarding Chromium: Launch Chromium and Wait Until it is Closed
Similar question regarding Edge: Launch Edge Browser and Wait Until it is Closed
Similar question regarding Safari: Launch Safari and Wait Until it is Closed
Here is a sample program that may somehow manages to demonstrate the capability of a selenium library to fulfill what you want. You need to download the selenium library and set it to your IDE first before you can run this program.
The program allows you to click a button. Then the firefox browser automatically opens and launch a website in a few seconds. Please wait while the website is loading. After that you may close the Firefox browser. The program shall also automatically close after 2 seconds.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.net.ConnectException;
import javax.swing.*;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class AnotherTest extends JFrame {
WebDriver driver;
JLabel label;
public AnotherTest() {
super("Test");
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width - 400) / 2, (screenSize.height - 100) / 2, 400, 100);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
quitApplication();
}
});
JButton jButton1 = new javax.swing.JButton();
label = new JLabel("");
JPanel panel = new JPanel(new FlowLayout());
panel.add(jButton1);
add(panel, BorderLayout.CENTER);
add(label, BorderLayout.SOUTH);
jButton1.setText("Open Microsoft");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
label.setText("Loading browser. Please wait..");
java.util.Timer t = new java.util.Timer();
t.schedule(new java.util.TimerTask() {
#Override
public void run() {
openBrowserAndWait();
}
}, 10);
}
});
}
private void openBrowserAndWait() {
driver = new FirefoxDriver();
String baseUrl = "https://www.microsoft.com";
driver.get(baseUrl);
java.util.Timer monitorTimer = new java.util.Timer();
monitorTimer.schedule(new java.util.TimerTask() {
#Override
public void run() {
while (true) {
checkDriver();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
}
}
}
}, 10);
}
private void checkDriver() {
if (driver == null) {
return;
}
boolean shouldExit = false;
try {
label.setText(driver.getTitle());
} catch (NoSuchWindowException e) {
System.out.println("Browser has been closed. Exiting Program");
shouldExit = true;
} catch (Exception e) {
System.out.println("Browser has been closed. Exiting Program");
shouldExit = true;
}
if (shouldExit) {
this.quitApplication();
}
}
private void quitApplication() {
// attempt to close gracefully
if (driver != null) {
try {
driver.quit();
} catch (Exception e) {
}
}
System.exit(0);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new AnotherTest().setVisible(true);
}
});
}
}
Selenium is primarily used for testing automation of web applications. It can directly open browsers and read the html contents in it. See http://www.seleniumhq.org/ for additional information.

FB SDK not working on OS 7

I am implementing FB in one of my app.I am using jar 0.8.25. Its working fine on all simulators from 5 to 7.1.And for devices works only for OS 5 and 6 but not working on device 7 and 7.1.For OS 7 after log in success it remains on FB page it doesn't redirect back. and when i press back button, i get error encountered unable to refresh access token with try again button.
When analyzing on console it never finds access token single time for OS 7.while for 5 and 6 its working perfectly.
Please tell what may cause the issue.
Thanks,
This isn't a solution to your specific problem. I mentioned in the comments that I'm using an interface. So I'm posting here as its too much for the comment section. It is also not the COMPLETE solution, you will need to handle the flow and expired tokens, this is just to show you the logic of how I did this.
For my interface I open a browserfield to the Oauth url:
https://www.facebook.com/dialog/oauth?client_id=<APP_ID>&response_type=token&redirect_uri=http://www.facebook.com/connect/login_success.html&scope=publish_actions
And I add a listener to this browser to listen for the redirects after login. Once you have the access token, you should persist it and close the browserfield.
private class OAuthScreen extends MainScreen
{
BrowserField browser_field;
LoadingDialog loading_dialog;
public OAuthScreen(final Command task)
{
super(VERTICAL_SCROLL | HORIZONTAL_SCROLL);
BrowserFieldConfig browserConfig = new BrowserFieldConfig();
browserConfig.setProperty(BrowserFieldConfig.VIEWPORT_WIDTH, new Integer(Display.getWidth()));
browser_field = new BrowserField(browserConfig);
browser_field.addListener(new BrowserFieldListener()
{
public void documentCreated(BrowserField browserField, ScriptEngine scriptEngine, Document document) throws Exception
{
int index = browserField.getDocumentUrl().indexOf("#access_token=");
if (index == -1)
{
super.documentCreated(browserField, scriptEngine, document);
}
else
{
access_token = browserField.getDocumentUrl().substring(index + "#access_token=".length(), browserField.getDocumentUrl().indexOf("&"));
PersistentObject store = PersistentStore.getPersistentObject(STORE_KEY);
FacebookTokens store_tokens = new FacebookTokens();
store_tokens.access_token = access_token;
store.setContents(store_tokens);
store.commit();
if (task != null) task.execute();
OAuthScreen.this.close();
}
}
public void documentLoaded(BrowserField browserField, Document document) throws Exception
{
super.documentLoaded(browserField, document);
loading_dialog.close();
}
});
// whatever loading dialog you want, this sometimes takes a while to open
loading_dialog = LoadingDialog.push(loading_field);
add(browser_field);
browser_field.requestContent("https://www.facebook.com/dialog/oauth?client_id="+APP_ID+"&response_type=token&redirect_uri=http://www.facebook.com/connect/login_success.html&scope=publish_actions");
}
}
The callback task is just for if I want to perform a call directly after login.
Now just perform API calls as you need them. API methods here https://developers.facebook.com/docs/graph-api/reference/v2.0/
Methods that require the access token, should have it appended to the url such as, https://graph.facebook.com/me/feed?access_token=" + access_token
Be aware that clearing your access token won't clear the token stored in the browser field. And will mean that you can't login next time (because the browser is still logged in).
So if you want to logout you need to open this link in a browserfield before clearing your local access token "https://www.facebook.com/logout.php?next=http://www.facebook.com/connect/login_success.html&access_token=" + access_token
Clearing the cookies of the browser should suffice, but I haven't found a way to do this.

Java JButton and swing problem

I am doing a networking project. I compiled a code under Java Project console app and it works. But when I create a GUI and assign the code to run when a button is pressed, it hangs on clicking the button.
This is the source code:
#Action
public void EstablishConnection() {
serverAddress = jTextFieldServerAddress.getText();
serverPort = Integer.parseInt(jTextFieldPort.getText());
serverUName = jTextFieldUName.getText();
serverUPwd = jTextFieldUPwd.getText();
try {
client = new FTPClient();
client.connect(serverAddress, serverPort);
boolean login = client.login(serverUName, serverUPwd);
if(login) {
System.out.println("Successfully logged in\n");
}
else {
System.out.println("Unable to login\n");
}
}
catch(Exception ex) {
System.out.println("Exception Raised: " + ex);
}
}
The action is called when a button is pressed in the swing app. It is not working for me. But it is working very fast for a console app.
Anytime I see the word "hang" I assume you need to be using a separate Thread to execute the hanging code. See Concurrency in Swing for the solution.
I would suggest that you should run code that depends on external factors, like accessing a remote server etc., that could delay the response, in a thread of it's own.
Display a MessageDialog with an indeterminate progress bar:
connProgressBar.setIndeterminate(true);
You neither know whether your connection will terminate, nor if it will, so add a button that allows the user to kill the connection thread, whenever she feels like it.
Since you are probably connecting to an ftp server in order to upload and download files, after the connection has been established, use a determinate progressbar that shows the download percentage of the file or files progress, that runs in a new thread.

Session management in the gwt

I am working on an GWT-ext application.
In this application I managed client side session. For this I write below code:
To manage the session:
import com.google.gwt.user.client.Timer;
public class ClientTimers {
private static final Timer SESSION_MAY_HAVE_EXPIRED_TIMER = new Timer() {
#Override
public void run() {
// Warn the user, that the session may have expired.
// You could then show a login dialog, etc...
}
};
public static void renewSessionTimer() {
// First cancel the previous timer
SESSION_MAY_HAVE_EXPIRED_TIMER.cancel();
// Schedule again in 5 minutes (maybe make that configurable?)
// Actually, let's subtract 10 seconds from that, because our timer
// won't be synchronized perfectly with the server's timer.
SESSION_MAY_HAVE_EXPIRED_TIMER.schedule(5 * 60 * 1000 - 10000);
}
}
To get the user activity:
Ext.get("pagePanel").addListener("click", new EventCallback() {
#Override
public void execute(EventObject e) {
//MessageBox.alert("On Mouse Click");
});
Ext.get("pagePanel").addListener("keydown", new EventCallback() {
#Override
public void execute(EventObject e) { //
//MessageBox.alert("On Key Press Click");
}
});
This code is working fine but my issues :
This code will do log out automatically as the time out occurs.For my code I want that on click or key down it should do logout. Case is like this:If user is logged in and time to log out is 5 min.User don't do any activity on the screen than right now as per the above code it will log out automatically as the 5 min complete.
Now my requirement is that if user logged in and it doesn't do any thing for 5 mins.It should not do any logged out automatically.Instead of logging out on completion of 5 min,If user do click or key down on 6 min then it should do the log out process.
Basically the log out process as the timer exceed the specified time should be done on the user activity, not automatically.
In the Timer, increment a variable for each second.
And when user click on any button after 5 minutes or on 6th minute than check the counter variable and if the variable is greater than 6 than you can use Window.Location.reload(); to logout or reload().
I think the thing you are searchin for is:
Window.Location.reload();
Fire it every few secons with a timer, so the user always apper to be active.
(Btw I have that from Window close issues in gwt -ext )
Install a JavaScript event handler on an invisible div that covers the whole area. If it gets an event, send an AJAX request to the server.
The server can then do whatever it needs to do. On the client side, you can wait for a reply from the AJAX request and display "You have been logged out".
There is one drawback of this approach: Objects stored in the session will be kept alive for too long. So even if the user never logs out and just walks away (or his browser crashes), the session will stay alive.
After a couple of days, so many dead sessions will accumulate that your server will crash.
So the better solution is to auto logout the user as you do already and install an AJAX event handler as described above to display a message when the user returns to the browser.
This way, your server can clean up dead sessions and the user gets a message when he can read it (when he is in front of the screen).
Note that you can't differentiate between the user and the cleaning crew hitting the mouse.

Categories

Resources