JLink と Web service
JLink のサンプル
ビルドにはふつう make とか ant を使うが、ここでは単発 self-contained を目指したいので、Windows OSのもとでバッチファイルを作成しビルドする。UNIX環境(Cygwinも含む)だったらシェルスクリプトが相当するけど、普通の人は makefile を書く。MacOSのことはMac使いに聞いてください。
- JLinkTest.java
import com.wolfram.jlink.*; public class JLinkTest { public static void main(String[] argv) { if (argv.length == 0){ argv = new String[]{"-linkname", "C:\\Program Files\\Wolfram Research\\Mathematica\\9.0\\MathKernel.exe"}; } KernelLink ml = null; try { ml = MathLinkFactory.createKernelLink(argv); } catch (MathLinkException e) { System.out.println("Fatal error opening link: " + e.getMessage()); return; } try { // カーネルが起動したときに送る // 最初のInputNamePacketを捨てる. ml.discardAnswer(); ml.evaluate("2+2"); ml.waitForAnswer(); int result = ml.getInteger(); System.out.println("2 + 2 = " + result); // 結果を文字列として得たい場合は,getIntegerでなく // getString } catch (MathLinkException e) { System.out.println("MathLinkException occurred: " + e.getMessage()); } finally { ml.close(); } } }
- コンパイル
makeJLinkTest.bat を以下の内容で作成する。
javac -classpath "C:\Program Files\Wolfram Research\Mathematica\9.0\SystemFiles\Links\JLink\JLink.jar";. JLinkTest.java
そしてコンパイルの実行は
makeJLinkTest
- 実行方法
java JLinkTest
JLink.jar への CLASSPATH を通していない人は、ここで -classpath オプションを使う必要がある。例えば
java -classpath ..JLink.jarへの絶対path... JLinkTest
Tomcat の独自テスト
指示に従って必要なファイルを作成し、この図のように配置していく。
□Program Files └□Apache Software Foundation └□Tomcat 7.0 ├□conf │└□Catalina │ └□localhost │ └◇test.xml ... 新規作成 └□webapps └□test ... ここ以下を新規作成 ├◇startpage.html ... 新規作成 └□WEB-INF ├□classes │└◇HelloMath.class ├□lib │├◇JLink.jar ... ここにMathematicaのディレクトリーからコピーして来る │└□SystemFiles ... 欲しいのは末端の DLL ファイルだけだが階層を以下のようにつくってコピーする │ └□Libraries │ └□Windows-x86-64 │ └◇JLinkNativeLibrary.dll ... これが欲しかった └◇web.xml
test.xml を以下の内容で作成し指定場所に配置する。
<Context path="/test" docBase="C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\test" reloadable="false" />
test ディレクトリーを作成し、以下の startpage.html を配置する。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J"> <title> Start Page </title> </head> <body> <form method="post" action="HelloMath"> x= <input type="text" name="x"><br> <br> y= <input type="text" name="y"><br> <br> <input type="submit" value="submit"> </form> </body> </html>
この段階でテストを実行しよう。Tomcat を再起動して
http://localhost:8080/test/startpage.html
にアクセスしたら x と y を入力し、submit するフォームが表示されるはずだ。でも、まだ submit ボタンを押してもエラーが帰ってくるだけだ。まだ、その後の処理をする servlet を作成していないから。
Servlet を作成し Tomcat に登録するまで
Submit ボタンが押されたら servlet の登場となる。その部分はこれから作成する。
HelloMath.java を作成する。HelloMath は startpage.html で submit ボタンが押されたときにTomcat上で起動されるservletである。このバージョンではMathematicaへの接続はせずに、自前で足し算を実行し、解答ページを作成しクライアントに戻す。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import com.wolfram.jlink.*; public class HelloMath extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ int result = 0; try { int x = Integer.parseInt(request.getParameter("x")); int y = Integer.parseInt(request.getParameter("y")); result = x+y; } catch (NumberFormatException e){ result = -999; } response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Hello World!</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello World!</h1>"); out.println("x + y = " + result); out.println("</body>"); out.println("</html>"); } }
コンパイルは makeHelloMath.bat で行う。これは一行で。
javac -classpath スペース "C:\Program Files\Apache Software Foundation\Tomcat 7.0\lib\servlet-api.jar; スペースも改行も不可 C:\Program Files\Wolfram Research\Mathematica\9.0\SystemFiles\Links\JLink\JLink.jar";. HelloMath.java
出来上がった class ファイルを先の配置図にあるように適切にコピーする。
実行は、Tomcat の再起動と、場合によってはブラウザーのキャッシュをクリアしなければならない。ブラウザーを再起動するのが確実だ。
Servlet から JLink 経由で Mathematica に接続する
startpage2.html を以下のように作成し、先ほどの startpage.html と同じディレクトリーに配置する。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J"> <title> Start Page </title> </head> <body> <form method="post" action="HelloMath2"> x= <input type="text" name="x"><br> <br> y= <input type="text" name="y"><br> <br> <input type="submit" value="submit"> </form> </body> </html>
HelloMath2.java を以下のように作成する。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import com.wolfram.jlink.*; public class HelloMath2 extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ String x = request.getParameter("x"); String y = request.getParameter("y"); String result = null; String[] argv = new String[] {"-linkname", "C:\\Program Files\\Wolfram Research\\Mathematica\\9.0\\MathKernel.exe"}; KernelLink ml = null; try { ml = MathLinkFactory.createKernelLink(argv); } catch (MathLinkException e) { System.out.println("Fatal error opening link: " + e.getMessage()); return; } try { // カーネルが起動したときに送る // 最初のInputNamePacketを捨てる. ml.discardAnswer(); ml.evaluate("Plus[" + x + "," + y + "]"); ml.waitForAnswer(); result = ml.getString(); } catch (MathLinkException e) { System.out.println("MathLinkException occurred: " + e.getMessage()); } finally { ml.close(); } response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Hello World!</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello World!</h1>"); out.println("x + y = " + result); out.println("</body>"); out.println("</html>"); } }
コンパイル用のバッチファイルは以下の内容で makeHelloMath2.bat とする。1行のみ。
javac -classpath スペース "C:\Program Files\Apache Software Foundation\Tomcat 7.0\lib\servlet-api.jar;改行もスペースも不可 C:\Program Files\Wolfram Research\Mathematica\9.0\SystemFiles\Links\JLink\JLink.jar";. HelloMath2.java
コンパイル成功したら、HelloMath2.class を HelloMath.class と同じディレクトリにコピーする。
web.xml を以下のように加筆修正する。
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <servlet> <servlet-name>HelloMath</servlet-name> <servlet-class>HelloMath</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloMath</servlet-name> <url-pattern>/HelloMath</url-pattern> </servlet-mapping> <servlet> <servlet-name>HelloMath2</servlet-name> <servlet-class>HelloMath2</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloMath2</servlet-name> <url-pattern>/HelloMath2</url-pattern> </servlet-mapping> </web-app>