IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java ME Discussion :

Communication entre Midlet et Servlet en ulitisant Tomcat


Sujet :

Java ME

  1. #1
    Candidat au Club
    Inscrit en
    Juin 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 6
    Points : 2
    Points
    2
    Par défaut Communication entre Midlet et Servlet en ulitisant Tomcat
    Bonjour à tous,
    J'ai developpé une simple Midlet juste pour les tests, qui fait les operations suivantes:
    - Ouvre une connexion http avec une Servlet en utilisant Tomcat.
    - Ouvre deux flux DataInputStream et DataOutputStream.
    - envoyer deux String (Username et Passwd) via DataOutputStream à la Servlet.
    - La Servlet verifie le user et le passwd et repond à la Midlet sur DataInputStream.

    jusque là tous marche bien. Mais juste aprés, lorsque je tente d'envoyer un autre String à partir de la Midlet via DataOutputStream (Sachant que j'ai gardé la connexion et les stream toujours ouverts), je reçoie l'exception suivante:

    detailMessage:java.lang.String="Write attempted after request finished"

    Je remercie d'avance celui qui m'aidera, je sais que la solution est simple mais ce probleme m'a coûté beaucoup de temps.

    Med

  2. #2
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Points : 1 271
    Points
    1 271
    Par défaut
    S'agissant d'HTTP, le mode de fonctionnement est Requête/Réponse.

    Il te faut donc réouvrir ta connexion HTTP, et réobtenir tes flux via getOutputStream et getInputStream.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 137
    Points : 158
    Points
    158
    Par défaut
    Citation Envoyé par Greybird
    Il te faut donc réouvrir ta connexion HTTP, et réobtenir tes flux via getOutputStream et getInputStream.
    ou bien, envoyer le login et le mot de passe comme paramètre HTTP, ouvrir l'outputstream et envoyer la suite des données.

    Le serveur de son côté lit les paramètres login/mot de passe.
    Si il n'autorise pas l'accés, il renvoie une erreur 403, sinon il traite les données envoyées par la midlet.

  4. #4
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Points : 1 271
    Points
    1 271
    Par défaut
    Citation Envoyé par manitoba
    ou bien, envoyer le login et le mot de passe comme paramètre HTTP, ouvrir l'outputstream et envoyer la suite des données.

    Le serveur de son côté lit les paramètres login/mot de passe.
    Si il n'autorise pas l'accés, il renvoie une erreur 403, sinon il traite les données envoyées par la midlet.
    Je pense que tu es un peu décalé par rapport à la question... La problème se situe au niveau de l'émission de la deuxième requête, pas au niveau d'une authentification...

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 137
    Points : 158
    Points
    158
    Par défaut
    Citation Envoyé par Greybird
    Je pense que tu es un peu décalé par rapport à la question...
    L'interet, c'est la diversité des réponses :-)

  6. #6
    Candidat au Club
    Inscrit en
    Juin 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 6
    Points : 2
    Points
    2
    Par défaut a.med16
    Je vous remercie tous pour votre effort, mais en effet, ce que je tente de faire pour le moment est juste un simple test. Car l’application que je compte développer après, aura besoin de garder la connexion http ouverte, son principe est le suivant :
    1- Il y aura 3 composantes : clients et serveurs mobiles développés avec J2ME (c’est les Midlets) et un coordinateur fixe sous forme de Servlet.
    2- Les serveurs mobiles (les Midlets) ouvrent des connexions Http avec la Servlet (le coordinateur), ils font l’authentification de User et Passwd. Ces connexions restent ouvertes durant toute la durée de l’exécution du serveur mobile (la Midlet).
    3- Les clients mobiles ouvrent des connexions Http avec la Servlet (le coordinateur), émettent des requêtes vers le coordinateur. Le coordinateur les rediriges vers le serveur concerné (la Midlet). Le serveur concerné traite la requête et répond au coordinateur. Le coordinateur répond à son tour au client mobile qui a initié la requête. Le client mobile ferme ensuite la connexion qui a ouvert avec la Servlet.
    Ce scénario impose que les serveurs mobiles (les Midlets) gardent les connexions ouvertes avec la Servlet (le coordinateur), car ils pourront à tout moment recevoir des requêtes provenant de la Servlet (le coordinateur).
    Mais le problème est que je n’arrive pas à réutiliser la connexion ouverte au départ par le serveur mobile avec la Servlet pour l’authentification. Si je tente réutiliser le DataInputStream ou le DataOutputStream je reçois l’exception citée ci-dessus.

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 137
    Points : 158
    Points
    158
    Par défaut
    Je suggererais bien de passer en socket pure. mais tu risques d'avoir des problèmes avec les gateways opérateurs.

    Il me semble que la seule solution est de rester en HTTP comme suggéré précedemment par GreyBird , et sans doute de gérer un contexte de session sur ton serveur .

  8. #8
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Points : 1 271
    Points
    1 271
    Par défaut
    Effectivement, si tu souhaites faire du push vers le mobile, il te faudrait idéalement des sockets, mais les gateway opérateurs vont t'embêter.

    HTTP n'est tout simplement pas destiné à ce genre de comportements, et tu ne pourras pas faire autrement.

    Une fois une requête émise et sa réponse reçue, la connexion au serveur HTTP est perdue. C'est pour cela que tu ne peux pas réutiliser tes flux. Ces flux n'existent plus une fois la réponse reçue. Tu ne peux pas maintenir ta connexion entre la Servlet et les MIDlet serveur.

    Au mieux, ce que tu peux faire, c'est requêter régulièrement la servlet depuis les MIDlet serveur pour savoir si tu as des informations à récupérer.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 18
    Points : 20
    Points
    20
    Par défaut
    -la connection permanente HTTP n'est pas possible sur certains opérateurs (SFR de mémoire) qui restent en HTTP1.0. Ne pas oublier de rajouter cela:
    conn.setRequestProperty("HTTP-Version", "HTTP/1.1");
    conn.setRequestProperty("Connection", "Keep-Alive");

    - l'utilisation des sockets n'est possible qu'en data-plan et nécessite une configuration APN spécifique avec des ports particuliers suivant opérateurs. Déjà qu'avec HTTP c'est la galère, en socket c'est puissance 1000. Certains phones n'aiment pas du tout les sockets et les incompatibilités sont encore plus nombreuses. Et il faut gérer les déconnections et autre timeout...

    - passer par du SMS-push mais le QOS n'est pas garanti...

  10. #10
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Points : 1 271
    Points
    1 271
    Par défaut
    Citation Envoyé par guzzoti
    -la connection permanente HTTP n'est pas possible sur certains opérateurs (SFR de mémoire) qui restent en HTTP1.0. Ne pas oublier de rajouter cela:
    conn.setRequestProperty("HTTP-Version", "HTTP/1.1");
    conn.setRequestProperty("Connection", "Keep-Alive");
    Tiens, voilà une information qui m'intéresse.

    Es-tu certain qu'utiliser une connexion persistante en HTTP 1.1 permet de réutiliser les flux créés par l'objet HTTPConnection ? J'ai toujours cru qu'à chaque nouvelle requête, il fallait récréer les flux, du fait notamment du fonctionnement interne de l'objet HTTPConnection.

    Si on peut bien réutiliser ces flux, et aux problèmes de gateway opérateur près, mes messages précédents sont effectivement erronés, et je te prie de m'en excuser.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 18
    Points : 20
    Points
    20
    Par défaut
    La persistance de connection n'est possible que sur certains modèles SE récents et Nokia compatible HTTP1.1 en plus avec les histoires de Chunked Data.
    Il n'y a donc pas que la gateway qui peut poser problème: la configuration du serveur, des éventuels routeurs, le firmware du téléphone, la configuration de l'APN du téléphone...
    Si on rendre vraiment dans le détail on se prend la tête avec ces histoires de connections en J2ME. Le truc est de regarder ce qui marche et faire pareil: par exemple Opera Mini une simple connection HTTP1.0/POST.
    Pour du push on doit faire un timer qui interroge le serveur à intervalles réguliers via requêtes HTTP1.0/POST poolées (pour éviter les connections parallèles qui posent problèmes sur certains terminaux).

  12. #12
    Candidat au Club
    Inscrit en
    Juin 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Oui effectivement, les socket causeront beaucoup de problemes, lorsque on souhaite deployer notre application. je prefere rester sur le protocole Http.
    Je trouve que le probleme perciste. D'ailleur je n'arrive meme pas à reutiliser le DataOutputStream aprés avoir reçu le reponse de la Servlet, meme si je le fais juste aprés sans attendre aucun moment.
    si j'arrive à realiser la solution de Mr guzzoti (conn.setRequestProperty("Connection", "Keep-Alive") ) sa serai génial, sinon j'utilise l'idée du timer.

    Ci-dessous un segment de mon code qui assure la communication entre la Midlet et Servlet.


    Source Midlet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
          if (command == Cmdlogin)
          {
            Thread    th = new  Thread()
            {
              public	 void	run()
             {
                String   url  =  "http://"+textField12.getString()+":8080/Login/new-serveur";
                HttpConnection conn = null;
                DataInputStream dis = null;
                DataOutputStream dos = null;
                boolean	trouv = false;
                try
                {
                   conn = (HttpConnection)Connector.open(url);
                   conn.setRequestProperty("HTTP-Version", "HTTP/1.1");
                   conn.setRequestProperty("Connection", "Keep-Alive");
                   conn.setRequestMethod(HttpConnection.POST);
                }
                catch (Exception e)
                {
                   System.out.println("Erreur de connexion");
                }
                //Envoyer la requête
                try
                {
                  dos = new DataOutputStream(conn.openOutputStream());
                  dos.writeUTF(UserTF.getString());
                  dos.writeUTF(PassTF.getString());
                  dos.flush();
                  dis = new DataInputStream(conn.openInputStream());
                  trouv = dis.readBoolean();
                  if (trouv)
                  {
                    dos.writeUTF(UserTF.getString()); // à cet endroit je reçoie l'exception "Write attempted after request finished"
                    dos.writeUTF(PassTF.getString());
                    dos.flush();
                    DisplayVar.setCurrent(ChoixConnexion);
                  }
                  else
                  {
                    Alert  alert = new Alert("Erreur","User name ou password incorrects",null,AlertType.ERROR);
                    alert.setTimeout(Alert.FOREVER);
                    DisplayVar.setCurrent(alert, LoginScr);
                  }
                }
                catch (Exception e)
                {
                   Alert  alert = new Alert("Erreur","Une erreur s'est produite lors de la connexion",null,AlertType.ERROR);
                   alert.setTimeout(Alert.FOREVER);
                   DisplayVar.setCurrent(alert, LoginScr);
                }
                finally
                {
                  ...
    Source Servlet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
      public	void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
      {
              String pathInfo = request.getPathInfo();
     
              ...
     
              else if (pathInfo.equals("/new-serveur"))
              {
                      DataInputStream   dis = null;
                      DataOutputStream  dos = null;
                      try
                      {
                              dis = new DataInputStream(request.getInputStream());
                              dos = new DataOutputStream(response.getOutputStream());
                              String  name = dis.readUTF();
                              String	password = dis.readUTF();
                              System.out.println("verification du user");
                              FileInputStream	fis = null;
                              ObjectInputStream	ois = null;
     
                              ...
     
                              if ((user == null) || (!user.isCorrectPassword(password)))
                              {
                                 dos.writeBoolean(false);//Invalid name or password
                              }
                              else
                              {
                                 dos.writeBoolean(true);
                                 String str1 = dis.readUTF();
                                 String str2 = dis.readUTF();
                              }
                             }
                      }
                      catch  (IOException e)
                      {
                              System.out.println("Erreur lors de la vérification"+e);
                      }
                      finally
                      {
                       ...

  13. #13
    Candidat au Club
    Inscrit en
    Juin 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    quelqu'un a une idée de ce probleme? pourquoi la methode "conn.setRequestProperty("Connection", "Keep-Alive");" ne resoud pas le probleme?
    il doit y exister certainement une solution pour faire un push sur le mobile

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 18
    Points : 20
    Points
    20
    Par défaut
    conn.setRequestProperty("Content-Length", Integer.toString(dataleng));
    avant les dos.write(); ou le datalen= nombre d'octets envoyés

    de plus il y a une mauvaise interpretation sur le keep-alive: le httpconnection ne peut être utilisé qu'une fois. C'est la connection physique qui est réutilisée et est maintenu par la VM.
    il faut donc impérativement refaire la boucle:
    - creation de l'httpconnection et des setrequestproperty
    - ecriture sur l'outputstream
    - lecture de la réponse du server
    - lecture de l'inputstream
    tu peux faire cela ds un Thread avec Thread.yield ou un sleep entre chaque appel a l'httpconnection

  15. #15
    Candidat au Club
    Inscrit en
    Juin 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Je pense que c’est préférable de rester sur HTTP/1.0, je crains de rencontrer les problèmes suscités en phase de déploiement.
    Pour contourner la contrainte de HTTP/1.0 qui ferme automatiquement la connexion après l’envoi total de la réponse, j’ai pensé à utiliser le scenario suivant :
    - utilisation d’une BDD au niveau de la Servlet qui stocke les requêtes envoyées par les clients mobiles et les réponses des serveurs mobiles.
    - les serveurs se connectent périodiquement à la Servlet pour voir s’ils ont des requêtes à traiter. En cas d’existence, le serveur mobile traite la requête et ouvre une nouvelle connexion avec la Servlet pour envoyer la réponse.
    - Le client initiateur de la requête entre dans une boucle où il vérifie à chaque itération la disponibilité de la réponse
    - noter que à chaque envoi/réception d’une requête/réponse une nouvelle connexion HTTP sera ouverte.

    Je vais essayer cette solution et je vous tiendrai au courant du résultat.
    Salutation

Discussions similaires

  1. Communication entre jquery et servlet java
    Par Philcmoi dans le forum jQuery
    Réponses: 3
    Dernier message: 28/01/2014, 12h25
  2. Communication entre applet et servlet
    Par jeromeSERRE dans le forum Tomcat et TomEE
    Réponses: 2
    Dernier message: 17/04/2010, 12h11
  3. communication entre applet et servlet
    Par ~~ Lu ~~ dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 06/08/2008, 12h07
  4. Communication entre servlets
    Par kam81 dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 23/10/2006, 08h44
  5. Problème de communication entre php et Laszlo(Tomcat)
    Par YUN59 dans le forum Autres langages pour le Web
    Réponses: 1
    Dernier message: 21/07/2006, 13h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo