How would you implement a constantly running service in Java EE?
What I'm trying to do:
User1 connects to a service pool; waits for response.
User2 connects to the same service pool; waits for response.
Server performs task (matches users) on all Users in the service pool.
Server returns response to appropriate Users once they have been matched; if User1 matches with User2, User1 receives User2 as a response and User2 receives User1.
I'm not asking how to perform the task (match). I'm asking how to a have this server service run as long as there are Users in the pool?
In Java EE, there seems to be no independently running method support. The only things I can think of are:
Infinite loop on a separate thread
Timer Service
I'm wondering if there is another/better way.
For running a process under the hood you're actually right. Can use infinite loop or Timer Service. Take a look at Quartz as well. You just need to register users in some kind of thread safe collection.
For realtime updates you can't be sure that HTTP request will wait long enough. May just timeout. You need to use WebSockets or CometD to abstract publish/subscribe channel. You should use a Java EE server that accepts asynchronous HTTP requests (i.e. suppports Servlet 3)
You have inded 2 different problems :
you want different sessions to interact with each other
you want the server to send its response once it could match users
For first part, you could put a specialized bean or object in ServletContext in which sessions will register their users and from where they will get matching users. If you want to allow bidirectionnal exchanges from that time, you can use some kind of pair of buffers where one session writes where the other reads. You should also use a SessionListener to unregister a session as soon as it is closed.
For second part, you must be aware that you cannot hope that a HTTP connection will live as long as you need it. Even if neither the server nor the client have a short timeout, you might go through any other network equipement (proxy, router, ...) that can close it without further notice. IMHO the most robust way would be to have a page that automatically refreshes itself via javascript, a HTTP Refresh header or a <meta http-equiv="refresh"> tag.
Related
I am learning socket and server/client model concept and having a hard time understanding the server client concept. If a client sends a request, can server sends more than one respond? Or we have to put everything in one respond?
For a memory game program, when a client click a card, the action will send a request to server in order to turn the card in every player's program, if the second card does not match, the server tells players wait 2 secs, turn the 2 cards back, and then assign turn to next player. Can a server does this in multiple responds or it has to do it in single respond? Since no client requests for some responds, so I don't know if it is achievable or not.
If you're talking about TCP connections, after the connection has established client and server are equivalent, both are free to send data as long and as much they like and/or shut down their end of the connection.
Edit: After several passes I think i have understood what the second paragraph of your question is aiming for.
There is, of course, nothing which would stop the server from doing anything.. What your server seems to do, most of the time, is blocking on a InputStream.read() operation. If you want the server to operate even when no network input happens, one solution might be to use a read timeout, or check the input stream for readability before actually reading.
This is not your complete answer.
For one request, you get one response back.
Please read on this information in wikipedia for the basics
"Request-response, also known as request-reply, is a message exchange pattern in which a requestor sends a request message to a replier system which receives and processes the request, ultimately returning a message in response. This is a simple, but powerful messaging pattern which allows two applications to have a two-way conversation with one another over a channel. This pattern is especially common in client-server architectures.1
For simplicity, this pattern is typically implemented in a purely synchronous fashion, as in web service calls over HTTP, which holds a connection open and waits until the response is delivered or the timeout period expires. However, request-response may also be implemented asynchronously, with a response being returned at some unknown later time. This is often referred to as "sync over async", or "sync/async", and is common in enterprise application integration (EAI) implementations where slow aggregations, time-intensive functions, or human workflow must be performed before a response can be constructed and delivered."
The scenario is the sending of a password reset mail to the user from a web request (and possibly other mail related tasks in the future).
The arguments I bring to the table for queuing:
I believe web requests should be handled as fast as possible
Decoupling the send action from the request, more easily allows externalization of the mail system (if required in the future)
The arguments I recognize against queuing:
The user does not get feedback if something goes wrong during the sending of the message
What are more arguments in this discussion? And to those in favor of queuing, how would you implement the queue? Scheduled action? Infinite dequeuing task (with interval, of course)?
Thanks!
I would suggest you to decouple actual sending of mail from your app business logic.
Do this asynchronously: Use queue or at least different thread for sending such notifications.
Sending of email could be time consuming operation,
even if you use your own internal mail server which is close to your app.
SMTP conversation consists of several requests/responses.
Do not treat sending of a mail as a transactional action.
When target SMTP server replies with 250 OK as a response for DATA command - it just takes responsibility for this mail nothing else.
Delivery could fail in future if next server in the chain is not able to deliver mail (read about DSN, aka bounce).
Last but not least think about failure modes.
What if your business critical functionality is slowed down / blocked by auxiliary one (email notification), not good I guess.
You definitely don't want to do the send synchronously since the mail server may be slow.
Send a JMS message and use an MDB to send the email.
In a Java EE 6+ scenario you can use #Asynchronous annotation in a EJB method. It returns a Future<V>. So you can continue with proccesing and ask later for task ending, while it is executed in another thread.
So you can accept a lot of request fastly, you decouple the send action from request, and you can get feedback.
http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html
You may think that requests should be serviced as fast as possible, but what about the user? What does he think?
The user needs his password reset. He doesn't care how long that takes. If he can't complete that request he can't do anything at all.
Don't queue.
I think u should go to queue. Because it help in fast performance and to check whether the password reset request is arrived from correct source.
So u can use Map for queue implementation. Because in map u can use email id as key and a unique request reference as value. And this map element should be deleted within a time period.
Also for fast email service u can create a simple thread class that send emails and start a new thread by passing some data arguments in it. and scheduling will automatically managed by web container for these threads.
The application we are building has a very simple concept: it receives incoming events from a Database and for each event it opens an interactive session with clients (in the event) by showing a menu. Based on client response, we move to the next state or take some concrete action (e.g. transferring funds).
Sessions are independent of one another. For example, suppose we get two events from the database saying clients A and B have reached a zero account balance state. In response to this event, we establish two connections to A and B show a menu which looks like the following:
Please select an option:
1. Get $5
2. Get $10
3. Ignore
For options 1 and 2, we ask for confirmation in the form of second menu.
Are you sure?
1. yes
2. no
In this case, we'll have two sessions. Client A might choose option 1 (1. Get $5), whereas Client B chooses option 3 [in the first menu]. In the case of Client A, we'll present the second menu (above) and if the response is 1. yes, we'll take some concrete action such as transferring funds and closing the session.
All client communication is done by a 3rd party system which takes JSON including client address, menu text and returns a response back to us. It takes care of actually maintaing the session on the wire, whereas we only need to do response correlation and dealing with session states.
We're expected to handle 50,000 of such sessions in parallel.
Earlier, we designed the system in Java using SEDA model. Having heard of Actors, we are willing to check them out and write a quick PoC project (Java/AKKA). My questions are:
Has anyone had experience in building such kind of an application? Is 50,000 simultaneous sessions too much for AKKA to handle? (Note, we are only waiting for the response. When the response comes, based on the answer, we jump to the next stage, so it should be possible).
Which architectural stye/paradigm which best suit this problem in AKKA? Are there any frameworks out there for this kind of problem?
This is actually a reasonably easy use case with Akka's clustering. 50K sessions represented as an Actor instance for each is not very high load. The reason to use clustering is only for fault tolerance.
The idea behind the architecture would be to have a web tier for handling RESTful requests that correspond to the sessions. These requests would be sent to the Akka cluster and routed to the appropriate session Actor by session ID, or a new one would be created. When a session is done, you stop the actor that is associated with it.
Note that the session actors should send themselves timeout messages via the scheduler. Upon completion of handling a new message, the actor should schedule itself a message via the ActorSystem scheduler for 15 minutes (or whatever your timeout is). When a new session message is received, that scheduled task should be cancelled, the new update handled, and then a new timeout scheduled. There is a plausible race condition here, in that a timeout message may be in your session actor's mailbox queue AFTER a session message, but if your timeout message includes a time of when it was scheduled (the 15 minutes ago), you can check that and ignore it and reschedule another (just as a safety mechanism to avoid a memory leak). If the time is greater than 15 minutes ago, then you stop the actor.
To see how the distribution of work to the session actors would be implemented, please see the "Distributed Workers with Akka and Java" template in Typesafe's Activator. You will have a fully running clustered Akka application that you can tailor to do the session management as I've described above. You can then export the project and work on it in Eclipse/IntelliJ/Sublime/TextMate/etc. To download Activator, see here.
I know that every request is served by a servlet thread, but will it be possible for one user session, two request served by two different thread?
If the situation above really happens, what about thread local variable stored by first request-serving thread be read by second request-serving thread?
I'm afraid that if I store user credential in Spring Security's SecurityContextHolder(which uses thread local variable) in first thread, the second thread will not be able to access the user credential...
I know that every request is served by a servlet thread, but will it be possible for one user session, two request served by two different thread?
Yes, that's possible.
I'm afraid that if I store user credential in Spring Security's SecurityContextHolder(which uses thread local variable) in first thread, the second thread will not be able to access the user credential...
Security is established separately for each request by Spring, you do not have to handle this yourself.
No, one request will not be served by several threads. What can really happen is serving of 2 requests by one thread. This is the reason that you should be very careful using thread local variables yourself. However you can trust Spring framework: it does things right. It can for example use session or request ID when using thread local, so 2 request being processed by one thread will not be confused.
Two separate requests of the same user are handled (most likely) by two different threads.
I am not sure what Spring does, but the Servlet api provides a way to retrieve data that is specific to the user session (how the server tracks the session is irrelevant, but have a look at cookies and url rewriting).
Now, If I wanted to have the user credentials on a threadlocal variable (which is not unusual, as the ThreadLocal pseudo-singleton is the most convenient way of injection I know), I would store them on the users HttpSession (which is persistent across all requests of the same user) and use a servlet filter to put them on the threadlocal at the beginning of each request.
I hope this makes things a bit clearer for you. I find it is better to know what's happening under the hood even when using the most up to date framework :)
What is the best way to perform long tasks (triggered by a user and for that user only) in a java web app? I tried using ejb #Asynchronous and jax-ws asynchronous (polling) calls but the Future<?> they are returning is not serializable and could not be stored in HttpSession (to retrieve the result later when it's done). Is there a simple way to use concurrent Future<?> in a java web environment or do I have to go with a full-blown jobs management framework?
Best solution so far was to use an application-scoped Map<SessionId, List<Future<?>>>. This works in cluster with sticky sessions and does not need to use JMS queues and storage of result in database.
The best is to use JMS . Implement a messaging solution which is asynchronous which sends a message to a queue/topic where a MDB listens to that queue / topic to be triggered upon the message arrival to perform the long task in an offline manner
http://www.javablogging.com/simple-guide-to-java-message-service-jms-using-activemq/
http://docs.oracle.com/javaee/1.3/jms/tutorial/
If your process is supposed to generate a result and you are expecting the process to take a long time, probably the best way is two have 2 separate calls:
First one to trigger the process and which return a unique process identifier
Second one to retrieve the result using the process identifier
So your overall process flow will be:
Client call back end service.
Back end service starts async process with unique id and return the unique id to client right away.
Async process persist the result in session or other more persistent mechanism (db, file, etc.)
Client side poll server with unique id
Retrieval method return result when exist, otherwise return not done message