From 3e1e9110ef7a677032a03b2764e098a5b600b769 Mon Sep 17 00:00:00 2001 From: Jakub Skoczen Date: Thu, 18 Feb 2010 14:33:50 +0100 Subject: [PATCH] Add doc/tutorial. --- examples/zgate/doc/ARTICLE | 213 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 examples/zgate/doc/ARTICLE diff --git a/examples/zgate/doc/ARTICLE b/examples/zgate/doc/ARTICLE new file mode 100644 index 0000000..573b552 --- /dev/null +++ b/examples/zgate/doc/ARTICLE @@ -0,0 +1,213 @@ +BUILDING A SIMPLE HTTP-TO-Z3950 GATEWAY USING YAZ4J AND TOMCAT +============================================================== + +[Yaz4J](http://www.indexdata.com/yaz4j) is a wrapper library over the +client-specific parts of YAZ, a C-based Z39.50 toolkit, and allows you to use +the ZOOM API directly from Java. +[ZOOM](http://zoom.z3950.org/api/zoom-1.4.html) is a relatively straightforward +API and with a few lines of code you can write a basic application that can +establish connection to a Z39.50 server. +Here we will try to build a very simple HTTP-to-Z3950 gateway using yaz4j and +the Java Servlet technology. + +## COMPILING AND INSTALLING YAZ4J + +Yaz4j is still an experimental piece of software and as such is not distributed +via Index Data's public Debian apt repository and there is no Windows installer +either. While it is possible to use the pre-built Linux binaries, users of +other OSes will have compile yaz4j from source. No need to worry (yet) - the +process of compiling yaz4j is quite simple and we will be up and running in no +time :). The source code can be checked-out out from our +[Git repository](http://git.indexdata.com/?p=yaz4j.git;a=summary), and assuming +you have Git installed on your machine you can do that with: + + git clone git://git.indexdata.com/yaz4j + +The compilation of both native and Java source code is controlled by Maven2, +to build the library, invoke the following commands: + + cd yaz4j + mvn install + +That's it. If the build has completed successfully you end up with two files: +os-independent jar archive with Java ZOOM API classes +(yaz4j/any/target/yaz4j-any-VERSION.jar) and os-dependent shared library +(yaz4j/linux/target/libyaz4j.so or yaz4j/win32/target/yaz4j.dll) that contains +all necessary JNI "glue" to make the native calls possible from Java. If we were +writing a command line Java application, like any other external Java library, +yaz4j-any-VERSION.jar would have to be placed on your application classpath +and the native, shared library would have to be added to your system shared +library path (LD_LIBRARY_PATH on linux, PATH on Windows) or specified as a +Java system property (namely the java.library.path) just before your +application is executed: + + java -cp /path/to/yaz4j-*.jar -Djava.library.path=/path/to/libyaz4j.so MyApp + +## SETTING UP THE DEVELOPMENT ENVIRONMENT + +Setting up a development/runtime environment for a web (servlet) application is +a bit more complicated. First, you are not invoking the JVM directly, but the +servlet container (e.g Tomcat) run-script is doing that for you. At this +point the shared library (so or dll) has to be placed on the servlet container's +shared libraries load path. Unless your library is deployed to the standard +system location for shared libs (/usr/lib on Linux) or it's location is already +added to the path, the easiest way to do this in Tomcat is by editing +(create it if it does not exist) the CATALINA_HOME/bin/setenv.sh (setenv.bat on +Windows) script and putting the following lines in there: + + LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libyaz4j.so + export LD_LIBRARY_PATH + +on Windows + + set PATH=%PATH;X:\path\to\yaz4j.dll + +That's one way of doing it, another would be to alter the standard set of +arguments passed to the JVM before the Tomcat starts and add +-Djava.library.path=/path/to/lib there. Depending on a situation this might be +preferable/easier (on Debian/Ubuntu you can specify JVM arguments using +/etc/default/tomcat6). + +With the shared library installed we need to install the pure-Java yaz4j-any*jar +with ZOOM API classes by placing it in Tomcat's `lib` directory +(CATALINA_HOME/lib). As this library makes the Java System call to load the +native library into the JVM you cannot simply package it along with your web +application (inside the .war file) - it would try to load the library each time +you deploy the webapp and all consecutive deployments would fail. + +## WRITING A SERVLET-BASED GATEWAY + +With your servlet environment set up all that is left is to write the actual +application (peanuts :)). At IndexData we use Maven for managing builds of our +Java software components but Maven is also a great tool for quickly starting up +a project. To generate a skeleton for our webapp use the Maven archetype plugin: + + mvn -DarchetypeVersion=1.0.1 -Darchetype.interactive=false -DarchetypeArtifactId=webapp-jee5 -DarchetypeGroupId=org.codehaus.mojo.archetypes -Dpackage=com.indexdata.zgate -DgroupId=com.indexdata -DartifactId=zgate archetype:generate --batch-mode + +This will generate a basic webapp project structure: + +|-- pom.xml +`-- src +|-- main +| |-- java +| | `-- com +| | `-- indexdata +| | `-- zgate +| `-- webapp +| |-- WEB-INF +| | `-- web.xml +| `-- index.jsp +`-- test + `-- java + `-- com + `-- indexdata + `-- zgate + +Maven has already added basic JEE APIs for web development as the project +dependencies, we need to do the same for yaz4j, so edit the `pom.xml` and +add the following lines in the `dependencies` section: + + + org.yaz4j + yaz4j-any + VERSION + provided + + +It's crucial that the scope of this dependency is set to `provided` otherwise +the library would end up packaged in the .war archive and we don't want that. + +The implementation of our simple gateway will be contained in a single servlet - +`ZGateServlet` - which we need to place under `src/main/webapp/com/indexdata/zgate.` +The gateway will work by answering HTTP GET requests and will be controlled +solely by HTTP parameters, the servlet doGet method is shown below: + +protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + String zurl = request.getParameter("zurl"); + if (zurl == null || zurl.isEmpty()) { response.sendError(400, "Missing parameter 'zurl'"); return; } + + String query = request.getParameter("query"); + if (query == null || query.isEmpty()) { response.sendError(400, "Missing parameter 'query'"); return; } + + String syntax = request.getParameter("syntax"); + if (syntax == null || syntax.isEmpty()) { response.sendError(400, "Missing parameter 'syntax'"); return; } + + int maxrecs=10; + if (request.getParameter("maxrecs") != null && !request.getParameter("maxrecs").isEmpty()) { + try { + maxrecs = Integer.parseInt(request.getParameter("maxrecs")); + } catch (NumberFormatException nfe) { + response.sendError(400, "Malformed parameter 'maxrecs'"); + return; + } + } + + response.getWriter().println("SEARCH PARAMETERS"); + response.getWriter().println("zurl: " + zurl); + response.getWriter().println("query: " + query); + response.getWriter().println("syntax: " + syntax); + response.getWriter().println("maxrecs: " + maxrecs); + response.getWriter().println(); + + Connection con = new Connection(zurl, 0); + con.setSyntax(syntax); + try { + con.connect(); + ResultSet set = con.search(query, Connection.QueryType.PrefixQuery); + response.getWriter().println("Showing " + maxrecs + " of " +set.getSize()); + response.getWriter().println(); + for(int i=0; i + ZgateServlet + com.indexdata.zgate.ZgateServlet + + + ZgateServlet + /zgate + + +On top of that, we will also make sure that our servlet is automatically +triggered when accessing the root path of our application: + + + zgate + index.jsp + + +Now we are ready to build our webapp: + + mvn package + +The resulting .war archive is located under `target/zgate.war`, we can deploy +it on tomcat (e.g by using the /admin Tomcat admin console) and test by issuing +the follwoing request with your browser or curl +(assuming Tomcat is running on localhost:8080): + + http://localhost:8080/zgate/?zurl=z3950.loc.gov:7090/voyager&query=@attr%201=7%200253333490&syntax=usmarc + + +That's it! You just build yourself a HTTP-to-Z3950 gateway! Just be careful +with exposing it to the outside world - it's not very secure and could be easily +exploited. The source code for the gateway's Maven project is attached. Also, +IndexData is working on a Debian/Ubuntu package (and maybe even a Windows +installer :)) and the installation of yaz4j and Tomcat configuration will be +greatly simplified - so stay tuned! -- 1.7.10.4