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