Don't keep connection on failure.
[catagits/fcgi2.git] / doc / fcgi-java.htm
1 <html>
2 <head><title>Integrating FastCGI with Java</title>
3 </head>
4
5 <body bgcolor="#FFFFFF" text="#000000" link="#cc0000" alink="#000011" 
6 vlink="#555555">
7
8 <center>
9 <a href="http://fastcgi.com">
10     <img border=0 src="../images/fcgi-hd.gif" alt="[[FastCGI]]"></a>
11 </center>
12 <br clear=all>
13 <h3><center>Integrating FastCGI with Java</center></h3>
14
15 <!--Copyright (c) 1996 Open Market, Inc.                                    -->
16 <!--See the file "LICENSE.TERMS" for information on usage and redistribution-->
17 <!--of this file, and for a DISCLAIMER OF ALL WARRANTIES.                   -->
18 <!-- $Id: fcgi-java.htm,v 1.2 2001/05/14 12:59:51 robs Exp $ -->
19
20 <P ALIGN=CENTER>
21 Steve Harris
22 <BR>
23 Open Market, Inc.
24 <BR>
25 <EM>7 May 1996</EM>
26 </P>
27
28 <h5 align=center>
29 Copyright &copy; 1996 Open Market, Inc.  245 First Street, Cambridge,
30   MA 02142 U.S.A.<br>
31 Tel: 617-621-9500 Fax: 617-621-1703 URL:
32   <a href="http://www.openmarket.com/">http://www.openmarket.com/</a><br>
33 </h5>
34 <hr>
35
36 <H3><A NAME = "S1"> 1. Introduction</A></H3>
37 Java is an object-oriented programming language developed by Sun
38 Microsystems.  The Java Depvelopers Kit (JDK), which contains the basic
39 Java class packages, is available from Sun in both source and binary
40 forms at Sun's
41 <a href="http://java.sun.com/java.sun.com/JDK-1.0/index.html">JavaSoft</a>
42 site.  This document assumes that you have some familiarity with the
43 basics of compiling and running Java programs. 
44 <p>
45 There are two kinds of applications built using Java.
46 <ul>
47   <li> <i>Java Applets</i> are graphical components which are run off
48        HTML pages via the <tt>&lt;APPLET&gt;</tt> HTML extention tag.<br><br>
49        
50   <li> <i>Java Applications (Apps) </i> are stand-alone programs
51        that are run by invoking the Java interpreter directly. Like
52        C programs, they have a <tt>main()</tt> method which the interpreter
53        uses as an entry point.
54 </ul>
55 The initial emphasis on using Java for client side applets should not
56 obscure the fact that Java is a full strength programming language
57 which can be used to develop server side stand alone applications,
58 including CGI and now FastCGI applications.
59 <p>
60 The remainder of this document explains how to write and run FastCGI Java
61 applications. It also illustrates the conversion of a sample Java CGI program
62 to a FastCGI program.
63
64
65
66 <H3><A NAME = "S2"> 2. Writing FastCGI applications in Java</A></H3>
67
68 Writing a FastCGI application in Java is as simple as writing one in C.
69
70 <ol>
71   <li> Import the <tt>FCGIInterface</tt> class.
72   <li> Perform one-time initialization at the top of the
73        <tt>main()</tt> method.
74   <li> Create a new <tt>FCGIInterface</tt> object and send it an
75        <tt>FCGIaccept()</tt> message in a loop.
76   <li> Put the per-request application code inside that loop.
77 </ol>
78
79 On return from <tt>FCGIaccept()</tt> you can access the request's environment
80 variables using <tt>System.getProperty</tt> and perform request-related
81 I/O through the standard variables <tt>System.in</tt>,
82 <tt>System.out</tt>, and <tt>System.err</tt>.<p>
83
84 To illustrate these points, the kit includes <tt>examples/TinyCGI</tt>,
85 a CGI Java application, and <tt>examples/TinyFCGI</tt>, the FastCGI
86 version of TinyCGI.  These programs perform the same
87 functions as the C programs <tt>examples/tiny-cgi.c</tt> and
88 <tt>examples/tiny-fcgi.c</tt> that are used as examples in the
89 <A HREF="fcgi-devel-kit.htm#S3.1.1">FastCGI Developer's Kit document</A>.
90
91
92 <h4>A. TinyCGI</h4>
93 <PRE> 
94 class TinyCGI { 
95         public static void main (String args[]) {               
96                 int count = 0;
97                 ++count;
98                 System.out.println("Content-type: text/html\n\n");
99                 System.out.println("&lt;html&gt;");
100                 System.out.println(
101                         "&lt;head&gt;&lt;TITLE&gt;CGI Hello&lt;/TITLE&gt;&lt;/head&gt;");
102                 System.out.println("&lt;body&gt;");
103                 System.out.println("&lt;H3&gt;CGI-Hello&lt;/H3&gt;");
104                 System.out.println("request number " + count + 
105                                         " running on host " 
106                                 + System.getProperty&lt;"SERVER_NAME"));
107                 System.out.println("&lt;/body&gt;");
108                 System.out.println("&lt;/html&gt;"); 
109                 }
110         }
111
112 </PRE>
113 <h4>B. TinyFCGI</h4>
114 <PRE> 
115 import FCGIInterface;
116
117 class TinyFCGI {        
118         public static void main (String args[]) {               
119                 int count = 0;
120                 while(new FCGIInterface().FCGIaccept()>= 0) {
121                         count ++;
122                         System.out.println("Content-type: text/html\n\n");
123                         System.out.println("&lt;html&gt;");
124                         System.out.println(
125                           "&lt;head&gt;&lt;TITLE&gt;FastCGI-Hello Java stdio&lt;/TITLE&gt;&lt;/head&gt;");
126                         System.out.println("&lt;body&gt;");
127                         System.out.println("&lt;H3&gt;FastCGI-HelloJava stdio&lt;/H3&gt;");
128                         System.out.println("request number " + count + 
129                                         " running on host " 
130                                 + System.getProperty&lt;"SERVER_NAME"));
131                         System.out.println("&lt;/body&gt;");
132                         System.out.println("&lt;/html&gt;"); 
133                         }
134                 }
135         }
136
137 </PRE>
138 <h4>C. Running these Examples</h4>
139
140 We assume that you have downloaded the JDK and the FastCGI Developer's
141 Kit, and that you have a Web server running that can access the
142 <tt>fcgi-devel-kit/examples</tt> directory. In all cases where we
143 specify paths, we are using relative paths within
144 <tt>fcgi-devel-kit</tt> or the JDK which will need to be enlarged to a
145 full path by the user.
146
147 <h5>Configuring</h5>
148 <ol>
149   <li> Add your JDK's <tt>java/bin</tt> directory to your Unix <tt>PATH</tt>
150        if it isn't there already.<br><br>
151        
152   <li> Add the directories <tt>fcgi-devel-kit/examples</tt> and
153        <tt>fcgi-devel-kit/java/classes</tt> to your Java
154        <tt>CLASSPATH</tt>.<br><br>
155         
156   <li>In your Open Market Secure WebServer configuration file,
157       <tt>httpd.config</tt>, add the following two lines:<br><br>
158        
159        <tt>ExternalAppClass TinyFCGI -host </tt><i>hostName:portNum</i><br>
160        <tt>Responder TinyFCGI fcgi-devel-kit/examples/TinyFCGI</tt><br><br>
161               
162        <ul>
163        <li><i>hostName</i> is the name of your host machine.<br>
164        <li><i>portNum</i> is the port that you've selected for
165             communication between the Web server and the Java application.<br>
166        </ul><br>
167
168        On other servers you can use <tt>cgi-fcgi</tt> to get a
169        similar effect.
170        
171   <li> Create a soft link <tt>examples/javexe</tt> to the
172        <tt>java/bin</tt> directory in your JDK.
173        This link is required only to run the
174        CGI scripts <tt>examples/TinyCGI.cgi</tt> and
175        <tt>examples/TinyFCGI.cgi</tt>, which use it to
176        invoke the Java interpreter <tt>java/bin/java</tt>.
177        It is not used by FastCGI applications.
178
179    <li> You might have to modify <tt>examples/TinyFCGI.cgi</tt> to use a
180         Unix shell for which your CLASSPATH is defined.
181 </ol>
182
183 <h5> Running </h5>
184
185 <ul>
186   <li> To run TinyFCGI as FastCGI, you invoke the Java interpreter
187        with the -D option, giving it the <tt>FCGI_PORT</tt> environment
188        variable
189        and the same <i>portNum</i> that was used in the Web server
190        configuration. The command is:
191        <br><br>
192        <tt>java -DFCGI_PORT=portNum TinyFCGI</tt>
193        <br><br>
194        Then point your browser at <tt>fcgi-devel-kit/examples/TinyFCGI</tt>.
195        Notice that each time you reload, the count increments.<br><br>
196        
197   <li> To run TinyCGI, point your browser at
198        <tt>fcgi-devel-kit/examples/TinyCGI.cgi</tt> on your host machine.
199        Notice that the count does not increment.<br><br>
200
201   <li> Finally, you can run TinyFCGI as a straight CGI program by pointing
202        your browser at <tt>fcgi-devel-kit/examplesi/TinyFCGI.cgi.</tt> The results
203        are exactly the same as when you ran TinyCGI. Invoking a FastCGI
204        program without an <tt>FCGI_PORT</tt> parameter tells the
205        FastCGI interface
206        to leave the normal CGI environment in place.
207 </ul>
208 <p>
209 Due to gaps in the Java interpreter's support for listening
210 sockets, Java FastCGI applications are currently limited to
211 being started as external applications.  They can't be started and
212 managed by the Web server because they are incapable of using
213 a listening socket that the Web server creates.
214
215
216
217 <H3><A NAME = "S3"> 3. Standard I/O and Application Libraries</A></H3>
218
219 As we have seen above, FastCGI for Java offers a redefinition
220 of standard I/O corresponding to the the <i>fcgi_stdio</i> functionality.
221 It also offers a set of directly callable I/O methods corresponding to
222 the <i>fcgiapp</i> C library. To understand where these methods occur
223 we need to look briefly at the FastCGI redefinition of standard I/O.<p>
224
225 Java defines standard I/O in the <i>java.System</i> class as follows:<p>
226
227 public static InputStream in = new BufferedInputStream(new FileInputStream(FileDescriptor.in), 128);<br>
228 public static PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out), 128), true);<br>
229 public static PrintStream err = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.err), 128), true);<p>
230
231 The File Descriptors <i>in</i>, <i>out</i>, <i>err</i> are constants set to 0, 1 and 2 respectively.<p>
232
233 The FastCGI interface redefines <i>java.System in, out</i>, and <i>err</i>
234 by replacing the File streams with Socket streams and inserting streams
235 which know how to manage the FastCGI protocol between the Socket streams
236 and the Buffered streams in the above definitions.
237 <p>
238 For those cases where the FCGI application needs to bypass the standard I/O
239 streams, it can directly access the methods of the FCGI input and output
240 streams which roughly correspond to the functions in the C <i>fcgiapp</i>
241 library. These streams can be accessed via the <i>request</i> class variable
242 in FCGIInterface. Each Request object has instance variables that refer to an
243 FCGIInputStream, and to two FCGIOutputStreams associated with that request.
244
245 <H3><A NAME = "S4"> 4. Environment Variables</A></H3>
246
247 Java does not use the  C <i>environ</i> list. Nor is there a <i>getenv</i>
248 command that reads system environment variables. This is intentional for
249 reasons of portability and security. Java has an internal dictionary of
250 properties which belongs to the System class. These System properties
251 are <i>name/value</i> associations that constitute the Java environment.
252 When a Java application starts up, it reads in a file with default properties.
253 As we have seen, additional System properties may be inserted by using
254 the -D <i>Java</i> command argument.<p>
255
256 For CGI, where the Java application is invoked from a .cgi script that,
257 in turn, invokes the Java interpreter, this script could read the environment
258 and pass the variables to the Java application either by writing a file
259 or by creating -D options on the fly. Both of these methods are somewhat
260 awkward.<p>
261
262 For FastCGI Java applications, the environment variables are obtained from
263 the FastCGI web server via <tt>FCGI_PARAMS</tt> records that are sent to the
264 application at the start of each request. The FastCGI interface stores the
265 original startup properties, combines these with the properties obtained
266 from the server, and puts the new set of properties in the System properties
267 dictionary. The only parameter that has to be specifically added at startup
268 time is the FCGI_PORT parameter for the Socket creation.  In the future, we
269 expect that even this parameter won't be needed, since its use is due to an
270 acknowledged rigidity in the JDK's implementation of sockets.<p>
271
272 <H3><A NAME = "S4"> 5. Further examples: EchoFCGI and Echo2FCGI</A></H3>
273
274 The next two examples illustrate the points made in the last two sections.
275 EchoFCGI and Echo2FCGI both echo user input and display the application's
276 environment variables. EchoFCGI reads the user input from System.in, while
277 Echo2FCGI reads the user input directly from the intermediate FastCGI input
278 stream.
279
280 <h4>A. EchoFCGI</h4>
281 <pre>
282 import FCGIInterface;
283 import FCGIGlobalDefs;
284 import java.io.*;
285
286 class EchoFCGI {
287         
288         public static void main (String args[]) {
289                 int status = 0;
290                 while(new FCGIInterface().FCGIaccept()>= 0) {
291                 System.out.println("Content-type: text/html\n\n");
292                         System.out.println("&lt;html&gt;");
293                         System.out.println(
294                                 "&lt;head%gt;&lt;TITLE&gt;FastCGI echo
295                                       &lt;/TITLE&gt;&lt;/head&gt;");
296                         System.out.println("&lt;body&gt;");     
297                         System.out.println(
298                                          "&lt;H2&gt;FastCGI echo&lt;/H2&gt;");
299                         System.out.println("&lt;H3&gt;STDIN&lt;/H3&gt;");
300                         for ( int c = 0; c != -1; ) {
301                                 try {
302                                         c = System.in.read();
303                                 } catch(IOException e) {
304                                         System.out.println(
305                                         "&lt;br&gt;&lt;b&gt;SYSTEM EXCEPTION");
306                                         Runtime rt = Runtime.getRuntime();
307                                         rt.exit(status);
308                                         }
309                                 if (c != -1) {  
310                                         System.out.print((char)c);
311                                         }
312                                 }
313                         System.out.println(
314                                 "&lt;H3&gt;Environment Variables:&lt;/H3&gt;");
315         
316                         System.getProperties().list(System.out);
317                         System.out.println("&lt;/body&gt;");
318                         System.out.println("&lt;/html&gt;");
319                         }
320                 }
321         }
322 </pre>
323 <h4>B. Echo2FCGI</h4>
324 <pre>
325 import FCGIInterface;
326 import FCGIGlobalDefs;
327 import FCGIInputStream;
328 import FCGIOutputStream;
329 import FCGIMessage;
330 import FCGIRequest;
331 import java.io.*;
332
333 class Echo2FCGI {
334
335         public static void main (String args[]) {
336                 int status = 0;
337                 FCGIInterface intf = new FCGIInterface();
338                 while(intf.FCGIaccept()>= 0) {
339                 System.out.println("Content-type: text/html\n\n");
340                         System.out.println("&lt;html&gt;");
341                         System.out.println(
342                                 "&lt;head&gt;&lt;TITLE&gt;FastCGI echo
343                                     &lt;/TITLE&gt;&lt;/head&gt;");
344                         System.out.println("&lt;body&gt;");                     
345                         System.out.println("&lt;H2&gt;FastCGI echo&lt;/H2&gt;");
346                         System.out.println("&lt;H3&gt;STDIN:&lt;/H3"&gt;);
347                         for ( int c = 0; c != -1; ) {
348                                 try {
349                                         c = intf.request.inStream.read();
350                                 } catch(IOException e) {
351                                         System.out.println(
352                                         "&lt;br&gt;&lt;b&gt;SYSTEM EXCEPTION");
353                                         Runtime rt = Runtime.getRuntime();
354                                         rt.exit(status);
355                                         }
356                                 if (c != -1) {  
357                                         System.out.print((char)c);
358                                         }
359                                 }
360                         System.out.println(
361                                 "&lt;H3&gt;Environment Variables:&lt;/H3&gt;");
362         
363                         System.getProperties().list(System.out);
364                         System.out.println(&lt;"/body&gt;");
365                         System.out.println("&lt;/html&gt;");
366                         }
367                 }
368         }
369 </pre>
370 <h4>C. Running these Examples</h4>
371
372 <h5>Configuring</h5>
373
374 As with TinyFCGI, you need to configure the web server to recognize these
375 two FastCGI applications. Your configuration now looks like this:<p> 
376 <pre>
377 ExternalAppClass java1 -host hostname:portNum
378 Responder java1 fcgi-devel-kit/examples/TinyFCGI
379 ExternalAppClass java2 -host hostname:portNumA
380 Responder java2 fcgi-devel-kit/examples/EchoFCGI
381 ExternalAppClass java3 -host hostname:porNumB
382 Responder java3 fcgi-devel-kit/examples/Echo2FCGI
383 </pre>
384 <p>
385 Note that the application classes and port numbers are different for each
386 application.
387
388 <h5>Running</h5>
389
390 As with TinyFCGI, you need to run these programs with the -D option
391 using FCGI_PORT and the appropriate port number.
392
393 To get some data for standard input we have created two html pages with
394 forms that use a POST method. These are echo.html and echo2.html. You must
395 edit these .html files to expand the path to <i>fcgi-devel-kit/examples</i>
396 to a full path. Once the appropriate Java program is running, point your browser at the corresponding HTML page, enter some data and select the <i>go_find</i> button.
397
398
399 <H3><A NAME = "S6"> 6. FastCGI Java Classes</A></H3>
400
401 The Java FastCGI classes are included in both source and byte code format in
402 <i>fcgi-devel-kit/java/src</i> and :<i>fcgi-devel-kit/java/classes</i>
403 respectively. The following is a brief description of these classes:<p>
404
405 <dl>
406 <dt><i>FCGIInterface</i><dd> This class contains the FCGIaccept method called
407      by the FastCGI user application. This method sets up the appropriate
408      FastCGI environment for communication with the web server and manages
409      FastCGI requests.<br>
410      
411  <dt><i>FCGIInputStream</i><dd> This input stream manages FastCGI
412       internal buffers to ensure that the user gets all of the FastCGI
413       messages associated with a request. It uses FCGIMessage objects
414       to interpret these incoming messages.<br>
415       
416   <dt><i>FCGIOutputStream</i><dd> This output stream manages FastCGI
417        internal buffers to send user data back to the web server
418        and to notify the server of various FCGI protocol conditions.
419        It uses FCGIMessage objects to format outgoing FastCGI messages.<br>
420       
421 <dt><i>FCGIMessage</i><dd> This is the only class that understands the
422      actual structure of the FastCGI messages. It interprets incoming
423      FastCGI records and constructs outgoing ones..<br>
424      
425 <dt><i>FCGIRequest</i><dd>This class currently contains data fields
426      used by FastCGI to manage user requests.  In a multi-threaded
427      version of FastCGI, the role of this class will be expanded.<br>
428
429 <dt><i>FCGIGlobalDefs</i><dd>This class contains definitions of FastCGI
430      constants.
431 </dl>
432 <HR>
433 <ADDRESS><A HREF="mailto:harris@openmarket.com">Steve Harris // harris@openmarket.com</A></ADDRESS>
434 </i></i></body>
435 </html>