How to set a timer for activity of users? - java

I need to execute a specific method if user stop working in 5 hours.
Lets say user is signed in, but he does not add any record to a specific table of database for 5 hours.
Any time user adds a record to the specified table, the timer of that particular user should be reset otherwise it will keep going.
If it reaches to 5 hours , application should show a message indicating that you have not added any record for 5 hours.
To clarify please have a look at these steps
1- (1:00 PM) user1 is signed in -> timer of user1 is set
3- (1:00 PM) user2 is signed in -> timer of user2 is set
5- (1:10 PM) user1 adds something to the tableA
-> timer of user1 will be reset
6- (6:00 PM) user1 adds something to the tableA
-> timer of user1 will be reset
7- (6:00 PM) 5 hours is elapsed for user2 without adding any record to tableA
-> show the message to user2
8- (11:10 PM) 5 hours is elapsed for user1 without adding a record to TableA
-> show the message to user1
....
As shown above I do not care what they do while being signed in. I just care about adding records to that specific table. (TableA) For example user 2 is active but does not add any
record to tableA so receives the message once his timer reaches to 5 hours.
I've found the following except, but suppose it is not useful, as once I run it in user's class, it is not possible to get back to the same class and reset it.
Timer timer = new Timer();
int startingTime=10000; //millisecond 10 seconds=10000
int delayTime=1000; // millisecond 1 second
timer.schedule(new TimerTask()
{
public void run() {
System.out.println("Timer repeat statement");
}
},startingTime,delayTime);

Since you use java-ee and struts, I assume you are talking about web-app.
So use standard session management. Implement HttpSessionActivationListener to init the timer on session start, and set your session time out to 5 hours. When session expired, run you code.
You need to implement session-scope bean to check this, and reset the timer with a method called from your service layer to this bean, when a record to specific table performed.
Also you have to check timer associated with current session in your JSP to check if you need to display message.
E.g. you created TimerBean - some bean with session-related timer to check from JSP.
1.
public class SessionListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent arg0) {
//init your timer in TimerBean and associate it with created session
}
#Override
public void sessionDestroyed(HttpSessionEvent arg0) {
//check your timer value and run you code if it's necessary
}
}
2.
#Startup //use eager initialization, or call init from login page
#Singleton // singleton session bean
public class YourDbTableSessionManager {
#Resource
private javax.ejb.SessionContext
void writeToDb {
//reset your timer in TimerBean for SessionContext
//perform write
}
}
3.
web.xml
<web-app ...>
<listener>
<listener-class>your.package.SessionListener</listener-class>
</listener>
</web-app>

Related

send data to server every minute (For check status user)

For check status user i should send some data to server every 5 minutes with retrofit2.
Of course, this information should be sent when the user is in the app
This means that when the user is out of the application, there is no need to send something to the server
What is the best way to do this?
For connection to server i use retrofit2.
One solution is to use Android's work manager to ping your server with http request. You can create initial OneTimeWorkRequest when user logins and with in each execution create a new OneTimeWorkRequest with 5 minutes delay. When user exits the app cancel all the work request.
See the Jetpack Library: https://developer.android.com/topic/libraries/architecture/workmanager
Another solution for which you need to make changes in your architecture is to use Sockets with library like SocketIO. Connect the socket from your app when user login notifying server that user is online. When socket disconnect server can mark user offline: https://socket.io/blog/native-socket-io-and-android/
One other solution is to use Firebase Realtime database for presence system. Firebase has nice example of how to do this: https://firebase.googleblog.com/2013/06/how-to-build-presence-system.html
You can write this code in service and make network call every 5 minutes using handler or RxJava;
public class YourService extends Service{
public final Handler handler = new Handler();
#Override
public void onCreate() {
makeCallEvery5Min();
}
private void makeCallEvery5Min(){
runnable = new Runnable() {
#Override
public void run() {
// execute call here
}
handler.postDelayed(runnable, delay);
}
}
}
RXJava
private void makeCallEvery5min() {
Observable.interval(0, 5, TimeUnit.MINUTES)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(v -> your_network_call() );
}
May help you below approach
If user is log in, should have user id.
Now try to check for user id of particular user in user log in session.
Note: below code should be added in web page(jsp or servlet)--.
Single User Approach:if(userId==Session.getUserId(userId)){response.refresh(5);//write code to send data to server using retrofit2.}
MultiUser Approach: multiple users log in.if(Session.getUsers()!=null){response.refresh(5);//write code to send data to server using retrofit2 }

HashMap in CustomAuthenticationProcessingFilter

We have an existing Spring Boot Security structure which uses CustomAuthenticationProcessingFilter with some other filters and database to login users.
The requirement is that each user should not be allowed to login for 30-60 sec once an attempt is made. We are not yet clear if the attempt must be successful or not.
We are thinking of using HashMap to record username (which is unique) with the attempted login timestamp.
If the user is not in the HashMap just add the username in it and go ahead with login. If the user is in HashMap check the timestamp and if this attempt is withing 30-60 sec, just exit from filter. This will not go through login process.
private static HashMap<String, DateTime> loginMap = new HashMap<String, DateTime>();
...
...
if(user not in map) {
put the user
}
else if(user in map and time difference > 30-60sec) {
change timestamp;
go ahead to login;
}
else {
exit without changing time;
}
Sometimes the login attempts are 4-5 times for 1 sec. As the HashMap will be accessed by many threads, how stable is this solution? Only first thread will add in HashMap and others will read it.
Is there any other structure or solution we can use?
Thank you very much for your help.

Spring : Send automated email to member and admin after timer expires

I am working on a Spring-MVC application in which there is Service desk functionality I am working on. So, as a part of Service desk, users can create issues and assign a support-team member. In that, they can also assign in how much time issue needs to be resolved. I am setting the time in java.sql.TimeStamp.
Now, when the time expires, I would like to send an email to the support-team admin, the person who created the issue and the support-team member responsible for resolving the issue.
If it was a normal scheduled or cron job, I can just write a #Scheduled method and get it over with, but here, I would like to check for example after 6 hours if the issue was resolved or not. How do I accomplish that? I have no idea to be honest.
Here is service layer part the SupportRequest :
#Service
#Transactional
public class SupportRequestServiceImpl implements SupportRequestService{
private final SupportRequestDAO supportRequestDAO;
#Autowired
public SupportRequestServiceImpl(SupportRequestDAO supportRequestDAO){
this.supportRequestDAO = supportRequestDAO;
}
#Autowired
private SupportTeamService supportTeamService;
#Override
public int addSupportRequest(SupportRequest supportRequest, int assignedTeamId, Long groupId) {
SupportTeam supportTeam = this.supportTeamService.getSupportTeamMemberById(assignedTeamId);
if(!(supportTeam == null)){
supportRequest.setCreationTime(new Timestamp(System.currentTimeMillis()));
supportRequest.setAssignedTeamMemberId(supportTeam.getTeamId());
return this.supportRequestDAO.addSupportRequest(supportRequest,groupId);
}
return 0;
}
}
I don't know what else to show. Thanks a lot.
Update
Will something like this work?
long delay = 1000*60*60*12; // after 12 hrs
Timer timer = new Timer();
Calendar cal = Calendar.getInstance();
timer.schedule(new TimerTask() {
public void run() {
// Task here ...
System.out.println("inside the main");
Integer id = new Integer(10);
Assert.assertNotNull(id);
}
}, delay);
For these kind of scenario, there should be background process running. That process will check for issues that has not been fixed in given time. Then this process will send a message to whoever you want and then continue running in background.
There are different ways of doing this.
1. Batch Process
You can make batch process. Batch process will be running on your server, it will check for expired issues and then send mail to the support-team admin.
2. Techniques for Real-time Updates
You can also you real time update techniques in spring. Using this technique you will fire request after every given period that will check for expire issues. If any issue found that has not been fixed you can send mail. Please read the related document here : Spring MVC 3.2 Preview: Techniques for Real-time Updates
3. Web Socket
Web socked can also be useful for these kind of task. Find the good source here :
SPRING FRAMEWORK 4.0 M2: WEBSOCKET MESSAGING ARCHITECTURES

How to Delete data from Database upon closing the browser

When a user logs in to my web app, I create a session:
session.setAttribute("SessionNumber","100");
And his username is added to a table named ONLINE_USERS.
Other Online users will be able to see him, they see all online users
When the user clicks on the log out button, I delete that row from the table, then I delete the session using:
session.invalidate();
But let's say the user existed the browser, his session will be gone, but the row will stay in the database as an online user, how to avoid this?
I'm using JSP-Servlets on Netbeans.
You can enable a custom HttpSessionListener to delete the table row upon session invalidation.
public class YourHttpSessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
//put row in the database
}
public void sessionDestroyed(HttpSessionEvent event) {
//delete the row from database
}
}
Declare the listener in your web.xml:
<listener>
<listener-class>YourHttpSessionListener</listener-class>
</listener>
Note that there will be a delay between the moment the user exits the browser and his session expires on the server. But session expiration time is configurable. You should find a suitable expiration timeout: not too long so you don't display for too much offline users as online, but not too short to allow connected users an idle period.
I think this is a good trade off for a chat application developed with basic servlet and jsp technology.
As I understand you want see users that are operating on web site at the moment, problem with HttpSessionListener is that session can live quite long before its destroyed, so it can happen that the user is not using the web site long time when it is destroyed.
(see http://www.smartsoftwarebits.com/qaa/46-misc/82-how-to-set-session-timeout-for-tomcat )
Solution: You can add a column to the database where you will store the time stamp of the last request
which user made. To keep this column up to date use a servlet filter. ( http://docs.oracle.com/javaee/6/api/javax/servlet/Filter.html )
To clear online users add a timer job (for example using quartz) where you will delete rows (online users) that are older than (for example) 5 minutes (thus when last interaction is older than 5 mins.) ( http://quartz-scheduler.org/ )
Using this you will now quite precisely if there is user is "still there" or not.
In addition you can add a timer to client side javascript to make an ajax call periodically. You can handle this way the situation when user did not close the browser just were inactive for a while.
First thing is to catch the event when the browser is closed
You can try below code snippet in your jsp to hit a js function which will call an ajax function to hit server side component. Then simply use the session API to invalidate the session and add the code to delete the record from the table.
window.onbeforeunload = WindowClose;
function WindowClose() {
//Write a AJAx request here to hit the server side servlet to invalidate the session
}
Or use
<body onunload="WindowClose(); >
In the server side code , use
HttpSession session = request.getsession();
session.setMaxInactiveInterval(0); //or session.invalidate();
It will be good approach to define default session timeout value in the web.xml so that incase browser crashes, sessions will invalidate after the stipulated amount of time has passed.
<session-config>
<session-timeout>30</session-timeout>
</session-config>

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