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