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