Octave – java – MySQL

Des de fa uns temporada estic involucrat en el manteniment d’una aplicació que combina una aplicació web d’anàlisi financera feta amb Java, una base de dades Oracle i un motor de càlcul suportat per Matlab. El motor de càlcul Matlab agafa i emmagatzema directament de la base de dades Oracle.

Una cosa que se’m va passar immediatament pel cap va ser com es podria implementar aquesta aplicació fent servir, exclusivament, programari lliure. Per als puristes, dir que incloc al Java en aquesta categoria de Programari Lliure, i també incloc, si més no, de moment, la base de dades MySQL. PostgreSQL també és una candidata interessant a base de dades. El PL/pgSQL de PostgreSQL és un factor a tenir molt en compte.

El tercer element de l’arquitectura, el motor de càlcul, tenia uns quants candidats. Octave és compatible a un 95% amb el llenguatge “.m” que s’escriu per a Matlab. FreeMat i Scilab també incorporen un llenguatge molt compatible amb el de matlab. Últimament, a més, també caldria tenir en compte també el llenguatge R. R, però, no és compatible amb Matlab de la forma gairebé directa que ho són Octave, Freemat o Scilab.

Val a dir també que Octave, Freemat i Scilab presenten diferències entre ells. Octave, per exemple, es presenta en consola de text, quan Scilab i Freemat ho fan en una GUI. Els llenguatges i propòsits d’Octave, Freemat i Scilab tampoc són exactament iguals entre ells ni amb Matlab. Octave és, des del meu punt de vista, el més proper a Matlab; Scilab sembla més orientat a les simulacions i es diria, per les toolboxes disponibles, que és més “d’enginyeria” que “matemàtic; Per la seva banda, Freemat té l’aspecte d’estar més orientat a la formació

Vet aquí també que una de les diferències entre Matlab, Octave, FreeMat i Scilab es dona justament en el punt que tm’havia cridat l’atenció: la interfície amb bases de dades.

A Scilab la solució general per estendre l’entorn i fer coses que inicialment no hi estan previstes, com atacar una base de dades, és desenvolupar scripts en llenguatge Tcl/Tk. Tcl/Tk forma part del core de Scilab. Així, per exemple, per atacar una base de dades Oracle caldria afegir el paquet Oratcl i fer un script tcl que ataqués la base de dades Oracle. Scilab proporciona l’entorn d’execució per a l’script tcl, i la interfície per passar objectes i dades entre l’script tcl i l’entorn Scilab.

Pel cas de MySQL la cosa es simplifica perquè hi ha un mòdul específic scilab-scimysql que en instal·lar-lo i activar-lo a un Scilab ens proporciona comandes que es poden fer servir directament dins els scripts .sce (l’equivalent als .m de matlab) per accedir a bases de dades MySql. És molt semblant a la combinació de Matlab + Oracle del sistema que estem mantenint.

El mòdul scilab-scimysql està disponible per instal·lar des del Synaptic (faig servir una Debian 7.0). Cal activar el MySQL Toolbox al menú d’eines:

scimysql

I també, un cop configurat l’entorn i l’accés a la base de dades, es poden executar les demos (menú d’ajuda)

Les demos es poden trobar a /usr/share/scilab/contrib/scimysql (alternativament, es pot descarregar de la pàgina web anterior el scimysql-0.1.1.tar.gz

FreeMat, per la seva banda només ofereix la possibilitat de carregar o escriure fitxers plans de text. Es disposa de la “Freemat External Interface” (FEI)) que permet extendre Freemat desenvolupant mòduls amb C. Sempre que tinguem una llibreria amb C per accedir a una base de dades, es podrà fer servir la FEI per a desenvolupar el mòdul que permeti fer la interfície amb els nostres scripts de Freemat. No és una opció per al desenvolupament ràpid.

Finalment, Octave disposa, per una banda, del package “database” amb el que se’ns ofereix connectivitat directa amb bases de dades de tipus PostgreSQL. Per altra banda també disposa del package octave-java que permet fer servir Java com a llenguatge per a estendre la funcionalitat de l’aplicació (el mateix que fa Scilab amb Tcl/Tk).

Disposar de Java a l’Octave és una opció molt poderosa. Mitjançant Java es pot accedir a totes les bases de dades per a les que existeixi un driver Jdbc, és dir, a la pràctica totalitat. No només a bases de dades: a qualsevol servei per al que es disposi de driver Java.

El package octave-java incorpora un reduït nombre de funcions que permeten instanciar objectes java i executar-ne els mètodes; obtenir els mètodes i atributs d’una classe; afegir classes i llibreries al classpath… Els tipus dels valors retornats pels mètodes executats des d’Octave de les instàncies dels objectes java es tradueixen als tipus propis d’Octave per a tipus simples, i es poden fer servir directament des les funcions pròpies d’Octave. Potser aquest és el punt més fluix d’aquesta llibreria: Es troba a faltar un mapeig directe entre algun tipus matricial de Java a les matrius d’Octave que són, en definitiva, el tipus bàsic d’aquesta aplicació.

Tenint en compte els criteris anteriors, la meva tria és Octave + Java + MySql. La tria de MySQL respon a un criteri banal: ja la tinc instal·lada amb el XAMPP. La tria d’Octave respon a le fet de poder fer servir Java, que és un llenguatge amb el que em trobo còmode.

No cal dir que les combinacions Octave + PostgreSQL (amb package octave-database), o Scilab + MySQL (amb Scilab MySQL Toolbox) ofereixen implementacions més directes al permetre accedir a les bases de dades des dels mateixos scripts “.m” d’Octave o “.sce” de Scilab, sense haver de passar per un script o aplicació externa en Java o Tcl/Tk.

Res millor que un exemple per veure com funciona.

Primer de tot, la descripció del programari involucrat:

GNU Linux Debian Versió 7.0 (wheezy) de 32 bits
GNU Octave, versió 3.6.2
MySQL 5.5.27 (el que va amb la versió de Xampp que tinc instal·lada).
Java JDK 1.7.0
Driver JDBC de MySQL mysql-connector-java-5.1.22-bin.jar
phpMyAdmin per a fer l’administració de la base de dades MySQL.
Eclipse Juno (IDE de Java)

El primer pas ha estat assegurar que el paquet octave-java està disponible. Si no ho està, es pot instal·lar des del Synaptic:

synaptic

Cal establir correctament la variable d’entorn JAVA_HOME.

El que vull és, des d’Octave,
1. crear una taula ‘prova’, amb tres camps (id int, clau varchar(50), valor varchar(50))
2. afegir-hi dades a la taula (insert)
3. modificar-ne alguns valors (update)
4. recuperar-los (select)

Com es pot aconseguir?

Em cal una classe Java d’utilitat. Només tres mètodes: executarSql(sql) per a Create, Insert, Update i Delete; i obrirCursor(sql) i tancarCursor() per a obtenir un ResultSet.

La classe java és aquesta:

OctaveMysql.java

package cat.stsoftlliure.octave.mysql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class OctaveMysql {

	String url = "jdbc:mysql://localhost/test";
	Connection conn;
	Statement stmt;
	ResultSet rs;

	public OctaveMysql() throws ClassNotFoundException {
		Class.forName("com.mysql.jdbc.Driver");
	}

	public void executeSql(String sql) throws ClassNotFoundException,
			SQLException {
		conn = DriverManager.getConnection(url);
		stmt = conn.createStatement();
		stmt.execute(sql);
		stmt.close();
		conn.close();
	}

	public ResultSet openCursor(String sql) throws SQLException {
		conn = DriverManager.getConnection(url);
		stmt = conn.createStatement();
		return rs = stmt.executeQuery(sql);
	}

	public void closeCursor() throws SQLException {
		stmt.close();
		conn.close();
	}

	public static void main(String args[]) {
		String sql = "CREATE TABLE IF NOT EXISTS `prova` ("
				+ "`id` int(11) NOT NULL," + "`clau` varchar(50) NOT NULL,"
				+ "`valor` varchar(50) NOT NULL," + "PRIMARY KEY (`id`)" + ")";
		try {
			OctaveMysql om = new OctaveMysql();
			om.executeSql(sql);
		} catch (Exception e) {
			System.out.println("error: " + e.getMessage());
		}
	}

}

I llavors, puc fer servir aquesta classe als meus scripts “.m”

prova_mysql.m

# afegeix al classpath la classe de prova i el driver de mysql 
javaaddpath("/home/albert/Workspace/wk-java/octave-mysql/jar/octave-mysql.jar");
javaaddpath("/home/albert/drivers-jdbc/mysql-connector-java-5.1.22/mysql-connector-java-5.1.22-bin.jar");

# instancia l'objecte java 
mysql = java_new("cat.stsoftlliure.octave.mysql.OctaveMysql")

# itera sobre la taula
rs = mysql.openCursor("select clau, valor from prova")

while rs.next()
  printf("%s - %s\n", rs.getString(1), rs.getString(2))
endwhile

# tanca objectes de connexió
mysql.closeCursor()

L’execució de l’script anterior em torna següent:

albert@athena:~$ octave
GNU Octave, version 3.6.2
Copyright (C) 2012 John W. Eaton and others.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  For details, type `warranty'.

Octave was configured for "i486-pc-linux-gnu".

Additional information about Octave is available at http://www.octave.org.

Please contribute if you find this software useful.
For more information, visit http://www.octave.org/help-wanted.html

Read http://www.octave.org/bugs.html to learn how to submit bug reports.

For information about changes from previous versions, type `news'.

octave:1> clc

octave:2> prova_mysql
mysql =



rs =



nom1 - valor1
nom3 - valor2
nom3 - valor3
nom4 - valor4
nom5 - valor5
nom6 - valor6
ans = [](0x0)
octave:3> 

He amagat tota la lampisteria que cal per accedir a la base de dades a la classe Java, que actua com una capa tècnica que exposa mètodes de servei a l’Octave . Aquests mètodes són el que invoco des d’Octave. Tanmateix Octave té la capacitat d’utilitzar directament les classes java: El mètode que obre un “cursor” retorna un ResultSet, i els mètodes del ResultSet (a l’exemple, getString) són invocats des d’Octave. És dir, també hauria pogut posar la lampisteria java a l’Octave (però no hauria estat una bona idea).

En resum, un exemple molt senzill de com ampliar la funcionalitat d’Octave amb Java, en concret per accedir a la base de dades MySql, però que es pot aplicar a qualsevol àmbit per al que es disposi de classes i llibreries Java.

I ara que ja se com, ja puc crear una replica del sistema Matlab + Oracle fent servir només eines lliures. Cost de les llicències, zero. 😉