I'd like to update user session attributes (for example, user's money amount) every 20 minutes. How can I achieve this? Any ideas?
Your problem has two distinct parts:
How do I update user session attributes whenever I want to?
How do I do something every 20 minutes?
For the first part, you just need to keep a collection of all current sessions that you can access from anywhere (i.e. without the need of having an HttpServletRequest). This is answered in this post:
How do I get a list of all HttpSession objects in a web application?
For the second part, your best fit is probably a ScheduledExecutorService. See also: Running a Java Thread in intervals
You can use Timer Service for this task.
If you use Spring you can try TaskExecutor
Related
i use the latest Acitiviti 5.22.0 engine (to be more concrete i use Alfresco Process Services 1.6.3) and i have implemented a Spring bean that gets executed every 10 minutes to generate a JSON representation of all my processes (process name, startDate, endDate, current taskName(s) and assignee(s)), to send them to an audit server. The problem is, that i only need to send all changed processes since the last run.
I do not want to send the JSON as soon as a process changes but to do a batch update of my audit system every 10 minutes.
To accomplish this, i've tried different approaches. My latest one:
Create a event listener bean that listens to all PROCESS_STARTED, PROCESS_COMPLETED, PROCESS_CANCELLED, TASK_COMPLETED, ...
Every time the event is triggered, store a process variable "_dirty" and set it to true
Every 10 minutes (wenn my JSON-bean is executed) query for all processes with the "_dirty" variable set to true
After sending the JSON to the audit system, set all "_dirty" process variables to false.
The problem with this approach: I am not able to update the "_dirty" variable after a process is ended. At least i don't know how.
My second approach would be to to store the processInstanceId on every event into a "global" property, but i don't know how to store this "global" property into database in case the server restarts. Is there a way to persist a property or an Entity into DB without creating an extra table, DAO, etc.?
Any ideas on how to solve this task? All tips are very much appreciated!
AFAIK, There's no such option
But you look at this. and see if it can be helpful in your case.
https://www.activiti.org/userguide/#_database_tables
As Linus suggested: This is not possible, so I needed some completely different approach.
I am creating an Ad-Hoc task now and store my properties as a local task variable. The Ad-Hoc task is owned by a system account and not assigned to anybody. This way I can make sure, no one of my real users tries to "complete" the task. Also I've written some code to generate the task if needed, so in case i want to clean it, it is created automatically the next time i want to store data.
Creating an Ad-Hoc task is quite easy by using org.activiti.engine.TaskService autowiring into my class.
Task task = taskService.newTask();
task.setDelegationState(DelegationState.PENDING);
task.setName("Some name goes here");
task.setTenantId("your tenant id (if any)");
task.setOwner("your system accounts ID");
task.setCategory("i use a special category to later query for the task");
taskService.saveTask(task);
After saving the task to the database, I can use the taskService to store and retrieve variables like this:
taskService.setVariableLocal(task.getId(), "variableKey", "variableValue");
Or query for the task like this:
Task task = taskService.createTaskQuery().taskDelegationState(DelegationState.PENDING).taskCategory("your special category").singleResult();
Not a very nice solution (I recommend having the task cached in a bean or something, so you don't need to query it all the time or even cache its values or something), but it works.
I'm implementing a web application using java (jsp). Now I'm adding some configuration buttons into the application, and i need to know which is the best strategy to persist them.
For example, I need to add a switch which will tell if each 10 jobs with errors the main worker must be stopped. It is a boolean variable called "safeStop". For that i need to persist if that config value is activated. This persistent value must be there even if the server is reset so it is not enought to persist it on RAM, it mus be persisted on disk.
This application will process thousands of works at day, so I need a safe and efficient way of persisting configuration.
I can't find any coherent info about different strategies of doing this and which is the best option. Any help or strategies will be helpful.
Thank you
I think the best practice would be to keep all the conf variables in a database and set a cookie on client side if that data needs to be processed. Once operations are performed update the values on server on session end or after a certain time or data volume or at the end when all processing operations are complete. This way you'll achieve performance, store information on something besides ram while using the RAM for shorter transaction operations
I am doing geoquery among 300 user entities with a result range 10.
I've maked a query for 120 times. For each query I got 10 user entity objects.
After this my app engine read operations reached 52% (26000 operations).
My user entity has 12 single value properties and 3 multi-value properties(List type).
User entity have 2 indexes for single value properties and 2 indexes on list type properties.
Can any one please help me to understand how google's appengine counts the datastore read operations?
As a start, use appstats. It'll show you where your costs are coming from in your app:
https://developers.google.com/appengine/docs/java/tools/appstats
To keep your application fast, you need to know:
Is your application making unnecessay RPC calls? Should it cache data
instead of making repeated RPC calls to get the same data? Will your
application perform better if multiple requests are executed in
parallel rather than serially? The Appstats library helps you answer
these questions and verify that your application is using RPC calls in
the most efficient way by allowing you to profile your RPC calls.
Appstats allows you to trace all RPC calls for a given request and
reports on the time and cost of each call.
Once you understand where your costs are coming from you can optimise.
If you just want to know what the prices are, they are here:
https://developers.google.com/appengine/docs/billing
You can analyse what is going on under the hood with appstats: https://developers.google.com/appengine/docs/java/tools/appstats
I've been researching how to fix this issue for sometime but can't seem to find a proper solution.
Here's the issue:
I have a Java EE application where many users can login, they are presented with an item list, and they can select and edit any one of those.
All users see the same item list.
As mentioned, they can edit an item but I'd like to restrict the editing function to one user. That is, many users can edit different items simultaneously but only one user can edit a particular item.
When one user is editing an item, an message should appear to any other user trying to edit that item.
I have implemented this by setting a flag on the item, inUse, to true and then check for that. When the user is done editing the item, either by clicking save or cancel, the flag is set to false.
Problem with this approach is to account for cases when the user leaves his browser open or the browser is closed.
I tried setting a session timeout but can't seem to make that work because when the session times out, I don't have access to that item. I only have access to the httprequest session id.
Perhaps this is the wrong approach since it seems it's an issues that many applications would have and a less hackie solution should exist.
I looked into using threads and synchronized methods but don't know how that would work because once the user enters into the edit item screen, the method exits and releases the lock.
I found this solution Only one user allowed to edit content at a time but not sure if that's the way to go in Java.
Is there a more elegant/java solution? If so can you point me in the right direction please? How would you implement this?
Thanks!
The solution:
Although originally I thought optimistic locking was the way to go, I quickly realized that it wouldn't really work for my environment. I decided to go with a combination of pessimistic locking (http://www.agiledata.org/essays/concurrencyControl.html#PessimisticLocking) and timeouts.
When an item is accessed, I set an inUse field to true and the object's last accessed field to the current time.
Everytime when somebody tries to edit the object, I check the inUse field and the lastAccessed field + 5 mins. So basically, I give 5 mins to edit the user.
Do it like they do in a database, where a timestamp is used. The timestamp is kept with the record and when a person submits his edit, the edit does not go through unless the timestamp is the same (meaning 'no edits have occurred since I read this record'). Then when the edit does go through, a new timestamp is created.
First of all, in your persistence layer, you really should be doing optimistic locking, using a version/timestamp field.
At a UI level, to handle your use case I would do resource leasing:
Add two fields to your table:
LAST_LEASE_TIME: Time of the last lease
LAST_LEASE_USER: User that leased the record for the last time.
When a user tries to edit your record, first check that the record is not leased, or that the lease has expired (that is, the lease is not older that the specified lease time) or that the user is the one that was granted the lease.
From your web browser, periodically renew the lease, for example with an AJAX call.
When the user ends editing the record, explicitly expire the lease.
By doing leasing, you solve the "closed browser" problem: after the lease period expires without any lease renovation, the algorithm automatically "releases" the resource.
Sounds like you could use : Session Beans Quote:
In general, you should use a session bean if the following circumstances hold:
At any given time, only one client has access to the bean instance.
The state of the bean is not persistent, existing only for a short period of time (perhaps a few hours).
Martin Fowler describes 4 patterns for such a problem:
Online Optimistic Locking
Online Pessimistic Locking
Offline Optimistic Locking
Offline Pessimistic Locking
You should decide which one to use according to your problem.
JPA, JDO and Hibernate provide 1 and 2 out of the box.
Hibernate can handle 3 too, (I'm not sure about JPA and JDO).
None handle 4 out of the box and you shall implement it yourself.
I am building a web application that has a top thin frame which should show the time in seconds in which the servlet session will timeout.
The problem is that a AJAX call to a servlet which returns the last access time, and the inactiveInterval itself updates the session.
So is there a way I can get information about the session via a servlet that does not incrementing the lastAccessedTime?
Thanks
It seems that no one really answered the question as asked. The last response is closest - and probably best - piggy back the information needed on another request. I would add that if you can count on XHR activity that you can set a response header with the value(s) you want.
Assuming you really want want you asked for - to summarize / restate - a servlet that participates in the session but doesn't update the last accessed time, you should be able to accomplish that with a Filter that chains an overriden HttpServletResponse that returns an overridden Session object - overriding the getLastAccessedTime() method with its own (stored as an attribute in the real session of course). It will probably need to perform its own manual invalidation of the real session.
Questions like this show the age of the Servlet specification, even in its latest forms, there isn't enough control of some of the low-level authentication mechanisms, and overriding can be difficult even with Filters. These limitations manifest themselves using technologies like AJAX.
In thesis, you should not relay the session expiry time on the session time itself, in your case a counter should be implemented by decreasing the login time from the current time.
RemainingTime = CurrentTime - LoginTime
Your ajax call should query this variable.
Hope that solves your problem.
Can I ask for some more details?
What is the real requirement? Is it that the session time out within x seconds of a user logging in?
In that case, you you can use the getCreationTime() method on the HTTPSession object
http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpSession.html#getCreationTime%28%29
remainingTimeInMilliseconds = System.currentTimeMillis - session.getCreationTime()
OR
Is the requirement for the session to time out after x seconds of inactivity? If so then do a
remainingTimeInMilliseconds = System.currentTimeMillis - session.getLastAccessedTime()
There's no need for your top frame to ask the server for the last access time. Why not let every HTML page contain a JavaScript snippet, which sets a defined variable to either last access, or perhaps more convenient, set the variable to the assumed expiration date of the HTTP session. Depending on how you generate your web pages, you can add the code snippet to a default template, or perhaps even add a Filter, which will embed the required code on every HTML page.
Be aware though, that IMHO, the servlet specification only states, that the server may invalidate the session at some point after the expiration time has passed, so accessing the session after the expiration time is not guaranteed to fail.