Attendre un évènement en base de données dans une servlet - Java - Programmation
Marsh Posté le 05-01-2004 à 17:20:51
public Object lock = new Object();
synchronzied(lock) {
lock.wait(1000);
}
Marsh Posté le 05-01-2004 à 17:56:29
sans oublier le
synchronzied(lock) {
lock.notify();
}
Marsh Posté le 05-01-2004 à 18:01:25
bin si il doit le réveiller avant oui
Marsh Posté le 05-01-2004 à 21:41:17
euh une servlet qui repond pas avant 1 minute, z'etes gentil mais le browser il va partir en timeout. j'espere.
problème de design à mon avis.
passer par une applet si vraiment necessaire.
Marsh Posté le 05-01-2004 à 21:47:32
the real moins moins a écrit : euh une servlet qui repond pas avant 1 minute, z'etes gentil mais le browser il va partir en timeout. j'espere. |
c'est clair qu'il y a un problème de design hein
le wait(1000) c'est 1 sec hein si c'est de ça que tu parles. Sinon
Citation : |
Marsh Posté le 05-01-2004 à 21:58:41
bon alors, mes remarques:
- si on peut proposer une autre solution de design, voici ce que je ferais: garder en session ou dans l'applicationContext le nombre de fois qu'une requete à été executée sans succes et le moment ou elle a été executée la 1e fois. executer la requete une seule fois par requette à la servlet, stocket le compteur, afficher le tout a l'utilisateur.
- sinon:
pourquoi ne pas utiliserun Timer, c'est fait pour ça et ça marche bien.
Marsh Posté le 06-01-2004 à 08:59:10
the real moins moins a écrit : euh une servlet qui repond pas avant 1 minute, z'etes gentil mais le browser il va partir en timeout. j'espere. |
Pour 60 Secondes, j'abuse peut être un peu. Mais le browser ne partira pas en time out de toute façon, car la servlet qui peut mettre jusqu'a 60 secondes à répondre est appelée entant que source d'une image (et sert à récupérer et balancer des bonnées d'images en binaire).
Marsh Posté le 06-01-2004 à 09:01:07
the real moins moins a écrit : bon alors, mes remarques: |
Pourquoi ne pas utiliser un Timer ? Dans cette situation particulière, je veux justement bloquer le thread, et que le client n'ai pas de réponse tant que ma condition "theJob.isJobTreated()" n'est pas respectée ou que le time out de 60 secondes n'est pas écoulé.
Marsh Posté le 06-01-2004 à 09:01:35
Merci Dark pour ta réponse d'hier, j'pense que ça va m'aller parfaitement.
EDIT : oui, je sais que le wait (1000) c'est une secondes !
Marsh Posté le 06-01-2004 à 09:19:07
Ha mais au fait, j'y pense. Ce que tu m'as proposé Dark, ça va bloquer tous les clients qui cherchent à accèder à ma servlet pendant 1 secondes à chauqe fois. Moi je voudrais bloquer juste le thread en cours...
Marsh Posté le 06-01-2004 à 09:34:25
el_gringo a écrit : Ha mais au fait, j'y pense. Ce que tu m'as proposé Dark, ça va bloquer tous les clients qui cherchent à accèder à ma servlet pendant 1 secondes à chauqe fois. Moi je voudrais bloquer juste le thread en cours... |
ben non. Le synchronize il le fait sur un objet local à la méthode, pas sur un objet de la servlet.
Marsh Posté le 06-01-2004 à 09:41:54
benou a écrit : |
En fait je m'apprêtais à supprimer ma dernière remarque.
Par contre j'suis pas d'accord avec toi benou, il le fait son synchronized sur un membre de l'instance (déclaration précédée d'un indicateur de portée). D'ailleurs si je fais le synchronized sur un objet local à la méthode, je me prend à nouveau l'exception que j'avais à mon 1er post. Si je déclare le verrou (lock) entant qu'attribut de ma classe Servlet, ça roule.
Marsh Posté le 06-01-2004 à 10:21:42
el_gringo a écrit : |
ouais j'avais pas vu le "public" ...
si c'est ca que tu veux ok, mais tous les appels à ta servlets resteront bloqués : tu rends ta servlet monothreadée à ce moment là....
Marsh Posté le 06-01-2004 à 10:27:59
benou a écrit : |
C'est bien ce dont j'avais peur. Et comment je peux faire : ne pas répondre a un client donné tant que la condition "theJob.isJobTreated()" n'est pas vraie pour ce client, mais permettre néamoins l'accès à cette même servlet par d'autres threads ?
Marsh Posté le 06-01-2004 à 10:51:02
Bon d'après ce que j'i compris, ce que tu veux faire c'est attendre qu'un truc se passe en base. C'est à dire que la première requête qui arrive fasse des recherche en base, juqsu'à ce que "le truc se passse". Tant que le truc ne "s'est pas passé", les autres requêtes doivent être misent en attente.
Donc si c'est ca, voilà comment faire :
Code :
|
Marsh Posté le 06-01-2004 à 11:02:03
el_gringo a écrit : |
ce n'est pas à toi que je parlais mais à --
Marsh Posté le 06-01-2004 à 11:03:52
benou a écrit : Bon d'après ce que j'i compris, ce que tu veux faire c'est attendre qu'un truc se passe en base. C'est à dire que la première requête qui arrive fasse des recherche en base, juqsu'à ce que "le truc se passse". Tant que le truc ne "s'est pas passé", les autres requêtes doivent être misent en attente. |
Non, c'est pas ce que je cherche à faire. Au contraire, c'est ce que je veux éviter. J'explique le contexte, ça pourra aider à comprendre. Ma servlet sert à afficher une image spécifique selon chaque demande. Cette image est générée par un programme avec lequel elle comunique par base de données.
En schématisant :
- demande HTTP d'affichage d'image
- réception de la demande par la servlet HTTP
- écriture de l'ordre de génération d'image ("job" ) en base de données pour faire la demande au module de génération des images (sur lequel je n'ai absolument pas la main)
- attente que l'image ai été généré (job traité) par le module de génération des images (en vérifiant la base de données régulièrement : c'est dans celle-ci qu'est indiqué l'état de traitement du "job" )
- Quand le "job" est terminé, envoit de la réponse par la servlet HTTP (données d'images binaires + type MIME et compagnie)
La réponse ne doit être renvoyé au client QUE quand l'image est disponible (ou qu'une erreur a été constatée)
Marsh Posté le 06-01-2004 à 11:12:38
et pq tu ne t'arranges pas pour que ton module de génération d'image te callback qd il a terminé son bourzin. Ok ok, tu n'y a pas accès mais bon la façon dont il est invoqué tu peux modifier ca non?
(tu passe par la bd pour l'invoquer? )
Marsh Posté le 06-01-2004 à 11:17:05
darklord a écrit : |
Il me callbackera pas, tout simplement parce qu'il est pas fait pour ça. Il est écrit en C++, c'est un gros moteur de traitements de masse (qui en l'occurence sert à la génération d'images). Donc la façon dont il est invoqué, je peux pas modifier ça. Et, je comprend que ça te choque si je dit que je l' "invoque" par base de données. Disons que je lui poste une demande. ça passe mieux comme ça ?
Marsh Posté le 06-01-2004 à 11:34:25
el_gringo a écrit : |
oui ça passe mieux mais bon, ma réponse: "tu ne sais pas avoir un design propre si tu es obligé d'utiliser un truc pourri comme un porc"
et visiblement cai le cas
Marsh Posté le 06-01-2004 à 11:40:30
darklord a écrit : |
Ce truc est pas tout pourrit. C'est du traitement de masse. Je trouve pas choquand de lui poster de demander en base de données. Mais de toute façon, c'est comme ça, et ça, j'y peux absolument rien, j'dois faire avec. Si je peux pas avoir un design propre, tant pis, j'voudrais juste arriver à m'en sortir
Marsh Posté le 06-01-2004 à 11:50:17
el_gringo a écrit : |
ne te méprends pas hein, c'est bien ce que je dis. Si tu ne sais rien y faire, ca va etre dur de faire un truc propre c'est tout
Marsh Posté le 06-01-2004 à 12:01:51
darklord a écrit : |
J'avais compris.
Pour en revenir au sujet exact : la méthode que tu m'as proposée dès la 1er réponse fonctionne, mais problème : le verrou est un membre de la servlet, il va donc bloquer l'accès a tous les utilisateur de la servlet pendant qu'un des utilisateurs attend. C'est pas ce que j'essaye de faire. Et si je passe le verrou entant que variable locale, je me prend encore l'exception suivante :
java.lang.IllegalMonitorStateException: current thread not owner |
Marsh Posté le 06-01-2004 à 12:42:38
montre ton code
Marsh Posté le 06-01-2004 à 14:14:09
La partie de code inspirée de ce que tu m'as proposé envoit l'exception dont je parlais. Si le met "lock" entant qu'attribut, ça passe. Mais le comportement n'est alors plus celui souhaité (bloquage de tous les clients de la servlet pendant l'attente de 1000 ms).
Code :
|
Marsh Posté le 06-01-2004 à 14:30:13
Attend, mais le seul truc dont tu a besoin c'est de faire un sleep !!!
T'as juste à faire
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
pas besoin de faire de wait
Marsh Posté le 06-01-2004 à 14:40:44
oui mais bon si tu fais un sleep du thread ca va bloquer les autres threads qui voudraient accéder à cette instance de sa servlet.
Sinon gringo faudrait que je regarde un peu plus en profondeur, je ne comprends pas pq ca ne marcherait pas
Le deal c'est que si un thread, quel qu'il soit, est en wait d'un truc, tu ne peux pas t'attendre à ce qu'ils servent d'autres clients. Donc t'as pas de solution sinon de threadé ta servlet à mort
Marsh Posté le 06-01-2004 à 14:42:39
darklord a écrit : oui mais bon si tu fais un sleep du thread ca va bloquer les autres threads qui voudraient accéder à cette instance de sa servlet. |
N'importe quoi
Marsh Posté le 06-01-2004 à 14:45:45
benou a écrit : |
donc qd tu as une instance de la servlet Machin et que tu appelles service() ca te crée un nouveau thread à chaque fois peut etre?
Marsh Posté le 06-01-2004 à 14:48:29
el_gringo a écrit : |
et ça change quoi? au mieux t'auras pas ton image, au pire t'auras quand meme le popup de timeout
Marsh Posté le 06-01-2004 à 14:50:07
darklord a écrit : |
mais totoz quoi !!!! Tu le fais exprès c'est pas possible
c'est les différents Thread (du pool de thread du moteur de servlet) qui appellent la méthode service sur la même instance de la servlet. Si y a un thread qui reste coincé un moment dans la méthode ca impacte pas les autres threads !
Marsh Posté le 06-01-2004 à 14:50:49
j'adore les discours de sourds entre mecs qui savent pas s'exprimer
Marsh Posté le 06-01-2004 à 14:51:21
benou a écrit : |
sauf que je ne parlais pas de ca et merci de me prendre pour un con fini.
Bon spagrave, j'ai l'habitude
Marsh Posté le 06-01-2004 à 14:52:36
the real moins moins a écrit : j'adore les discours de sourds entre mecs qui savent pas s'exprimer |
quoi c'est très clair ce que je dis ...
Marsh Posté le 06-01-2004 à 14:53:37
darklord a écrit : |
Citation : oui mais bon si tu fais un sleep du thread ca va bloquer les autres threads qui voudraient accéder à cette instance de sa servlet. |
darklord a écrit : |
nan, vas-y ! dis, je veux comprendre !
Marsh Posté le 06-01-2004 à 14:56:41
benou a écrit : |
c'est bien ce que je dis
Marsh Posté le 06-01-2004 à 14:57:32
the real moins moins a écrit : c'est bien ce que je dis |
allez, raconte ce que tu as pas compris à tonton benou
Marsh Posté le 06-01-2004 à 15:17:31
benou a écrit : Attend, mais le seul truc dont tu a besoin c'est de faire un sleep !!! |
Ben voila. C'est tout bêtement ce que je cherchais depuis le début. Merci benou.
Marsh Posté le 05-01-2004 à 17:15:49
Bon, on va essayer d'expliquer ma situation simplement.
J'ai une servlet qui est chargée de vérifier l'état d'une tâche en base de données. Cet état peut être (entre autres) : "CRS" (en cours), "OK" (terminé avec succès), ou "ERR" (terminé avec erreur). Ma servlet ne doit rendre de résultat QUE quand la tâche est terminée (OK ou ERR), ou au bout de 60 secondes, si la tâche n'est tjs pas terminée.
Pour cela j'ai essayé qqch dans ce style :
Problème : sur le "Runtime.getRuntime().wait(1000);", je me mange une exception :
java.lang.IllegalMonitorStateException: current thread not owner
Je comprend la raison de l'exception. Je vois pas comment y pallier. Plus largement : comment effectuer cette attente de changement d'état en base de données.
Le multi-thread est déja géré par mon moteur de servlet, je n'ai donc pas besoin de créer de nouveau thread, mais comment mettre ce thread là en attente ?
Merci...
---------------
Les Vers Solitaires, on aime ... ou pas !