Newsgroup: it.comp.java
Titolo: applet <-> servlet

Ciao a tutti,
vi pongo il mio problema e grazie in anticipo.
Ho un'applet che invia degli oggettti serializzati ad una
servlet. La servlet invia in risposta un oggetto Acknowledge
all'applet scrivendolo serializzato nella outputstream della
response. Il problema che mi assilla e' che quando l'applet
cerca di aprire la input stream dall'applet mi da un'eccezione
java.io.FileNotFoundException.
Riepilogando le operazioni sono nell'ordine:
1. L'applett ottiene una java.net.URLConnection dall'URL
    della servlet.
2. L'applet crea l'oggetto da inviare.
3. L'applet ottiene la OutputStream dalla URLConnection.
4. L'applet scrive l'oggetto nell'OutputStream
5. La servlet riceve l'oggetto inviato. (legge ed interpreta)
Fin tutto bene
6. La servlet scrive l'oggetto di Acknowledge
    nell'OutputStream della HTTPResponse.
7. L'applet cerca di ottenere la InputStream dalla
    URLConnection
A questo mi becco l'eccezione FileNotFoundException.
Appena scritto chiamo subito Flush e Close delle Input/Output
stream sia nell'applet che nella servlet.
/*
  * Applet.java
  *
  */
package gui;
import java.net.*;
import java.io.*;
public class Applet extends java.applet.Applet {
   /** The name of the server */
   private String hostname = "127.0.0.1";
   /** The port fo the tomcat server */
   private String port = "8080";
   /** The name of the community */
   private String comm = "none";
   /** The URL of the server */
   private URL url = null;
   /** The connection to the server */
   private HttpURLConnection connection = null;
   /** Initializes the applet HermesApplet */
   public void init() {
     hostname = getParameter("hostname");
     port = getParameter("port");
     comm = getParameter("comm");
     try {
       url = new 
URL("http",hostname,Integer.parseInt(port),HttpConstants.HERMES_PATH);
     } catch (Exception e) {
       Trace.error(this,e);
     }
     initComponents();
   }
   private void button1ActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_btnLoginActionPerformed
     System.out.println("Trying login...");
     LoginMessage login =
         new LoginMessage(txtLogin.getText(),comm,txtPassword.getText());
     System.out.println("Created object querying server... ");
     Object response = getServletResponse(url,login);
     System.out.println("" + response);
   }
   public Object getServletResponse( URL url, Object sendobj ) {
     InputStream is = null;
     OutputStream os = null;
     ObjectInputStream ois = null;
     ObjectOutputStream oos = null;
     try {
       // Open connection
       connection = (HttpURLConnection) url.openConnection();
       connection.setUseCaches(false);
       connection.setDoOutput(true);
       connection.setDoInput(true);
       connection.setRequestProperty("Content-Type", 
"application/octet-stream");
       connection.setRequestMethod("POST");
       connection.connect();
       System.out.println("Getting output stream");
       os = connection.getOutputStream();
       if ( sendobj != null ) {
         System.out.println("Getting object output stream");
         oos = new ObjectOutputStream(os);
         oos.writeObject(sendobj);
         oos.flush();
       } // end if
       System.out.println("Getting input stream " + connection.getURL());
       ///Qui da l'errore....
       is = connection.getInputStream();
       System.out.println("Getting object input stream");
       ois = new ObjectInputStream(is);
       Object obj = ois.readObject();
       // Close ois
       ois.close();
       oos.close();
       return obj;
     } catch (Exception exc) {
       // Servlet connection error
       exc.printStackTrace();
       return null;
     }
   } // end getServletResponse
/*********************************************************************************/
/*
  * Servlet
  */
package servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.net.*;
import java.util.*;
public class Servlet extends javax.servlet.http.HttpServlet {
     protected void doGet(javax.servlet.http.HttpServletRequest 
httpServletRequest, javax.servlet.http.HttpServletResponse 
httpServletResponse) throws javax.servlet.ServletException, 
java.io.IOException {
       //super.doGet(httpServletRequest, httpServletResponse);
       doPost(httpServletRequest, httpServletResponse);
     }
     protected void doPost(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse) throws 
javax.servlet.ServletException, java.io.IOException {
       super.doPost(httpServletRequest, httpServletResponse);
       boolean requestIsCorrect = true;
       httpServletResponse.setContentType("application/octet-stream");
       HttpSession session = httpServletRequest.getSession(true);
       String nick = httpServletRequest.getParameter("nick");
       try {
         System.out.println("Received request");
         ObjectInputStream ois =
           new ObjectInputStream(httpServletRequest.getInputStream());
         Object obj = ois.readObject();
         //ois.close();
         log("Getting agent for " + session.getId());
         store(obj);
         log("Sending ack...");
         OutputStream os = httpServletResponse.getOutputStream();
         ObjectOutputStream oos =
           new ObjectOutputStream(os);
         log("" + oos + "" + os);
         oos.writeObject(new Acknowledge());
         oos.flush();
         os.flush();
         oos.close();
         //httpServletResponse.getWriter().println("Login sent!");
       } catch(Exception e) {
         log(this.getClass().getName(),e);
       }
       //}
     }

Credo di aver risolto.
Le soluzione sono due, un work around ed una soluzione piu' pulita che 
pero' sembra contravvenire alla documentazione di SUN.
-- La prima --
Suggeritami da un post nel ng comp.lang.java.programmer.
Inserire la chiamata per ottenere la InputStream in un ciclo del tipo:
...
int patience = 10;
int tries = 10;
for (int i = 0, i < tries; i++) {
   try {
      Thread.sleep(patience);
      connection.getInputStream()
      i = tries;
   } catch () {}
}
-- La seconda --
Suggeritami da Luca Davanzo
Effettuare le chiamate
...
connection.setDoInput(true);
connection.setDoOutput(true);
...
esattamente in questo ordine,
Daniele