ENGLISH | JAPANESE |
We learn in this chapter how to call prolog programs from Servlet and return the result on Servlet. The mechanism allows you to build in your Web page various AI technologies implemented in prolog.
We employ JPL, the Java interface to prolog, to call prolog programs from Java. JPL is developed by Fred Dushin and detailed explanation is given in the distribution, under doc directory. We will not therefore repeat the explanation of the interface below. We illustrate how the interface is used on Servlet. The sample programs are taken from the distribution, under 'demo/getting-started' directory. It is good idea to test-run Test.java under the directory before proceeding to check if JPL was installed correctly as shown in [Testing JPL]. You may have to run it within Meadow if the result is not visible in Bash Window.
/tmp/jpl/demo/getting-started> java Test % test.pl compiled 0.02 sec, 1,084 bytes child_of(joe, ralf) = true descendent_of(steve, ralf) = true querying descendent_of( X, ralf ) X = joe querying descendent_of( X, ralf ) X = joe X = mary X = steve /tmp/jpl/demo/getting-started>
A note on Windows95: I have tested the samples below on Windows95 and Windows98 and found that calling prolog program from Servlet does not work on Windows95. I am not sure if it is generally so. Please tell me what happened if you run the samples on Windows95.
We assume that you have an elementary level of knowledge about prolog programming. Below (list[test.pl]) is a sample prolog program, 'test.pl', taken from 'demo/getting-started'. The program says that 'joe' is a child of 'ralf', and 'mary' and 'steve' are children of 'joe'. It defines descendent_of relation, too, such that X is descendent of Y if X is a child of Y or if there is a person Z who is child of Y and a parent of X.
child_of( joe, ralf ). child_of( mary, joe ). child_of( steve, joe ). descendent_of( X, Y ) :- child_of( X, Y ). descendent_of( X, Y ) :- child_of( Z, Y ), descendent_of( X, Z ).
You can load the program on SWI-prolog to test it as shown in (figure[Test run].
/tmp/jpl/demo/getting-started> pl Welcome to SWI-Prolog (Version 3.3.6) Copyright (c) 1990-2000 University of Amsterdam. Copy policy: GPL-2 (see www.gnu.org) For help, use ?- help(Topic). or ?- apropos(Word). 1 ?- [test]. % test compiled 0.02 sec, 1,156 bytes Yes 2 ?- child_of(joe, ralf). Yes 3 ?- descendent_of( X, ralf ). X = joe ; X = mary ; X = steve ; No 4 ?-
The program, demo/getting-started/Test.java, and the documentation illustrate well how to hand SWI-prolog variables and atoms. Let us examine the method, test_3, in Test.java (list[Test.java])
static void test_3() { Variable X = new Variable(); Term args[] = { X, new Atom( "ralf" ) }; Query query = new Query( "descendent_of", args ); System.out.println( "querying descendent_of( X, ralf )" ); java.util.Hashtable solution = query.oneSolution(); System.out.println( "X = " + solution.get( X ) ); }
The method prepares an inquiry, descendent_of( X, ralf ), to emit it to SWI-prolog and receives back an atom instantiating X. We modify the method slightly so that it returns an Atom bound to the variable, X. Let us call the method 'test3'. The method is defined as below (list[Method test3]). The type of the method is changed from 'void' to 'Atom' and the line, 'return (Atom)solution.get( X );' replaces for 'System.out.println( "X = " + solution.get( X ) );'
// // This is test3 method. // The type of the return value is Atom. // static Atom test3( String person ) { // // We construct the query, descendent_of( X, Person ) // where Person is instantiated already when called Variable X = new Variable(); Term args[] = { X, new Atom( person ) }; Query query = new Query( "descendent_of", args ); // // Obtain the first solution to return // java.util.Hashtable solution = query.oneSolution(); return (Atom)solution.get( X ); }
Executing 'query.oneSolution()' calls SWI-prolog, emitting the variable and name. By executing 'solution.get( X )', the Java method receives back some atom bound to X. We have to cast the return value to Atom type because the returned value is of 'Object' type.
We show the part of the program up to test3 method (list[prologServ.java]). The sample is almost identical with the one shown to illustrate basic usage of Servlet. Points to note are:
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; // // JPL package // import jpl.Atom; import jpl.Variable; import jpl.Term; import jpl.Query; import jpl.JPL; public class prologServ extends HttpServlet { public void doGet ( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException { res.setContentType( "text/html" ); PrintWriter out = res.getWriter(); out.println( "<html><head><title>Finding decendents of the person</title></head>" ); out.println( "<body>Using getParameter() method<br>" ); JPL.init(); // We initialize JPL Term consult_arg[] = { // // We have to specify the location of prolog program in full // new Atom( "/usr/local/jakarta-tomcat/webapps/proServ/WEB-INF/classes/test.pl" ) }; // // We consult 'test.pl' // Query consult_query = new Query( "consult", consult_arg ); boolean consulted = consult_query.query(); if ( !consulted ){ out.println( "Consult failed" ); System.exit( 1 ); } Enumeration enum = req.getParameterNames(); while( enum.hasMoreElements() ) { String name = (String)enum.nextElement(); String value = req.getParameter( name ); out.println( name + "=" + value + "<br>" ); // // We pass the task to test3 below // String descendent = test3( value ).name(); out.println( "descendent = " + descendent + "<br>" ); } out.println( "</body></html>" ); out.close(); } static Atom test3( String person ) { ( ... Suppressed ... ) } public void doPost ( ... Suppressed ... ) }
We create the application named 'proServ' under some working directory and build it as explained above. Upon entering the address, 'http://127.0.0.1:8080/proServ/index.html', you are prompted to enter a name of person, whose descendent we like to know of (figure[Query window]). We type in 'ralf' for this example.
Upon cliking 'SUBMIT', you are shown the result that 'joe' is a descendent of 'ralf', which was inferred by prolog (figure[Result]).
You can check that the prolog program is loaded on the starting window of Tomcat (Monitoring invocation of prolog.html)
( ... Suppressed ... ) Context log: path="/admin" Automatic context load docBase="C:\cygnus\usr\local\jakarta-tomcat\webapps\admin" Context log: path="/admin" Adding context path="/admin" docBase="C:\cygnus\usr\local\jakarta-tomcat\webapps\admin" % /usr/local/jakarta-tomcat/webapps/proServ/WEB-INF/classes/test.pl compiled 0.09 sec, 1,344 bytes
All the files comprising proServ application are found in Appendix.
Calling prolog program from Servlet did not work on Windows95 for my case. Please share your experience if you tried to do the same on Windows95.