% ============================================================================= % The CGAL Developers' Manual % Chapter: The CGAL Java Demo Server % ----------------------------------------------------------------------------- % file : java_demos.tex % authors: Francois Rebufat % ----------------------------------------------------------------------------- % $Revision$ % $Date$ % ============================================================================= \chapter{The \cgal\ Java Demo Server} \label{chap:java_demos} \ccChapterRelease{Chapter Version: 1.0} \\ \ccChapterAuthor{Fran\c cois Rebufat (\texttt{Francois.Rebufat@sophia.inria.fr})} \ccIndexMainItemBegin{Java demo server} The internet is one of the best ways to present, promote, and distribute application software and libraries. Commonly, web sites offer a textual description of the software product, online (or downloadable) documentation, the possibility to download the software itself, and sometimes a demo version (often limited in its features) that interested users can download and install to test if the software fulfills their needs. To decide upon the applicability and usability of a software product, a potential user generally has no other alternative than to download the software and go though the sometimes difficult installation process. This step often discourages users since installation frequently does not work as it should. The \cgal\ Java demo server presents an alternative method of evaluating the library. The demo server provides a Java applet that accepts input from the user, stores it, ships it to a local server, which performs the desired computation on the data using \cgal, and then ships the results back to the client web navigator where the results are displayed. To achieve this, two obstacles must be overcome: \begin{itemize} \item enabling an interface between Java applets and programs written in another language (\CC\ for \cgal) \item distributing data through the web, between the Java applet and the \cgal\ server. \end{itemize} Two new Java tools, \ccAnchor{http://java.sun.com/products/jdk/1.1/docs/guide/jni/}{Java Native Interface} (JNI) and \ccAnchor{http://java.sun.com/products/jdk/1.1/docs/guide/rmi/}{Remote Methods Invocation} (RMI), were chosen as the means to overcome these obstacles. In the following, we will briefly present these tools and describe in detail how we built the online \cgal\ demo. We do not provide a complete introduction to JNI and RMI and invite interested programmers to have a look at the \ccAnchor{http://www.javasoft.com}{javasoft} reference pages \lcTex{(\path|http://www.javasoft.com|)} for more details. The solutions we chose and the structure we present are not unique and smart programmers will probably find their own way through the JNI and RMI process. \section{The Java tools : JNI and RMI} \label{sec:jmi_and_rmi} The JNI and RMI tools are parts of \ccAnchor{http://java.sun.com/products/jdk/1.1/}{JDK-1.1}. By using these tools, we simulate a multi-language object distributed application through the web. Since the Java security manager is enabled, security is guaranteed for the client and the server. This kind of application could rapidly become messy and error prone. For this reason, we describe with simple pseudo-code how to deal with JNI and RMI before explaining the \cgal\ demo. \subsection{The JNI part} \label{sec:jni_part} \ccIndexSubitemBegin{Java demo server}{JNI} The JNI allows Java code that runs within a Java Virtual Machine to operate with applications and libraries written in other languages, such as C or \CC. For this, JNI defines standardized naming and calling conventions used by the Java Virtual Machine to call native methods and functions. A minimal JNI application consists of five files : \begin{description} \item[{\tt foo\_prog.C}] A native-language (\eg, \CC) program that implements, let's say, a function named \ccc{foo()}. \item[{\tt N\_foo.java}] A Java class that declares the Java function \ccc{cpp_foo()} as a native function. This class uses the JNI loading method \ccc{System.loadLibrary("libfoo")} to establish that the implementation of the native function is in the \texttt{libfoo.so}. (We will see later how \texttt{libfoo.so} is built.) \item[{\tt N\_0005ffoo.h}] An header file automatically obtained from \ccc{N_foo.java} by compiling it with the \texttt{javah -jni} command. This file declares, using the JNI naming convention, the \ccc{Java_N_1foo()} function interface between the Java \ccc{cpp_foo()} and the \CC\ \ccc{foo()} function. \item[{\tt N\_implementation\_foo.C}] Implements the \ccc{Java_N_1foo()} function that calls the \CC\ \ccc{foo()} function. \item[{\tt libfoo.so}] A dynamic library that contains the functions \ccc{foo()} defined in \texttt{foo\_prog.C} and \ccc{N_implementation_foo.C}. \end{description} Figure~\ref{fig:jni_files} shows the five files and their interdependencies. \begin{figure} \begin{ccTexOnly} \begin{center} \includegraphics[width=14cm]{jnis.eps} \end{center} \end{ccTexOnly} \caption{The files of a minimal JNI application. \label{fig:jni_files}} \begin{ccHtmlOnly}
JNI files
\end{ccHtmlOnly} \end{figure} In the main Java program (or applet), we will call the \ccc{cpp_foo()} member function of the class \ccc{N_foo}. This function knows that it is a native implementation and can find its definition in the \texttt{libfoo.so} file. All these functions and methods are parametrized and can exchange their resulting values. We will explain in the case of the \cgal\ demo how we chose to do that in Section~\ref{sec:cgal_demo}. \ccIndexSubitemEnd{Java demo server}{JNI} \subsection{The RMI part} \label{sec:rmi_part} \ccIndexSubitemBegin{Java demo server}{RMI} \begin{quote} RMI enables the programmer to create distributed Java-to-Java applications, in which the methods of remote JavaTM objects can be invoked from other Java virtual machines, possibly on different hosts. A Java technology program can make a call on a remote object once it obtains a reference to the remote object, either by looking up the remote object in the bootstrap-naming service provided by RMI, or by receiving the reference as an argument or a return value. A client can call a remote object in a server, and that server can also be a client of other remote objects. RMI uses Object Serialization to marshal and unmarshal parameters and does not truncate types, supporting true object-oriented polymorphism. \hspace*{\fill}{\em JDK documentation (Javasoft)} \end{quote} We will neither discuss nor explain the whole structure of RMI mechanism here, since it is a fairly complicated thing (refer to the the \ccAnchor{http://java.sun.com/products/jdk/1.1/docs/guide/rmi/}{javasoft reference pages}\lcTex{\footnote{\path|http://www.javasoft.com/products/jdk/1.1/docs/guide/rmi/index.html|}}). Globally RMI works as follows. An RMI server is declared and bound to the httpd server of the local server. A remote object, \texttt{Remote\_object}, that implements a remote interface is declared on this server. \texttt{Remote\_object} distributes data members and methods between the server and the client sides by using ``stub'' and ``skeleton'' layers that are directly built from \texttt{Remote\_object}. The stub is the client-side interface for \texttt{Remote\_object}, while the skeleton is the server-side interface. The following figure describes the general structure of RMI. \begin{ccTexOnly} \begin{center} \includegraphics[width=14cm]{rmi.eps} \end{center} \end{ccTexOnly} \begin{ccHtmlOnly}
RMI structure
\end{ccHtmlOnly} The remote reference layer deals with the lower-level transport interface. This layer is also responsible for carrying out a specific remote reference protocol, which is independent of the client stubs and server skeletons. The transport layer deals with connections and listening for calls and maintains a table of remote objects that reside in the address space. As we did for the JNI part, we present here a set of files that illustrate a minimal implementation using RMI. The programer has to write three files: the applet itself, an interface for the remote object, and the remote object itself. Two other files, the stub and the skeleton, are generated from the remote object. \begin{description} \item[{\tt RemoteInterface.java}] A public Java interface that declares all the functions used remotly by the remote object. \item[{\tt RemoteObject.java}] A public Java class that implements the RemoteInterface. The functions declared in the interface are implemented and distributed object data members are defined. It contains a main function to set an RMI security manager and to bind the object to the RMI server. \item[{\tt Myapplet.java}] An applet that declares objects of type \ccc{RemoteInterface} and applies functions from the interface to them. \item[{\tt RemoteObject\_Skel.class}, {\tt RemoteObject\_Stub.class}] These two files are automatically obtained by using the RMI compiler with the following command: {\tt rmic RemoteObject}. \end{description} The following picture shows the main content of the first three files. \begin{ccTexOnly} \begin{center} \includegraphics[width=13cm]{rmifile.eps} \end{center} \end{ccTexOnly} \begin{ccHtmlOnly}
RMI structure
\end{ccHtmlOnly} \ccIndexSubitemEnd{Java demo server}{RMI} \section{The \cgal\ demo} \label{sec:cgal_demo} You can see this demo and download the source files from \path|http://cgal.inria.fr/| As there are two separate parts, the JNI and RMI parts, we split the demo files in two directories \texttt{jni} and \texttt{rmi}. In the following two sections, we describe both these directories and explain step by step how to build executable files. Then, a simulation of the execution of the two parts will show how calls are managed and objects and variables distributed. \subsection{The \texttt{jni} directory} \label{sec:jni_directory} \index{Java\ demo\ server!\texttt{jni} directory|(} The files contained in this directory are exactly the same as those described in the Section~\ref{sec:jni_part}, except that there are more \CC\ files -- one for each \cgal\ object shown in the demo. The four files, \texttt{ConvexHull.C}, \texttt{cgal\_triangulation.C}, \texttt{polygons\_operations.C} and \texttt{triangulation\_operation.C} define their own objects and member functions that directly use \cgal\ objects and functions. For instance, \texttt{ConvexHull.C} implements a class \ccc{Cpp_Convexhull} with three data members, two arrays of \ccc{long}s for the point set $x$- and $y$-coordinates and one integer to store the total number of points. It has one member function, \ccc{ConvexHull}, that computes the convex hull of the point set, returns its size and stores the result in two arrays. The file \texttt{N\_Operation.java} declares the JNI interface functions and loads their definitions in the \texttt{linjni.so} library. The file \texttt{NimpOperations.C} implements these functions. Arguments and results are passed by pointers (arrays). \subsubsection{Adding functionality in the \texttt{jni} directory} \label{sec:new_jni_functionality} \index{Java\ demo\ server!adding functionality|(} To add some functionality, you have to perform the following steps: \begin{itemize} \item Edit a new file, for instance \texttt{new\_object.C}, that defines and implements the class for the object you want to add and the functionality on this object. Add \texttt{new\_object.o} to the list of objects files in the makefile. \item Edit \texttt{N\_Operations.java} and add a function that corresponds to the one written in the \texttt{new\_object.C} file. Compile \texttt{N\_Operations.java} using: \\ \centerline{\texttt{javac N\_Operations.java }} \item Build the header \texttt{N\_0005fOperations.h}: \\ \centerline{\texttt{javah -jni N\_Operations}} \item Edit the file \texttt{NimpOperations.C} and add the definition of the function corresponding to the one you've added in the \texttt{N\_Operations.java}. The syntax of this function must correspond exactly to the one defined in the \texttt{N\_0005fOperations.h} header file (copy and paste it). \item Set your {\tt LD\_LIBRARY\_PATH} variable \index{LD_LIBRARY_PATH variable@{\tt LD\_LIBRARY\_PATH} variable!for Java demo} so it contains the path of \texttt{libCGAL}, \texttt{libLEDA} (if \leda\ is used) and the \texttt{jni} directory. Set the \texttt{CLASSPATH} variable \index{CLASSPATH variable@{\tt CLASSPATH} variable} as for any Java application. Type {\tt make} to build all the ".o" files and the \texttt{libjni.so} library. \end{itemize} \index{Java\ demo\ server!adding functionality|)} \index{Java\ demo\ server!\texttt{jni} directory|)} \subsection{The \texttt{rmi} directory} \label{sec:rmi_directory} \index{Java\ demo\ server!\texttt{rmi} directory|(} We assume that the reader knows what an applet is and how events are handled in Java. The \texttt{rmi} directory contains only Java files, so knowing a little bit of Java is necessary to read the different files it contains. The structure as described in Section~\ref{sec:rmi_part}. The applet is named \texttt{CgalApplet} and contains the applet itself, a class named \ccc{PointZone} that extends \ccc{Canvas} and deals with the graphical part of the application, a class \ccc{Zone} that defines remote objects, contains methods to build them, tries to look for the RMI server and records remote objects. The \ccc{Zone} class also defines functions that call remote functions and stores results and data into its data members. Several classes, such as \ccc{MouseAdapter} and \ccc{Point_set} are defined for convenience. The two others files in this directory are \texttt{RemoteInterfaceOperations.java} and \texttt{OperationsImpl.java}. They contain remote functions to compute the several functionalities the demo offers and \ccc{get} methods to send results to the applet. All data are stored in arrays of integers that contain either $x$ or $y$ coordinates. Thus, a whole set of points is stored in two arrays. We define four pairs of arrays : {\bf Input arrays } : Store data (the user's set of points) that is produced by clicking on the screen. The arrays \ccc{X} and \ccc{Y} contain the base set of point, and the arrays \ccc{Xs} and \ccc{Ys} contain special points such as segments extremities used for the line-face circulator. {\bf Output arrays } : Store the results of computation. As for the input arrays, there are two pairs of output arrays: \ccc{X_c}, \ccc{Y_c} for the global results (such as for convex hull, triangulation) and \ccc{Xs_c}, \ccc{Ys_c} for additional results such as the faces traversed by a line-face circulator. \subsubsection{Adding functionality in the \texttt{rmi} directory} \label{sec:new_rmi_functionality} \index{Java\ demo\ server!adding functionality|(} Adding only new events, or automatically generated sets of points does not involve the RMI part. Only the applet and the event manager must be completed and this is pure java programming. To add new functionality (\eg, Voronoi diagrams) follow the steps outlined in Section~\ref{sec:new_jni_functionality} to add the functionality to the \texttt{jni} directory. Then proceed as follows : \begin{itemize} \item Edit the \texttt{RemoteInterfaceOperations.java} file and add a new function. For the sake of example, let's call it \ccc{voronoi}. Compile this file using the command: \\ \centerline{\texttt{javac RemoteInterfaceOperations.java}} \item Edit the \texttt{OperationsImpl.java} file and define the new \ccc{voronoi} function. The core of the \ccc{voronoi} function will build a new object of type \ccc{N_Operations} (JNI part) and call \ccc{cpp_voronoi} defined in the \texttt{N\_Operation.java} file. Here is the link between the JNI and the RMI parts. Compile \texttt{OperationsImpl.java}: \\ \centerline{\texttt{javac OperationsImpl.java}} The \texttt{LD\_LIBRARY\_PATH} and \texttt{CLASSPATH} must contain the \index{LD_LIBRARY_PATH variable@{\tt LD\_LIBRARY\_PATH} variable!for Java demo} \index{CLASSPATH variable@{\tt CLASSPATH} variable} path of the JNI part in order for it to find the file \texttt{N\_Operation.class}. \item Build the stub and skeleton files: \\ \centerline{\texttt{rmic OperationsImpl}} \item Edit the \texttt{CgalApplet.java} and add your new functionnality in the menu, define how to draw your object, and use the \ccc{Zone} constructor to build a new remote object. Compile the applet: \\ \centerline{\texttt{javac CgalApplet.java}} \end{itemize} Now that everything is compiled, you have to launch the RMI Bootstrap Registry: \\ \centerline{\texttt{rmiregistry \&}} Then launch the code server: \centerline{\texttt{java -Djava.rmi.server.codebase=http://cgal.inria.fr/DEMO/rmi/OperationsImpl \&}} The server should answer: \texttt{server bound in registry}. \index{Java\ demo\ server!adding functionality|)} \index{Java\ demo\ server!\texttt{rmi} directory|)} \subsubsection{Through the global process: A convex hull example} \label{sec:java_demo_example} We describe the entire process for the example when points are entered with the mouse by the user and then "convex hull" is chosen from the menu. Each time the user presses the left mouse button in the graphic canvas, $x$- and $y$-coordinates are sent and stored in \ccc{X}, \ccc{Y} arrays (in class \ccc{Zone}). Selecting ``convex hull'' from the menu causes the applet's \ccc{redraw} method to be called. The \ccc{redraw} method chooses the \ccc{convex_hull} drawing method that calls the \ccc{convex_hull} method in the class \ccc{Zone}. The \ccc{convex_hull} method from the class \ccc{OperationsImpl.class} is then called upon the \ccc{Zone} data member \ccc{convex_remote}. An \ccc{N_Operations} object is built and the method \ccc{cpp_convex_hull(X,Y,number_of_points,Xresult,Yresult)} is executed on it. Here, \ccc{Xresult} and \ccc{YResult} will store the results as member of the object \ccc{convex_remote}. In the JNI part, \ccc{cpp_convex_hull} translates java arrays to \CC\ arrays, builds an object of the class \ccc{Cpp_ConvexHull} (defined in \texttt{Convex\_hull.C}) and applies \ccc{ConvexHull(X_c,Y_c)} to it. The results are stored in the arguments of this function (\ccc{X_c} and \ccc{Y_c}), then sent to the arguments corresponding to \ccc{Xresult} and \ccc{Yresult} in the call to \ccc{cpp_convex_hull}, stored in the data members of the \ccc{convex_remote} object, and grabbed by the Java applet by using the \ccc{getXresult} and \ccc{getYresult} methods. The applet then displays what is stored in the \ccc{X_c} and \ccc{Y_c} arrays. \ccIndexMainItemEnd{Java demo server}