JSPのなかからScalaで記述したクラスを使うことを確かめてみました。
JSPページは、データベースをSelectしたScalaで記述したコードからのデータを JSP 側に渡して、JSP側でタグを付けするものです。
検索結果のレコードはjava.util.ArrayList を返し、要素はBeanに格納します。
このように実装した理由は、
1.ScalaのListではJava側から要素を取り出せなかったこと。
2.タプルだと格納できる要素数別のクラスとして返してくること
要素の取り出しがループで取れないこと
要素数に上限があることでデータベースのレコードを返すには問題があります。
3.JSON形式だとStringになってしまうのでデータベースのカラムの型が残らないこと
Beanのいいところは、表のカラム名を意識したコードが getEmpno のように書けること。ListやArrayだとどのカラムの値かはListやArrayに格納した実装を見ないとわからない。
Beanの課題は、事前にBeanクラスを作っておかなければならない。
Scalaで動的にクラスを定義する方法があるのか?
あるいは、別の方法が、、、
package SeeDo import java.util.Date class Employee ( var empno:Int, var ename:String, var job:String, var mgr:Int, var hiredate:Date, var deptno:Int, var varsal:Int ){ var Empno = empno var Ename = ename var Job = job var Mgr = mgr var Hiredate = hiredate var Deptno = deptno var Varsal = varsal def this() = this(0,null,null,0,null,0,0) def getEmpno = Empno def getEname = Ename def getJob = Job def getMgr = Mgr def getHiredate = Hiredate def getDeptno = Deptno def getVarsal = Varsal def setEmpno(value:Int):Unit = Empno = value def setName(value:String) = Ename = value def setJob(value:String) = Job def setMgr(value:Int) = Mgr def setHiredate(value:Date) = Hiredate = value def setDeptno(value:Int) = Deptno = value def setVarsal(value:Int) = Varsal = value override def toString() = "[Employee empno:"+Empno+",ename:"+Ename+",job:"+Job+",mgr:"+Mgr+",hiredate:"+Hiredate+",deptno:"+Deptno+",varsal:"+Varsal+"]" }
package SeeDo import java.util.ArrayList object Control { def using[A <: {def close():Unit},B](param:A)(f:A => B):B= try { f(param) }finally { param.close() } def bmap[T] (test: => Boolean)(block: => T):ArrayList[T] = { var ret = new ArrayList[T] while(test){ ret.add(block) // println("size="+ret.size()+" bmap="+block) } ret } }
データベースをSelectするクラスは、Scalaらしく findEmp関数になりました。
package SeeDo import java.sql.{DriverManager, Connection, Statement, ResultSet,SQLException} import java.util.ArrayList class Emp { val jdbcURL = "jdbc:oracle:thin:@192.168.0.105:1521:ORCL" val user ="scott" val passwd ="tiger" def oracle() : ArrayList[Employee] = { Class.forName("oracle.jdbc.driver.OracleDriver").newInstance() var conn:Connection = null var list:ArrayList[Employee] = null try { conn = DriverManager.getConnection(jdbcURL,user,passwd) list = findEmp(conn) } catch { case e:SQLException => println("Database error "+e) case e => { println("Some other exception type:") e.printStackTrace() } } finally { conn.close() } list } def findEmp(conn:Connection): ArrayList[Employee] = Control.using (conn.createStatement){st => Control.using (st.executeQuery("SELECT * FROM EMP")){rs => Control.bmap(rs.next){ new Employee( rs.getInt("empno") ,rs.getString("ename") ,rs.getString("job") ,rs.getInt("mgr") ,rs.getDate("hiredate") ,rs.getInt("deptno") ,rs.getInt("sal") ) } } } }
JSP のなかで自分1レコード単位で記述したいので、for ループで処理します。
ScalaのEMP表のBeanオブジェクトがJSP ( Java ) のなかで機能してます。
<%@ page contentType="text/html;charset=MS932" %> <%@ page import = "java.util.*" %> <%@ page import = "scala.*" %> <%@ page import = "SeeDo.*" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html LANG="ja-JP"> <head><title>Scala test</title></head> <BODY><TABLE border='1'> <% Emp o = new Emp(); ArrayList list = o.oracle(); %> <TR><TH>Class</TH><TD><%= o.getClass() %></TD></TR> <TR><TH>Class</TH><TD><%= list != null ? list.getClass() : "-" %></TD></TR> <TR><TH>ArrayList size</TH><TD><%= list != null ? list.size() : "-" %></TD></TR> </TABLE><BR> <TABLE border='2'> <% for(int i=0;i < list.size() ;i++){ Employee e = (Employee)list.get(i); %> <TR><TH><%=i%></TH> <TD><%= e.getEmpno() %></TD> <TD><%= e.getEname() %></TD> <TD><%= e.getJob() %></TD> <TD><%= e.getMgr() %></TD> <TD><%= e.getHiredate() %></TD> <TD><%= e.getDeptno() %></TD> <TD><%= e.getVarsal() %></TD> </TR> <% } %> </TABLE> </BODY></html>
処理結果は、EMP表のデータをテーブル化します。
余談
Scalaが普及すれば JSP のように Scala と HTML をいっしょに記述できる SSP? なんてものがリリースされるのでしょうね。
Webデザイナの方ならTaglibの方がいいのかもしれませんが、Taglibを覚えたくないのでHTMLのなかに直接コードが書ける方が好みです。しかし、Webデザイナも JavaScript の知識なしにはWebもデザインできないでしょうからHTMLにコードがあることは違和感ではないと思う次第です。JSP なら Java と JavaScript とコードスタイルが違うので区別しやすいのですが、ScalaとJavaScriptだとどうなんでしょうね。
そういう実装を試みている方もいらっしゃいますが、是非とも本格的に利用できるものへ発展して欲しいです。