http://nagoya.apache.org/bugzilla/show_bug.cgi?id=276 *** shadow/276 Fri Mar 9 19:13:52 2001 --- shadow/276.tmp.11958 Fri Mar 9 19:13:52 2001 *************** *** 0 **** --- 1,256 ---- + +============================================================================+ + | JNI problem: bufferedreader.read fails in Tomcat/IIS/JNI set-up BugRat Rep | + +----------------------------------------------------------------------------+ + | Bug #: 276 Product: Tomcat 3 | + | Status: UNCONFIRMED Version: 3.2.1 Final | + | Resolution: Platform: All | + | Severity: Normal OS/Version: All | + | Priority: High Component: Connectors | + +----------------------------------------------------------------------------+ + | Assigned To: [EMAIL PROTECTED] | + | Reported By: [EMAIL PROTECTED] | + | CC list: Cc: | + +----------------------------------------------------------------------------+ + | URL: | + +============================================================================+ + | DESCRIPTION | + There seems to be a bug that interferes with servlet-to-servlet communication, when +Tomcat is running under IIS (Win 2000 Advanced), using JNI. + + I'm attaching source for a pair of simple servlets that demonstrate the bug. The +first servlet (BadClient.java) opens a URLConnection to the second servlet +(BadServer.java). BadClient uses the URLConnection to open an output stream, then +uses the output stream to print some text, which will be read by BadServer. + + The BadServer servlet then calls request.getReader to get a reader object, to read +the text that was sent by BadClient. + + This all works fine under Tomcat 3.2, when Tomcat is running stand-alone. But if +Tomcat 3.2 is running inside IIS, using the JNI connector, there's a problem. +BadServer is never able to read any of the text sent by BadClient. The whole +process just seems to hang for exactly 1 minute... apparently, something times out +after 1 minute, and BadClient stops trying to read the text. Under JNI, the read +call returns -1. + + (Other servlets work fine under JNI.) + + The two servlets go on and perform other tasks after that, with BadServer reading a +local .GIF file, then sending it back to BadClient, which send the image back to the +browser. That part works; it's the first part that fails, as described above. + + I've tried various configurations of Tomcat -- using the JVM.DLL for classic, or +hotspot, or server (Java 1.3). No difference. I've looked in the various log files +for exceptions, and I don't see any. + + Here's the source for both servlets (around 100 lines each). If the formatting is +messed up too badly, please let me know and I'll email a copy to anyone who wants to +investigate the problem. + + // Here is all of BadClient.java (118 lines): + // BadClient.java -- demonstrates behavior that works fine in Tomcat 3.2 + // but does not work when Tomcat runs under IIS using JNI + // Used in conjunction with BadServer.java + import javax.servlet.*; + import javax.servlet.http.*; + import java.io.*; + import java.util.*; + import java.net.URLConnection; + import java.net.URL; + + public class BadClient extends HttpServlet { + + // TODO: Either modify the following string literal to represent + // the URL of the BadServer servlet, or specify that URL + // using an init parameter. + String m_url = "http://localhost:8100/test/servlet/BadServer"; + + public void init(ServletConfig config) throws ServletException { + super.init(config); + try { + String str = getInitParameter("url"); //URL to 2nd +servlet + if (str != null) { + m_url = str; + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + public void service(HttpServletRequest request, HttpServletResponse res) + throws ServletException, IOException + { + // Open an URLConnection to the BadServer servlet. + URL url = new URL(m_url); + URLConnection urlConnection = url.openConnection(); + urlConnection.setDoOutput(true); + urlConnection.setUseCaches(false); + urlConnection.setRequestProperty("Connection", "close"); + OutputStream os = null; + try { + os = urlConnection.getOutputStream(); + + // Only use one of the following two statements: + //PrintWriter pw = new PrintWriter(os); + OutputStreamWriter pw = new OutputStreamWriter(os); + + System.out.println("BadClient: About to print text. Time:" + +new Date()); + + // Send some text to the second servlet. This is the part that + // seems to fail when running on Tomcat 3.2 under IIS using +JNI. + + // If using a PrintWriter, use the println method... + /* + if (pw.checkError()) { + System.out.println("BadClient: will do println; +checkError is true."); + } + pw.println("This is some text sent from BadClient to +BadServer."); + if (pw.checkError()) { + System.out.println("BadClient: just did println; +checkError is true."); + } + */ + + // ...OR, If using an OutputStreamWriter, use this statement: + pw.write("This is some text sent from BadClient to +BadServer...", 0, 50); + + System.out.println("BadClient: Sent text. Time:" + new +Date()); + + String foo = request.getParameter("skipflush"); + if (foo != null && foo.length() > 0) { + System.out.println("BadClient: Will SKIP the +pw.flush..."); + } + else { + pw.flush(); + } + + foo = request.getParameter("skipclose"); + if (foo != null && foo.length() > 0 ) { + System.out.println("Will SKIP the pw.close... "); + } + else { + pw.close(); + } + + System.out.println("BadClient:After flush & close. Time:" + +new Date()); + } catch (Exception e) { + System.out.println(e.toString() ); + e.printStackTrace(); + } + os.close(); + + // Fetch an image from the second servlet + BufferedInputStream bin = + new BufferedInputStream( +urlConnection.getInputStream() ); + + DataInputStream dis = new DataInputStream(bin); + + // Read the text that precedes the image that we'll get back + String s = dis.readUTF(); + System.out.println("BadClient: Read header from BadServer: {" + s + +"}"); + + byte[] buf = new byte[1024]; + int count; + // now pump the image data to the browser + OutputStream outStream = res.getOutputStream(); + while ((count = dis.read(buf)) != -1) { + outStream.write(buf, 0, count); + } + outStream.flush(); + dis.close(); + outStream.close(); + } + + public String getServletInfo() { + return "ClientServlet Info"; + } + } + // end of BadClient.java + + //Here is all of BadServer.java (101 lines): + + // BadServer.java -- demonstrates behavior that works fine in Tomcat 3.2 + // but does not work if Tomcat is running under IIS with JNI. + // Used in conjunction with BadClient.java + + import javax.servlet.*; + import javax.servlet.http.*; + import java.io.*; + import java.util.*; + public class BadServer extends HttpServlet { + + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + public void doPost(HttpServletRequest request, HttpServletResponse res) + throws ServletException, IOException { + + try { + System.out.println("BadServer: will read text fromclient.:" + +new Date()); + + // Read in the text sent by the client servlet. + + // Only make one of the following two calls: + useBufferedReader(request); + //useInputStreamReader(request); + + System.out.println("BadServer: read text from the client.:" + +new Date()); + } + catch (Exception e) { + System.out.println(e.toString() ); + e.printStackTrace(); + } + + // Send the client back some text, followed by a GIF image + returnFile(res); + } + + void useInputStreamReader(HttpServletRequest request) + throws IOException { + + String buf = null; + int i = 0; + try { + InputStream is = request.getInputStream(); + InputStreamReader br = new InputStreamReader(is); + + char[] cbuf = new char[1024]; + i = br.read(cbuf, 0, 50); + buf = new String(cbuf); + } catch (Exception e) { + System.out.println(e.toString() ); + e.printStackTrace(); + } + System.out.println("BadServer:read returned " + i + " chars:" + buf); + } + + void useBufferedReader(HttpServletRequest request) + throws IOException { + //InputStream is = request.getInputStream(); + //BufferedReader br = new BufferedReader(new InputStreamReader(is)); + + String buf = null; + int i = 0; + try { + BufferedReader br = request.getReader(); + char[] cbuf = new char[1024]; + i = br.read(cbuf, 0, 50); + buf = new String(cbuf); + } catch (Exception e) { + System.out.println(e.toString() ); + e.printStackTrace(); + } + System.out.println("BadServer:readLine returned " + i + " chars:" + +buf); + } + + void returnFile(HttpServletResponse res) + throws ServletException, IOException { + + // TODO: If necessary, modify the following to point to a local GIF +file. + File f = new File("D:\\test.gif"); + + BufferedInputStream bin = new BufferedInputStream(new +FileInputStream(f)); + BufferedOutputStream os = new +BufferedOutputStream(res.getOutputStream()); + DataOutputStream dos = new DataOutputStream(os); + dos.writeUTF("Some text sent from BadServer!"); + + byte[] buf = new byte[1024]; + int nRead; + + while( (nRead = bin.read(buf)) != -1 ) { + os.write(buf, 0, nRead); + } + os.flush(); + bin.close(); + System.out.println("BadServer: Flushed OS."); + } + + public String getServletInfo() { + return "SecondServlet Information"; + } + } + // end of BadServer.java --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]