Is Spring Rest Controllers Singleton? - java

I have a sample Spring Rest application.
I have several clients accessing an API in the Spring Rest application. The API checks whether a job has started or not against the MSSQL DB that we use.
If the Job status in DB is in started status, it will pick the record and update its status to inprogress and return the details of the Job as the response to the API and based on that the client will do some processing.
We have observed that, more than one client is picking up the same Job which is in started status and updates it to inprogress and pass the response to the client. So, it ends up like the same job is being processed by multiple clients.
We tried to resolve this by adding a synchronized block and enclosed the DB call that picks the record in started state and update it to inprogress. The DB call resides in the service layer. But still the duplicate issue is there.
If the controller and the subsequent layers like service and DAO layers are singleton then, when multiple API calls hit the web app, the synchronized block of code should be executed by one request at a time. But that is not what we see practically.
Could someone please help to resolve this issue?

Actually Rest Controllers are Thread Safe it means it is capable of handling each HTTP requests unique. Also when you try to access the Rest Controller it creates a separate session id in browser you can also check that using developer console. Here you are trying to access same DB and change the status as inprogress, so there is a chance for the next api to fetch details of the previous session.. so try to modify the Rest API without modifying status in DB every time or you can do something like, if the DB is accessed by one API then the other API should not be able to access DB until the first connection is closed. Hope this can work for you.

Related

Spring session lazy deserialization

I have the following situation, i have a microservice architecture with an api gateway and multiple downstream services, some of these have an independent session and this causes my system to throw expired session exception on random service calls.
Since we cannot rewrite these services from scratch we started by introducing hazelcast so that all services can share the same session.
the problem now is that when a service writes an object of a class that other services don't have in their classpath a deserialization exception is thrown.
to solve this i was thinking that if only the attributes that get accessed from a service get deserialized i could probably avoid the exception and everything should work fine.
Do you know if this is at all possible with spring session, or maybe can suggest another solution that would allow me solve the initial problem?
here is a sample project to reproduce my problem: https://github.com/deathcoder/hazelcast-shared-session
I believe I got what's happening: Spring-Session-Hazelcast by default store session updates locally until request completed & when request completed, before returning the response, send everything to the cluster using EntryProcessor. EntryProcessor requires object classes available on the member who stores that session record and since data is distributed, it's possible some other member stores a session created in another instance. According to what you're saying, not all nodes are identical, don't contain all classes & this causes serialization exception.
What you can do, you can use User Code Deployment feature to deploy those missing classes to other members: https://docs.hazelcast.org/docs/3.11/manual/html-single/index.html#member-user-code-deployment-beta
If you're changing object that you're storing in the session, you can set class-cache-mode to OFF to prevent not caching them but sending with each operation.
Please try & let me know if this solves your problem.
I would try to avoid sessions in the API layer in the first place. They scale poorly. And synchronizing sessions is even less scalable.
Try using access tokens instead, for example a JWT token. A token should contain enough user identity information to load the resources necessary to process the transaction (the resources can be cached).
As for the other state in the session - microservices are self-contained from the process perspective, so all intermediate results should be persisted to the database. But of course I don't know the details of your particular application, so this is just a general thought.

Per user level synchronization in Spring MVC

I am designing an upload functionality with Spring MVC. All uploads from the client reach an endpoint which handles an ajax call. The controller that is mapped to the endpoint calls a function in a "#Service" class.
This function does the actual upload by uploading it to my cloud file system, and modifying a session variable. The problem is that it takes a while for the upload to be completed. Thus, the time for my controller to return prolongs. I want my controller to return right away by starting a thread to handle the upload and then return. If multiple uploads from the same client call the endpoint at the same time, I want to ensure a synchronized access to the session variable, how do I do this?
Spring uses servlet technology, different thread is created for each request on a servlet ( not different instances ) so what you really want to accomplish regarding the threads is already done.

Send a message from Server to All Clients

I know I don't have any code to show you guys, I am stuck at some point and I dont know where to start. I hope someone will help me.
I am developing a Spring MVC application, and I need to send a message to all active session users to execute a script which is available to all the clients as it is defined in a js file and included for every user.
I have looked around and found some frameworks which offers these type of functionalities like Atmosphere but I don't think it should be used in my situation as it is a big framework and the functionality required is very little. I have also gone thorough WebSockets but I cant find anything which would help me in invoking the script on client side for all the clients.
If someone can help me go to a right path or direct me to a similar example. I will be grateful
****Update****
I can also use polling if there is way that: if the controller gets a request the session should be considered idle during that, for instance, there is controller which is called every 5 minutes and in the session out time is 30 minutes. The session won't expire in this time if the controller used for polling is called every 5 minutes, I need to exclude the particular controller from calculating the idle time
No Polling Solution:
From what I gather, you need a Remote Procedure Call mechanism.
I would go with https://github.com/eriksank/rpc-websocket.
The general idea:
Your clients register themselves to your server process as "consumers".
When a message is ready, your server then goes through every registered "consumer" and sends the message which rpc-websocket can handle .
Polling Solution:
Here is a general idea, works if you have registered, logged on users.
Have a database table that stores messages, lets call it "messages".
Have a database table that keeps track of messages and users, lets call it "message_tracker". if a user has seen a message, there will be a row in this table for the messageId and UserID.
Have a javascript script poll a server url for new messages. What is a new message can be decided based on the database tables above.
If a new message is found, process it and then call another server url which inserts into the message_tracker database table

Online application calling Web service

In an application where there are say 1000 simultaneous users, would it be advisable to call a web service as a part of the request or fetch data from web service offline using a job and store it in your database?
I am confused between these two options:
1) Call the web service as a part of your request: user clicks link, page submits to controller, web service called (substantial data is fetched). Data is displayed to user.
2) Create a timer bean/ batch job that calls the service every 15 minutes and fetches data updates for all users, update the database. User may not see latest updates(updates will be 15 min old) but this is acceptable.
Wouldn't way 2 allow for better performance always? Is there a situation in which calling online service may be more advisable?
Finally, if both the service code and client code are java, would you rather use JNI-RMI instead of web service ?
Both 1 and 2 should be combined in final approach with Cache as solution to fetch/update data
1) Offline job updates the Cache in Web Server by fetching data from database
2) When user call Web service, data will be rendered from Cache instead of database.

Is there a way to explicitly commit and rollback transaction after several client&server submit

Environment: The application is using Spring Framework 2.5.6.SEC01 and iBatis 2.3.4.726. It is MVC design.
Here's the scenario:
Input/update data from the client
Press Update button to submit
Process the data and execute DML (insert, update, delete)
Back the result to client and display the data
However, upon the page loaded, I need to call the API via Javascript (i have no control with the API, just need to pass the required parameter and check the result if SUCCESS or ERROR)
If API returns SUCCESS, nothing to do. But it returns ERROR, I give alert message to inform the user.
I have View(client), Service and Data Access Layers. When the client do the submit (scenario #2), it enters the Service to process the data and automatically start Transaction (scenario #3). Automatically execute the commit upon exit to Service and back to client to show the data (scenario #4).
Problem: How can I suspend the transaction not to execute the commit, then back to client to call API via Javascript. When API returns SUCCESS, execute commit via Ajax (or other way) or in the other hand, rollback it.
Any guidance on the right direction is appreciated.
If I understand correctly, you want to start a database transaction, insert data (without comitting), keeping the connection and the transaction open, return to the client, and based on some javascript result, do a commit.
This feels like a strange design where the client can actually keep a connection open, making your application extremely vulnerable for (D)DOS attacks or client problems in general.
I would try really hard to remodel it as follows:
Upon submit, call the javascript you need to confirm the commit/save action
When the javascript succeeds, do the submit to your own server
Do normal Connection/Transaction handling within the DAO, not exposing transactions to the client.
This is quicker, more robust and also probably less code.

Categories

Resources