Entorn de desenvolupament LifeRay – MySQL sobre Lubuntu

LifeRay
Aquest mes de juny m’ha portat una interessant novetat: sembla que professionalment m’hauré de dedicar al manteniment d’un grup de portals muntats amb LifeRay, un sistema de gestió de continguts basat en tecnologia java.

Sempre que és possible m’agrada disposar d’un entorn de proves així que, dit i fet, he muntat el meu propi entorn al sobretaula Linux, per a poder fer  proves i experiments amb LifeRay sense riscos. Aprofitant l’avinentesa, escric aquest article que també em serveix per “documentar” el procés.

Programari emprat
He muntat l’entorn LifeRay sobre una distribució Lubuntu 12.10. Per proporcionar la base de dades he fet servir una MySQL 5.0, però no la versió dels repositoris d’Ubuntu, si no la que ve incorporada al XAMPP, d’Apache Friends, un paquet que incorpora un stack complet de serviddor MySQL, Servidor Web Apache i PHP. Per què he triat aquesta versió? La resposta és prosaica: essencialment, perquè ja el tenia instal·lat 😉

El primer de tot ha estat descarregar de la web de LifeRay el programari. A la feina farem servir la versió Enterprise de Liferay, amb llicència comercial, però també es disposa d’una versió LifeRay Community. La versió community pot ser útil precisament per a desenvolupadors o per a desplegaments de petits llocs.

En aquest enllaç podeu trobar les diferències entre les versións enterprise i community de LifeRay.

Val a dir que es disposa de força documentació al lloc de LifeRay. Hi ha disponible documentació prou interessant i útil servida, és d’agraïr, sota llicència Creative Commons. Per exemple,la User Guide.

La versió community de LifeRay va amb una llicència lliure. Descarrego, doncs , la versió community que va empaquetada amb Tomcat. També es poden trobar a la web altres  paquets de LIferay amb JBoss, Geronimo, Glassfish… però la de Tomcat té un avantage principal:El LifeRay IDE per a desenvolupar portlets i components per al portal és un Eclipse al que s’afegeix un plugin. El plugin incorpora el control del servidor Tomcat on es munta LifeRay. Per a d’altres tipus de servidors cal descarregar-se un plugin addicional. Trio la versió Tomcat per simplificar la instal·lació.

El LifeRay IDE també em demanará disposar del paquet de documentació javadoc, del codi font -útil per a depuració- i del plugins SDK, és dir, del framework java necessari per a desenvolupar portlets, templates o themes per a LifeRay.

En el meu cas he descarregat, doncs, aquests quatre paquets:

El plugins SDK: liferay-plugins-sdk-6.2-ce-ga2-20140319114139101.zip
El Javadoc: liferay-portal-doc-6.2-ce-ga2-20140321115737138.zip
El codi font: liferay-portal-src-6.2-ce-ga2-20140319114139101.zip
El paquet LifeRay-Tomcat: liferay-portal-tomcat-6.2-ce-ga2-20140319114139101.zip

Els passos a seguir són directes. No m’invento res, és el que està descrit a aquest enllaç de la Wiki de LifeRay.

1. Descomprimeixo el paquet de LifeRay-Tomcat i obtinc un servidor Apache Tomcat 7.0 amb el .war del CMS desplegat.

2. Engego el servidor anant a la carpeta bin i executant startup.sh

3. Per a poder controlar l’arrencada, a un terminal faig

tail -f catalina.out 

de la carpeta logs del Tomcat.

Base de dades MySQL
L’arrencada inicial resulta força lenta, si més no a la màquina que estic fent servir.

4. Aprofito per engegar el servidor de BD, en el meu cas, que faig servir XAMPP, ho faig amb un

sudo /opt/lampp/lampp startmysql

5. Creo la base de dades que farà servir LifeRay. lportal és el nom que fa servir per defecte. Suposant que tinc al PATH la ruta /opt/lampp/bin, aleshores faig:

mysql --user=root

i un cop dins,

create database lportal;

Finalment, quan el servidor ha arrencat, s’obre el Firefox apuntant a la pàgina http://localhost:8080

6. En aquesta pàgina hi configuro el compte inicial

2014-06-08-171247_1024x744_scrot

7. En aquest punt cal indicar que vull fer servir la base de dades MySQL. Faig click a Change i obtinc

2014-06-08-171302_1024x744_scrot

Indico que és una BD de tipus MySQL. El user per defecte de la BD de XAMPP és root, i sense password.
Finalment, procedeix a la instal·lació.

Al portatil de la feina la instal·lació ha portat el seu temps, però s’ha completat. Un cop els objectes de la BD han estat creats i la instal·lació completada el FireFox m’ha mostrat la pàgina d’instal·lació completada amb èxit. A continuació m’ha mostrat el formulari de d’acceptació de les condicions d’us, m’ha demanat que actualitzés el password i m’ha demanat la pregunta de seguretat per si se m’oblida el password.

En canvi, a casa, el procés m’ha donat alguns problemes de time out. Em temo que em caldrà actualitzar l’equip. La tàctica que m’ha funcionat ha estat, simplement, no carregar les dades de prova, ignorar el time out i esperar a que segons el log tomcat (tail -f catalina.out) s’hagués completat el procés.

Pantalla de benvinguda
Quan ha estat llest he obert manualment http://localhost:8080 i m’he trobat amb la pàgina de login. Ara la tinc així: he deixat només el portlet de sign-in

2014-06-08-204530_1024x744_scrot

Coses ràpides que es poden fer. Afegir-hi portlets. Per exemple, li he afegit el portlet del generador de contrasenyes. Click a afegir. Triar el portlet i col·locar-lo. És similar a com s’editen pàgines amb el SharePoint de MS. D’aquests components encastables a MS en diuen WebParts, aquí es fa servir el nom (més clàssic i més java-ish) de portlet.

2014-06-08-205223_1024x744_scrot

Això ens dona una idea de quina mena de tasques podem esperar trobar:

Desenvolupament, podrem crear i modificar llocs, pàgines, plantilles de pàgina, temes, estils i, per descomptat, portlets. Algunes d’aquestes activitats es desenvoluparan des de la mateixa interfície web de LifeRay, i d’altres, des del LifeRay IDE. Es podria arribar a donar el cas, extraordinari, d’intervenir directament sobre la base de dades.

Administració. Trobarem tasques com donar d’alta i baixa usuaris i grups, modificar-ne els permisos d’accés a pàgines i llocs.

Interfície amb altres sistemes. Segurament on es troba la major dificultat. Les grans corporacions tenen sistemes molt diversos i necessitats d’interconnexió variades. No és gens estrany que l’autenticació i autorització dels usuaris i els grups a diversos sistemes i entorns estigui gestionada des de, sovint, més d’un sistema. El single-sign-on és un dels més grans maldecaps amb que es pot trobar el departament TIC. No es tant una tasca de LifeRay com una tasca genèrica, a mig camí entre el desenvolupament, l’administració i la gestió.

Continguts. Queda en mans dels usuaris. Els usuaris, tanmateix, poden demanar suport i assistència a l’hora de pujar contingut al CMS.

Son les mateixes tasques que hom es troba amb altres CMS. Varia la tecnologia, però les tasques son similars.

LifeRay IDE
Per a poder fer els desenvolupaments descrits es pot fer servir el LifeRay IDE. Com he dit abans, es tracta d’un plugin per a Eclipse que permet engegar i aturar el servidor de LifeRay, fer-ne desplegament i desenvolupar portlets, templates, themes, hooks…

La versió mínima d’Eclipse és la 3.7 (Indigo). Des de la web de LifeRay es pot descarregar versions d’Eclipse amb el plugin pre-instal·lat. La darrera versió que es pot descarregar del lloc LifeRay és la Kepler.

A la pàgina de descàrrega es pot obtenir tant l’URL per a instal·lació del plugin des de l’eclipse, com el paquet zip amb plugin propiament dit, o la versió del Kepler amb el plugin pre-instal.lat:

2014-06-08-222821_1024x744_scrot

En engegar el Liferay IDE puc observar que es tracta d’un Eclipse adaptat.

Java EE - Eclipse _002

A destacar aquests tres botons:

Selecció_001

Els botons anteriors permeten accedir als wizards dels diferents projectes i desenvolupaments que és poden fer amb el LifeRay IDE.

Selecció_003

Selecció_007

I també configurar l’IDE per accedir a servidors LifeRay.

Selecció_008

Faré això últim:

Configurar LifeRay IDE

És molt senzill:

Al següent vídeo mostro com establir el Plugin SDK i, a continuació, com configurar un nou servidor de LifeRay. A tenir en compte: he deixat els zips de docs, src i liferay-tomcat bundle dins de la carpeta home de la emva instal·lació de Liferay, i també dins d’aquesta carpeta he descomprimit el zip de plugins. Això és necessari per a configurar, primer de tot, el plugins SDK, i a continuació, el nou server.

Des d’aquest moment ja puc engegar o aturar el meu servidor de LieRay des de l’Eclipse:

2014-06-09-010051_1024x744_scrot

Per a un proper post, la creació d’un porlet que pugui posar a les pàgines.

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. 😉

Un exercici amb el Framework Seam

Des de fa un temps que estic involucrat en el manteniment d’una aplicació desenvolupada sobre el framework Seam. Fins dates recents el manteniment s’ha limitat a modificacions menors, però fa poc ens ha entrat un canvi en profunditat.Ha estat l’oportunitat que estava esperant per a poder aprendre una mica més sobre aquest potent framework.

Primer de tot, què és Seam? La Viquipèdia ens dona una definició breu, senzilla i entenedora: “Seam és un Framework per a aplicacions Web desenvolupat per JBoss, una divisió de Red Hat.”

Hi han molts frameworks per a aplicacions web.  Un framework és  la sistematització de l’experiència acumulada en el desenvolupament de moltes aplicacions web. Aquesta sistematització pren la forma d’arquitectures, patrons, llibreries, bones pràctiques i eines de diferents tipus. En adoptar un framework per a desenvolupar una aplicació web el que estem fent, doncs, es manifestar la voluntat de “fer bé les coses”, repetint models coneguts que han funcionat.  De forma pràctica, l’adopció d’un framework es tradueix en l’ús de certes llibreries, metodologies i eines de desenvolupament

Spring ve a ser l’estàndar de facto de la indústria o, si més no, el framework java per a aplicacions web més popular. Si coneixem Spring, doncs, ja sabem que podem esperar de Seam.  Tanmateix, Seam té les seves pròpies característiques. En aquest enllaç podeu trobar una anàlisi comparativa entre els frameworks Seam i Spring.

Per aproximar-me a Seam provaré de fer “alguna cosa” amb el framework. Per exemple un gestor de biblioteca molt senzill.

El que vull fer és una aplicació web que em permeti donar d’alta i de baixa  llibres, classificar-los segons autor, temàtica i tipus de suport físic, i que em permeti saber a quin lloc de la casa paren.

Doncs bé, resulta que això puc fer-ho sense escriure una línia de codi java. Seam es capaç de generar una aplicació web de manteniment sense més que proporcionar-li un esquema de dades. La veritat és que és força espectacular. No cal dir que aquests superpoders no són pas els únics dels que disposa Seam, però per a una primera aproximació -res més pretenc en aquest post- és més que suficient.

Comencem: aplicacions. El framework Seam es pot fer servir amb qualsevol Servidor d’Aplicacions que suporti EJB3.0, ara bé, Seam és un producte de JBoss i, com es pot esperar s’integra fàcilment amb aquest servidor. El primer que faré, doncs, és descarregar les darreres versions de  JBoss AS i del Seam framework. Proveu els següents enllaços:

Seam 3.1.0 http://sourceforge.net/projects/jboss/files/Seam/3/3.1.0.Final/

jBoss AS 7.1.1 Final http://download.jboss.org/jbossas/7.1/jboss-as-7.1.1.Final/jboss-as-7.1.1.Final.zip

Ens caldrà una versió de JDK igual o superior a la 1.6 (feu un cop d’ull a http://www.oracle.com/technetwork/java/javase/downloads/index.html).

Si per alguna raó no poguéssim disposar almenys de JDK1.6, aleshores hauríem de fer servir versions anteriors de JBoss AS i de SEAM. Podria ser aquest el cas d’haver d’ocupar-nos del manteniment d’una aplicació legacy.

La següent configuració funciona amb JDK 1.5 (evidentment, funciona amb JDK superiors):

Seam 2.3.0 GA http://sourceforge.net/projects/jboss/files/JBoss%20Seam/2.3.0.Final/

JBoss AS 5.1.0.GA http://sourceforge.net/projects/jboss/files/JBoss/JBoss-5.1.0.GA

La instal·lació del servidor JBoss AS 1.7 i del Seam Framework 3.1.0 no presenta cap dificultat, es tracta, simplement de descomprimir el paquet zip corresponent. he creat una carpeta seam-jboss i els he descomprimit allà.

Si tinc versions diverses de JDK, puc modificar l’script d’arrencada de JBoss bin/standalone.sh per a indicar-hi explícitament quin JDK vull fer servir, només em cal donar un valor inicial a JAVA_HOME per a que apunti a la carpeta del JDK triat, per exemple:

JAVA_HOME=/home/albert/jdk1.6.0_30

El següent pas és crear les taules i relacions de la base de dades. Faré servir el servidor MySQL que em ve amb el XAMPP que tinc instal·lat de posts anteriors, i el phpMyAdmin com interfase de la base de dades.

Només vull fer una petita demostració, o sigui que no entraré en detalls: la idea és crear una petita bd de biblioteca. Tindré
– una taula per guardar els llibres (id, llibre, isbn, id_ubicació, id_format);
– una taula d’autors (id, autor);
– una taula de relació m-n entre llibres i autors (un autor pot haver escrit molts llibres, un llibre pot ser escrit per molts autors. Per tant: id, id_autor, id_llibre);
– una taula de relació m-n entre llibres i temàtiques (un llibre pot tractar diversos temes; un tema pot ser tractat per molts llibres. Per tant, id, id_llibre, id_tematica);
– lògicament, doncs, una taula de temàtiques (id, tematica).
– una taula d’ubicacions (id, lloc) ja que puc tenir llibres per uns quants llocs de la casa, a prestatges, o a DVDs (suposo que tinc els DVDs etiquetats, cosa que algun dia hauré de fer, però, en fi, això només pretén ser un exemple 😉
– una taula de formats: “paper”, “pdf”, “epub”, “cbr”… (id, format).

Dit i fet. Primer de tot creo la base de dades “prova_seam”, i les taules “llibre”, “autor”, “llibre_autor”, “llibre_tematica”, “ubicacio” i “format”.

A continuació, creo els índexos sobre totes les columnes que participaran en les relacions i, finalment, creo les relacions. Cal esmerçar-se en crear correctament els índexos i les relacions. És necessari per a que la màgia de Seam funcioni. Es tracta, simplement, de permetre que les eines de mapeig de model relacional a model d’objectes tinguin tota la informació necessària per a crear una capa de classes java que encapsulin l’accés a les dades.

Després d’una sessió de phpMyAdmin, obtinc un model de dades que m’agrada. L’esquema és el següent:


-- phpMyAdmin SQL Dump
-- version 3.4.5
-- http://www.phpmyadmin.net
--
-- Servidor: localhost
-- Tiempo de generación: 21-11-2012 a las 21:05:25
-- Versión del servidor: 5.5.16
-- Versión de PHP: 5.3.8

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Base de datos: `prova_seam`
--

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `autor`
--

CREATE TABLE IF NOT EXISTS `autor` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `autor` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=2 ;


-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `format`
--

CREATE TABLE IF NOT EXISTS `format` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `format` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=2 ;


-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `llibre`
--

CREATE TABLE IF NOT EXISTS `llibre` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `llibre` varchar(200) COLLATE latin1_spanish_ci NOT NULL,
  `isbn` varchar(13) COLLATE latin1_spanish_ci NOT NULL,
  `id_ubicacio` int(11) NOT NULL,
  `id_format` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `id_ubicacio` (`id_ubicacio`),
  KEY `id_format` (`id_format`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `llibre_autor`
--

CREATE TABLE IF NOT EXISTS `llibre_autor` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_llibre` int(11) NOT NULL,
  `id_autor` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `id_llibre` (`id_llibre`),
  KEY `id_autor` (`id_autor`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `llibre_tematica`
--

CREATE TABLE IF NOT EXISTS `llibre_tematica` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_autor` int(11) NOT NULL,
  `id_tematica` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `id_autor` (`id_autor`),
  KEY `id_tematica` (`id_tematica`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `tematica`
--

CREATE TABLE IF NOT EXISTS `tematica` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tematica` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `ubicacio`
--

CREATE TABLE IF NOT EXISTS `ubicacio` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ubicacio` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=2 ;

--
-- Volcado de datos para la tabla `ubicacio`
--

INSERT INTO `ubicacio` (`id`, `ubicacio`) VALUES
(1, 'llibreria de l''escriptori');

--
-- Restricciones para tablas volcadas
--

--
-- Filtros para la tabla `llibre`
--
ALTER TABLE `llibre`
  ADD CONSTRAINT `llibre_ibfk_1` FOREIGN KEY (`id_ubicacio`) REFERENCES `ubicacio` (`id`),
  ADD CONSTRAINT `llibre_ibfk_2` FOREIGN KEY (`id_format`) REFERENCES `format` (`id`);

--
-- Filtros para la tabla `llibre_autor`
--
ALTER TABLE `llibre_autor`
  ADD CONSTRAINT `llibre_autor_ibfk_1` FOREIGN KEY (`id_llibre`) REFERENCES `llibre` (`id`),
  ADD CONSTRAINT `llibre_autor_ibfk_2` FOREIGN KEY (`id_autor`) REFERENCES `autor` (`id`);

--
-- Filtros para la tabla `llibre_tematica`
--
ALTER TABLE `llibre_tematica`
  ADD CONSTRAINT `llibre_tematica_ibfk_1` FOREIGN KEY (`id_autor`) REFERENCES `autor` (`id`),
  ADD CONSTRAINT `llibre_tematica_ibfk_2` FOREIGN KEY (`id_tematica`) REFERENCES `tematica` (`id`);

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;


En aquest punt, deixo el phpMyAdmin i me’n vaig a la carpeta on tinc el seam.

Estic fent servir la versió de Seam 3.2.0. Amb aquesta versió hi han les següents eines disponibles per al desenvolupament d’aplicacions web:
– el JBoss Developer Estudio. que només requereix registre per a poder-lo descarregar lliurement.
– Les JBoss Tools. Que són plugins per Eclipse. Les JBoss Tools permeten crear, directament, aplicacions per al Framework Seam 2.3.0 i, indirectament, a través del plugin de Seam Forge, per al Framework Seam 3.1.0.
Seam Forge. Es tracta d’una shell des de la que es poden crear aplicacions, deployar, crear objectes nous… Aquesta shell s’integra com a plugin a les JBoss Tools o al JBoss Developer Studio. El Seam Forge vindria a ser l’evolució de l’script seam-gen de la versió Seam Framework 2.3.0. A diferència de seam-gen, que formava part del paquet de distribució del Framework, el Seam Forge ha de descarregar-se com una aplicació separada.

Seam Forge es pot extendre amb plugins. A la pàgina de plugins en trobarem alguns que ens caldran per a poder fer l’enginyeria inversa de la base de dades i per automatitzar les tasques d’administració dels desplegaments al JBoss AS. Però n’hi han d’altres. Serà cosa de provar a veure què fan.

Com que el repte és “crear una aplicació sense escriure una línia de codi”, i tenint en compte les explicacions anteriors, descarrego el Seam Forge. És un paquet zip que desplego a la mateixa carpeta de seam-jboss on tinc les carpetes del JBoss AS i del Seam Framework. Em cal indicar-li el JDK que penso fer servir i quina és la seva carpeta home. Per a fer-ho vaig a la carpeta bin del Seam Forge i allà modifico l’script forge per a establir les variables JAVA_HOME i FORGE_HOME.

Seam Forge em permetrà generar (scaffold) una aplicació o, si més no, l’esquelet i alguns òrgans vitals, d’una aplicació web. Tot plegat d’una forma que recorda els Archetypes de Maven. pel que estic veient, Maven és una eina que es fa força imprescindible a l’hora de treballar amb projectes desenvolupats a partir de Forge. En general Maven és una eina molt potent que caldria tenir en compte (almenys considerar-ne l’ús) de forma habitual.

A més, em caldrà tenir a ma el driver jdbc del MySQL per a poder desplegar-lo al JBoss.

És el primer que faig. Per a desplegar el driver jdbc n’hi ha prou amb col·locar-lo a la carpeta JBOSS_HOME/standalone/deployments. Si tenim una finestra oberta amb els logs del servidor veurem com, efectivament, el desplega. A més, a la consola d’administració del JBoss també veurem el nou desplegament:

UN cop tinc el driver disponible al JBoss, passo a la construcció de l’aplicació amb el Forge.

Escric forge al terminal i accedeixo a la shell. Una advertència, no tanqueu la shell del Forge fins completar tots els passos del desplegament de l’aplicació:

Per a poder fer l’enginyeria inversa del model de dades al MySQL i generar les classes java per hibernate em cal, primer de tot, carregar els hibernate-tools. Aquesta part del post està basada en aquest link (http://www.mastertheboss.com/forge/reverse-engineer-your-db-schema-using-jboss-forge).


albert@athena:~/seam-jboss/forge-distribution-1.1.2.Final/bin$ forge
    _____                    
   |  ___|__  _ __ __ _  ___ 
   | |_ / _ \| `__/ _` |/ _ \  \\
   |  _| (_) | | | (_| |  __/  //
   |_|  \___/|_|  \__, |\___| 
                   |___/      

JBoss Forge, version [ 1.1.2.Final ] - JBoss, by Red Hat, Inc. [ http://jboss.org/forge ]
[no project] bin $
[no project] bin $ forge install-plugin hibernate-tools
***INFO*** Preparing to install plugin: hibernate-tools
***INFO*** Checking out plugin source files to [/tmp/forgetemp2102291278366764408/repo] via 'git'
***INFO*** Switching to branch/tag [refs/heads/master]
***INFO*** Invoking build with underlying build system.
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building hibernate-tools-plugin 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ hibernate-tools-plugin ---
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ hibernate-tools-plugin ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 3 resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ hibernate-tools-plugin ---
[INFO] Compiling 9 source files to /tmp/forgetemp2102291278366764408/repo/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ hibernate-tools-plugin ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 3 resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ hibernate-tools-plugin ---
[INFO] Not compiling test sources
[INFO] 
[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ hibernate-tools-plugin ---
[INFO] Tests are skipped.
[INFO] 
[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ hibernate-tools-plugin ---
[INFO] Building jar: /tmp/forgetemp2102291278366764408/repo/target/hibernate-tools-plugin-1.0.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 22.651s
[INFO] Finished at: Sun Nov 18 14:29:57 CET 2012
[INFO] Final Memory: 33M/79M
[INFO] ------------------------------------------------------------------------
***INFO*** Installing plugin artifact.
***SUCCESS*** Installed from [https://github.com/forge/plugin-hibernate-tools.git] successfully.
Wrote /home/albert/.forge/httpsrawgithubcomforgepluginrepositorymasterrepositoryyaml.yaml
Wrote /home/albert/.forge/plugins/org/jboss/hibernate/forge/hibernate-tools-plugin/1.0.0-SNAPSHOT-311059c3-c505-46c1-915e-4a3af362ea9a
...

després d’escriure un munt de jars a la carpeta de plugins, finalment, tinc les hibernate tools disponibles al Forge:

Wrote /home/albert/.forge/plugins/org/jboss/hibernate/forge/hibernate-tools-plugin/1.0.0-SNAPSHOT-311059c3-c505-46c1-915e-4a3af362ea9a/slf4j-log4j12-1.5.10.jar
Wrote /home/albert/.forge/plugins/org/jboss/hibernate/forge/hibernate-tools-plugin/1.0.0-SNAPSHOT-311059c3-c505-46c1-915e-4a3af362ea9a/hibernate-tools-plugin.jar
Wrote /home/albert/.forge/plugins/org/jboss/hibernate/forge/hibernate-tools-plugin/1.0.0-SNAPSHOT-311059c3-c505-46c1-915e-4a3af362ea9a/module.xml
    _____                    
   |  ___|__  _ __ __ _  ___ 
   | |_ / _ \| `__/ _` |/ _ \  \\
   |  _| (_) | | | (_| |  __/  //
   |_|  \___/|_|  \__, |\___| 
                   |___/      

JBoss Forge, version [ 1.1.2.Final ] - JBoss, by Red Hat, Inc. [ http://jboss.org/forge ]

Ara creo el nou projecte:

[no project] bin $ new-project
 ? [named=The name of the new project (of type java.lang.String)]: provaseam
 ? Use [/home/albert/seam-jboss/forge-distribution-1.1.2.Final/bin/provaseam] as project directory? [Y/n] n

 ? Where would you like to create the project? [Press ENTER to use the current directory: bin] [ .../bin] /home/albert/workspace/wk-java/provaseam
***SUCCESS*** Created project [provaseam] in new working directory [/home/albert/workspace/wk-java/provaseam]
Wrote /home/albert/workspace/wk-java/provaseam
Wrote /home/albert/workspace/wk-java/provaseam/pom.xml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java
Wrote /home/albert/workspace/wk-java/provaseam/src/test/java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/resources
Wrote /home/albert/workspace/wk-java/provaseam/src/test/resources
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam
[provaseam] provaseam $

new-project ha creat un fitxer pom.xml (per a compilar i deployar amb maven) i una estructura de carpetes.

Ara cal omplir aquesta estructura de carpetes de contingut. A continuació, configuro paràmetres incials de persistència:

[provaseam] provaseam $ persistence setup
 ? [provider=ARG (of type org.jboss.forge.spec.javaee.jpa.api.JPAProvider)]: org.jboss.forge.spec.javaee.jpa.api.JPAProvider
[provider=ARG (of type org.jboss.forge.spec.javaee.jpa.api.JPAProvider)]: 

  1 - [HIBERNATE]
  2 - [OPENJPA]
  3 - [ECLIPSELINK]
  4 - [INFINISPAN]

 ? Choose an option by typing the number of the selection: 1
 ? [container=ARG (of type org.jboss.forge.spec.javaee.jpa.api.JPAContainer)]: org.jboss.forge.spec.javaee.jpa.api.JPAContainer
[container=ARG (of type org.jboss.forge.spec.javaee.jpa.api.JPAContainer)]: 

  1 - [JBOSS_AS6]
  2 - [JBOSS_AS7]
  3 - [JBOSS_EAP6]
  4 - [GLASSFISH_3]
  5 - [CUSTOM_JDBC]
  6 - [CUSTOM_JTA]
  7 - [CUSTOM_NON_JTA]

L’anterior es podia haver fet en una sola línia així si hagués afegit les opcions provider i container a persistence setup:

persistence setup --provider HIBERNATE --container JBOSS_AS7

Segueix:

 ? Choose an option by typing the number of the selection: 2
Use which version of 'jboss-javaee-6.0' ?

  1 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta4]
  2 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta5]
  3 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta6]
  4 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta7]
  5 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.CR1]
  6 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Final]
  7 - [org.jboss.spec:jboss-javaee-6.0:pom::2.0.0.Beta1]
  8 - [org.jboss.spec:jboss-javaee-6.0:pom::2.0.0.CR1]
  9 - [org.jboss.spec:jboss-javaee-6.0:pom::2.0.0.Final]
  10 - [org.jboss.spec:jboss-javaee-6.0:pom::2.1.0.Beta1]
  11 - [org.jboss.spec:jboss-javaee-6.0:pom::3.0.0.Beta1]
  12 - [org.jboss.spec:jboss-javaee-6.0:pom::3.0.0.Final]
  13 - [org.jboss.spec:jboss-javaee-6.0:pom::3.0.1.Final]*

 ? Choose an option by typing the number of the selection [*-default]  [0] 
***SUCCESS*** Installed [forge.spec.jpa] successfully.
***INFO*** Setting transaction-type="JTA"
***INFO*** Using example data source [java:jboss/datasources/ExampleDS]
 ? Do you want to install a JPA 2 metamodel generator? [y/N] 
 ? The JPA provider [HIBERNATE], also supplies extended APIs. Install these as well? [y/N] 
***SUCCESS*** Persistence (JPA) is installed.
Wrote /home/albert/workspace/wk-java/provaseam/src/main/resources/META-INF/persistence.xml
Wrote /home/albert/workspace/wk-java/provaseam/pom.xml
[provaseam] provaseam $

Fixem-nos en aquesta línia:

***INFO*** Using example data source [java:jboss/datasources/ExampleDS]

S’ha creat un datasource de prova. El podem trobar a la carpeta /home/albert/workspace/wk-java/provaseam/src/main/resources/META-INF/

El persistence.xml generat:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="forge-default" transaction-type="JTA">
    <description>Forge Persistence Unit</description>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="hibernate.transaction.flush_before_completion" value="true"/>
    </properties>
  </persistence-unit>
</persistence>

El que faré serà canviar el persistence.xml que fa servir el datasource d’exemple per un persistence.xml que apunti al datasource que crearé ara.

Creo el datasource. Per això copio un fitxer datasource.xml amb el següent contingut a la carpeta de deployments (JBOSS_HOME/standalone/deployments).

<datasources xmlns="http://www.jboss.org/ironjacamar/schema">
<datasource jndi-name="java:jboss/datasources/mysqldev" pool-name="poolmysqldev">
    <connection-url>jdbc:mysql://localhost/prova_seam</connection-url>
    <driver>mysql-connector-java-5.1.22-bin.jar</driver>
    <pool>
        <max-pool-size>30</max-pool-size>
    </pool>
    <security>
        <user-name>root</user-name>
        <password></password>
    </security>
</datasource>
</datasources>

Com abans amb el driver, si tenim una consola oberta amb els logs de funcionament del JBoss veurem com fa el deploy del datasource. A la consola d’administració podrem vereu el datasource que tot just hem creat i en podrem provar la connexió amb la base de dades.

I ara canvio el persistence.xml per un persistence.xml que apunti al meu datasource. Fixem-nos que les properties canvien. Pot ser interessant consultar la següent taula de Hibernate Dialects. En general, no està de més fer-li un cop d’ull a la documentació d’Hibernate.

Vet aquí el persistence.xml que poso a /home/albert/workspace/wk-java/provaseam/src/main/resources/META-INF/

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">

    <persistence-unit name="test">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/datasources/mysqldev</jta-data-source>
        <properties>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.username" value="root"/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
        </properties>
    </persistence-unit>  
</persistence>

I ara ja puc generar les classes amb les hibernate tools:

[provaseam] provaseam $ generate-entities
 ? Specify the URL for the JDBC connection. [jdbc:h2:tcp://localhost/sakila] jdbc:mysql://localhost/prova_seam
 ? Enter the user name for JDBC connection. [null] root
 ? Enter the password for JDBC connection. 
 ? Enter the dialect to use for the datasource. [org.hibernate.dialect.H2Dialect] org.hibernate.dialect.MySQLDialect
 ? Specify the class name for the JDBC driver for the datasource. [org.h2.Driver] com.mysql.jdbc.Driver
 ? Enter the path in the local file system to the jar file containing the JDBC driver. [null] /home/albert/jdbc-drivers/mysql.jar
 ? In which package you'd like to generate the entities, or enter for default: [com.example.provaseam.model] com.stsoftlliure.provaseam.model
Found 7 tables in datasource
Generated java at /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/LlibreAutor.java
Generated java at /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/LlibreTematica.java
Generated java at /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Tematica.java
Generated java at /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Autor.java
Generated java at /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Llibre.java
Generated java at /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Ubicacio.java
Generated java at /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Format.java
Generated 7 java files.
[provaseam] provaseam $

Ara genero l’esquelet de l’aplicació web:

[provaseam] provaseam $ scaffold setup
 ? No scaffold type was selected, use default [JavaServer Faces]? [Y/n] 
 ? Scaffold provider [faces] is not installed. Install it? [Y/n] 
 ? Facet [forge.maven.WebResourceFacet] requires packaging type(s) [war], but is currently [jar]. Update packaging? (Note: this could deactivate other plugins in your project.) [Y/n] 
***SUCCESS*** Installed [forge.maven.WebResourceFacet] successfully.
***SUCCESS*** Installed [forge.spec.ejb] successfully.
***SUCCESS*** Installed [forge.spec.cdi] successfully.
***SUCCESS*** Installed [forge.spec.servlet] successfully.
***SUCCESS*** Installed [forge.spec.jsf.api] successfully.
***SUCCESS*** Installed [faces] successfully.
 ? Create scaffold in which sub-directory of web-root? (e.g. http://localhost:8080/provaseam/DIR) [/] 
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp
Wrote /home/albert/workspace/wk-java/provaseam/pom.xml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/WEB-INF/beans.xml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/WEB-INF/faces-config.xml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/favicon.ico
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/scaffold/paginator.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/scaffold/pageTemplate.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/index.html
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/index.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/error.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/add.png
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/bootstrap.css
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/false.png
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/favicon.ico
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/forge-logo.png
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/forge-style.css
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/remove.png
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/search.png
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/true.png
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/jboss-community.png
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/WEB-INF/web.xml
[provaseam] provaseam $

Genero les classes de l’aplicació bàsica, a partir del model. L’aplicació bàsica és del tipus CRUD (Create, Read, Update i Delete), és dir, les quatre opcions mínimes de tot manteniment de taules.

[provaseam] provaseam $ scaffold from-entity com.stsoftlliure.provaseam.model.* --overwrite
***INFO*** Using currently installed scaffold [faces]
***SUCCESS*** Generated UI for [com.stsoftlliure.provaseam.model.Autor]
***SUCCESS*** Generated UI for [com.stsoftlliure.provaseam.model.Format]
***SUCCESS*** Generated UI for [com.stsoftlliure.provaseam.model.Llibre]
***SUCCESS*** Generated UI for [com.stsoftlliure.provaseam.model.LlibreAutor]
***SUCCESS*** Generated UI for [com.stsoftlliure.provaseam.model.LlibreTematica]
***SUCCESS*** Generated UI for [com.stsoftlliure.provaseam.model.Tematica]
***SUCCESS*** Generated UI for [com.stsoftlliure.provaseam.model.Ubicacio]
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/AutorBean.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/autor/create.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/autor/view.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/autor/search.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/resources/scaffold/pageTemplate.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/ViewUtils.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/WEB-INF/classes/META-INF/forge.taglib.xml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Autor.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/FormatBean.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/format/create.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/format/view.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/format/search.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Format.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/LlibreBean.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibre/create.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibre/view.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibre/search.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Llibre.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/LlibreAutorBean.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibreAutor/create.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibreAutor/view.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibreAutor/search.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/LlibreAutor.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/LlibreTematicaBean.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibreTematica/create.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibreTematica/view.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/llibreTematica/search.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/LlibreTematica.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/TematicaBean.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/tematica/create.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/tematica/view.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/tematica/search.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Tematica.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/example/provaseam/view/UbicacioBean.java
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/ubicacio/create.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/ubicacio/view.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/webapp/ubicacio/search.xhtml
Wrote /home/albert/workspace/wk-java/provaseam/src/main/java/com/stsoftlliure/provaseam/model/Ubicacio.java
[provaseam] provaseam $

Anem molt bé. En principi, la aplicació ja està llesta per compilar i desplegar. Però en realitat no. Si compilem i despleguem ara, obtindrem l’aplicació, però en provar a introduir valors a les taules obtindré errors. (si no us ho creieu simplement salteu-vos aquest pas i compileu i desplegueu ara). Com anuncia el link http://www.mastertheboss.com/forge/reverse-engineer-your-db-schema-using-jboss-forge alguna cosa no ha acabat d’anar a l’hora. Els errors que obtindreu si decidiu provar amb l’aplicació tal comestà deixen aquesta traça:

22:51:02,392 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/provaseam].[FacesServlet]] (http--127.0.0.1-8080-2) Servlet.service() for servlet FacesServlet threw exception: org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.stsoftlliure.provaseam.model.Format. Expected: class java.lang.Integer, got class java.lang.Long

Els ID que ha generat el plugin de les hibernate-tools per a les entitats ha estat del tipus Integer; El codi al que em refereixo és aquest:

A la carpeta

src/main/java/com/stsoftlliure/provaseam/model/
    LlibreAutor.java
    LlibreTematica.java
    Tematica.java
    Autor.java
    Llibre.java
    Ubicacio.java
    Format.java

Però resulta que el codi que han generat el pas d’scaffolding (la línia “scaffold from-entity com.stsoftlliure.provaseam.model.* –overwrite”), que ha generat el següent codi java:

src/main/java/com/example/provaseam/view/
    ViewUtils.java
    AutorBean.java
    FormatBean.java
    LlibreBean.java
    LlibreAutorBean.java
    LlibreTematicaBean.java
    TematicaBean.java 
    UbicacioBean.java

Tenim que els ID que referencien els objectes són del tipus Long.

Per exemple, mirem les classes Autor i AutorBean

Autor

package com.stsoftlliure.provaseam.model;

// Generated 19/11/2012 23:16:54 by Hibernate Tools 3.4.0.CR1

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * Autor generated by hbm2java
 */
@Entity
@Table(name = "autor", catalog = "prova_seam")
public class Autor implements java.io.Serializable
{

   private Integer id;
   private String autor;
   private Set llibreAutors = new HashSet(0);
   private Set llibreTematicas = new HashSet(0);

   public Autor()
   {
   }

   public Autor(String autor)
   {
      this.autor = autor;
   }

   public Autor(String autor, Set llibreAutors, Set llibreTematicas)
   {
      this.autor = autor;
      this.llibreAutors = llibreAutors;
      this.llibreTematicas = llibreTematicas;
   }

   @Id
   @GeneratedValue(strategy = IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   public Integer getId()
   {
      return this.id;
   }

   public void setId(Integer id)
   {
      this.id = id;
   }

...

AutorBean

package com.example.provaseam.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.stsoftlliure.provaseam.model.Autor;

/**
 * Backing bean for Autor entities.
 *
* This class provides CRUD functionality for all Autor entities. It focuses * purely on Java EE 6 standards (e.g. @ConversationScoped for * state management, PersistenceContext for persistence, * CriteriaBuilder for searches) rather than introducing a CRUD framework or * custom base class. */ @Named @Stateful @ConversationScoped public class AutorBean implements Serializable { private static final long serialVersionUID = 1L; /* * Support creating and retrieving Autor entities */ private Long id; public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } ...

En principi, doncs, i atenent al missatge d’error, tenim dues possibilitats: o corregir les classes generades amb les hibernate tools (canviant integer per long), o corregir les generades amb l’scaffolding (canviant Long per Integer), ara bé, resulta que a les classes generadese amb l’scaffolding, les NomClasseBean, es fa servir l’Id del tipus Long en altres mètodes d’us intern, com el FindById. Per tant, és millor canviar les classes generades amb Hibernate-tools, on l’Id només apareix un cop.

Per tant, canvio Integer per Long a Autor. Així:


(- Ep! Un moment! havies dit que no caldria escriure ni una línia de codi!
– Bé, estrictament no estem escrivint cap línia de codi, només estic modificant-ne alguna…Sí, d’acord… és una mica lleig)

package com.stsoftlliure.provaseam.model;

// Generated 19/11/2012 23:16:54 by Hibernate Tools 3.4.0.CR1

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * Autor generated by hbm2java
 */
@Entity
@Table(name = "autor", catalog = "prova_seam")
public class Autor implements java.io.Serializable
{

   private Long id;
   private String autor;
   private Set llibreAutors = new HashSet(0);
   private Set llibreTematicas = new HashSet(0);

   public Autor()
   {
   }

   public Autor(String autor)
   {
      this.autor = autor;
   }

   public Autor(String autor, Set llibreAutors, Set llibreTematicas)
   {
      this.autor = autor;
      this.llibreAutors = llibreAutors;
      this.llibreTematicas = llibreTematicas;
   }

   @Id
   @GeneratedValue(strategy = IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   public Long getId()
   {
      return this.id;
   }

   public void setId(Long id)
   {
      this.id = id;
   }

...

Un cop he fet els canvis a les classes d’entitat (Autor.java, Format.java, Llibre.java, Tematica.java, Ubicacio.java, LlibreAutor.java i LlibreTematica.java), puc compilar i deployar.

Per a fer-ho, primer instal·laré al forge el plugin de control del JBoss AS 7.1:

[provaseam] provaseam $ forge install-plugin jboss-as-7
Connecting to remote repository [https://raw.github.com/forge/plugin-repository/master/repository.yaml]... connected!
***INFO*** Preparing to install plugin: jboss-as-7
***INFO*** Checking out plugin source files to [/tmp/forgetemp3143468914443124072/repo] via 'git'
***INFO*** Switching to branch/tag [refs/heads/1.0.5.Final]
***INFO*** Invoking build with underlying build system.
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building plugin-jboss-as7 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ plugin-jboss-as7 ---
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ plugin-jboss-as7 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 2 resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ plugin-jboss-as7 ---
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 23 source files to /tmp/forgetemp3143468914443124072/repo/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ plugin-jboss-as7 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /tmp/forgetemp3143468914443124072/repo/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ plugin-jboss-as7 ---
[INFO] Not compiling test sources
[INFO] 
[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ plugin-jboss-as7 ---
[INFO] Tests are skipped.
[INFO] 
[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ plugin-jboss-as7 ---
[INFO] Building jar: /tmp/forgetemp3143468914443124072/repo/target/plugin-jboss-as7.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.310s
[INFO] Finished at: Sun Nov 18 16:25:25 CET 2012
[INFO] Final Memory: 47M/113M
[INFO] ------------------------------------------------------------------------
***INFO*** Installing plugin artifact.
***SUCCESS*** Installed from [https://github.com/forge/plugin-jboss-as.git] successfully.
Wrote /home/albert/.forge/httpsrawgithubcomforgepluginrepositorymasterrepositoryyaml.yaml

...

Wrote /home/albert/.forge/plugins/org/jboss/as/plugin-jboss-as7/dependencies/1.0.0-SNAPSHOT-b32f7bdd-fc1e-4d44-91ab-18119749258b/module.xml
    _____                    
   |  ___|__  _ __ __ _  ___ 
   | |_ / _ \| `__/ _` |/ _ \  \\
   |  _| (_) | | | (_| |  __/  //
   |_|  \___/|_|  \__, |\___| 
                   |___/      

JBoss Forge, version [ 1.1.2.Final ] - JBoss, by Red Hat, Inc. [ http://jboss.org/forge ]
The following plugins have been activated: [as7]
[provaseam] provaseam $

Compilo…

[provaseam] provaseam $ build
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building provaseam 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-war-plugin/2.1.1/maven-war-plugin-2.1.1.pom
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-war-plugin/2.1.1/maven-war-plugin-2.1.1.pom (7 KB at 38.6 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-war-plugin/2.1.1/maven-war-plugin-2.1.1.jar
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-war-plugin/2.1.1/maven-war-plugin-2.1.1.jar (76 KB at 657.7 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.3.1/maven-install-plugin-2.3.1.pom
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.3.1/maven-install-plugin-2.3.1.pom (5 KB at 83.7 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.3.1/maven-install-plugin-2.3.1.jar
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.3.1/maven-install-plugin-2.3.1.jar (23 KB at 352.8 KB/sec)
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ provaseam ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 2 resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ provaseam ---
[INFO] Compiling 15 source files to /home/albert/workspace/wk-java/provaseam/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ provaseam ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ provaseam ---
[INFO] Not compiling test sources
[INFO] 
[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ provaseam ---
[INFO] Tests are skipped.
[INFO] 
[INFO] --- maven-war-plugin:2.1.1:war (default-war) @ provaseam ---
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-archiver/1.2/plexus-archiver-1.2.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-archiver/1.2/plexus-archiver-1.2.pom (2 KB at 32.2 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-io/1.0.1/plexus-io-1.0.1.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-io/1.0.1/plexus-io-1.0.1.pom (2 KB at 20.5 KB/sec)
Downloading: http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.pom
Downloaded: http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.pom (12 KB at 166.6 KB/sec)
Downloading: http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-parent/1.3.1/xstream-parent-1.3.1.pom
Downloaded: http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-parent/1.3.1/xstream-parent-1.3.1.pom (14 KB at 210.2 KB/sec)
Downloading: http://repo1.maven.org/maven2/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.pom
Downloaded: http://repo1.maven.org/maven2/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.pom (2 KB at 33.5 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/apache/maven/shared/maven-filtering/1.0-beta-2/maven-filtering-1.0-beta-2.pom
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/shared/maven-filtering/1.0-beta-2/maven-filtering-1.0-beta-2.pom (4 KB at 64.5 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/apache/maven/shared/maven-shared-components/10/maven-shared-components-10.pom
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/shared/maven-shared-components/10/maven-shared-components-10.pom (9 KB at 84.9 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/apache/maven/maven-parent/9/maven-parent-9.pom
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/maven-parent/9/maven-parent-9.pom (33 KB at 433.3 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.pom (6 KB at 101.5 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus/1.0.12/plexus-1.0.12.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus/1.0.12/plexus-1.0.12.pom (10 KB at 106.3 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-interpolation/1.6/plexus-interpolation-1.6.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-interpolation/1.6/plexus-interpolation-1.6.pom (3 KB at 55.7 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-archiver/1.2/plexus-archiver-1.2.jar
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-io/1.0.1/plexus-io-1.0.1.jar
Downloading: http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar
Downloading: http://repo1.maven.org/maven2/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar
Downloading: http://repo1.maven.org/maven2/org/apache/maven/shared/maven-filtering/1.0-beta-2/maven-filtering-1.0-beta-2.jar
Downloaded: http://repo1.maven.org/maven2/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar (25 KB at 135.4 KB/sec)
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-io/1.0.1/plexus-io-1.0.1.jar (50 KB at 248.4 KB/sec)
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/shared/maven-filtering/1.0-beta-2/maven-filtering-1.0-beta-2.jar (33 KB at 150.7 KB/sec)
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-archiver/1.2/plexus-archiver-1.2.jar (178 KB at 595.9 KB/sec)
Downloaded: http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar (422 KB at 934.1 KB/sec)
[INFO] Packaging webapp
[INFO] Assembling webapp [provaseam] in [/home/albert/workspace/wk-java/provaseam/target/provaseam]
[INFO] Processing war project
[INFO] Copying webapp resources [/home/albert/workspace/wk-java/provaseam/src/main/webapp]
[INFO] Webapp assembled in [248 msecs]
[INFO] Building war: /home/albert/workspace/wk-java/provaseam/target/provaseam.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] 
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ provaseam ---
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-digest/1.0/plexus-digest-1.0.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-digest/1.0/plexus-digest-1.0.pom (2 KB at 19.5 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-components/1.1.7/plexus-components-1.1.7.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-components/1.1.7/plexus-components-1.1.7.pom (5 KB at 71.4 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom (8 KB at 117.7 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-container-default/1.0-alpha-8/plexus-container-default-1.0-alpha-8.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-container-default/1.0-alpha-8/plexus-container-default-1.0-alpha-8.pom (8 KB at 150.9 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-digest/1.0/plexus-digest-1.0.jar
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-digest/1.0/plexus-digest-1.0.jar (12 KB at 160.8 KB/sec)
[INFO] Installing /home/albert/workspace/wk-java/provaseam/target/provaseam.war to /home/albert/.m2/repository/com/example/provaseam/provaseam/1.0.0-SNAPSHOT/provaseam-1.0.0-SNAPSHOT.war
[INFO] Installing /home/albert/workspace/wk-java/provaseam/pom.xml to /home/albert/.m2/repository/com/example/provaseam/provaseam/1.0.0-SNAPSHOT/provaseam-1.0.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.090s
[INFO] Finished at: Sun Nov 18 16:28:22 CET 2012
[INFO] Final Memory: 65M/155M
[INFO] ------------------------------------------------------------------------
[provaseam] provaseam $

Configuro el plugin per a fer-lo servir amb el meu JBoss local

[provaseam] provaseam $ as7 setup
 ? The Java Home '/home/albert/jdk1.6.0_30' is already set, would you like to override it? [y/N] 
 ? A default version of 7.1.1.Final is already set, would you like to override it? [y/N] 
 ? Enter path for JBoss AS or leave blank to download: /home/albert/jboss-as-7.1.1.Final
***SUCCESS*** Installed [AS7ServerFacet] successfully.
[provaseam] provaseam $

i, finalment, faig el deploy:

[provaseam] provaseam $ as7 deploy
The deployment operation (FORCE_DEPLOY) was successful.
[provaseam] provaseam $

I ja només em queda provar l’aplicació que acabo de deplegar. Per això apunto el navegador a http://localhost:8080/provaseam i, efectivament obtinc una senzilla aplicació de biblioteca. Basada en un manteniment de taules. Com he dit abans, el resultat és força espectacular. L’esforç ha estat en definir i crear correctament les taules, els índexos i les relacions entre les taules (i arreglar alguns petits desajustos que Seam Forge ha deixat).

A la consola d’administració del JBoss podem veure els desplegaments realitzats:

Vet aquí la pantalla inicial de l’aplicació:

Per cert, com a extra, des de la pantalla inicial es pot enviar un tuit (feu click al link Get Excited!) per anunciar al món que ja hem fet la nostra primera aplicació amb Seam 3 i Forge! No m’hi estic pas!

Les relacions entre taules es resolen amb camps desplegables. Entro alguns formats i ubicacions i creo un llibre:

format:

ubicacio:

vaig a crear un llibre:

El llibre creat:

Cal reconèixer que és força lletja la representació dels formats i les ubicacions. Caldria corregir les visualitzacions. En tot cas, podem seguir l’enllaç, per exemple, de les ubicacions per obtenir tots els llibres que estan al prestatge de l’estudi:

En resum, una generació força automatitzada d’una aplicació de manteniment de taules (un CRUD) feta amb l’eina Seam Forge, amb la versió de Framework Seam 3.1. desplegada sobre un JBoss 7.1.

Val a dir que després de provar això mateix amb el seam-gen del framework Seam 2.3.0 un es queda una mica decebut. Fa l’efecte com si s’hagués anat enrere. En realitat, sembla que la qüestió és que s’ha iniciat un camí nou amb el Forge. Encara més, a la mateixa definició de Seam3 que fan a la web www.seamframeworkorg/seam3 han fet desaparèixer la paraula framework per parlar de conjunt de mòduls i eines: “Seam3 is a collection of modules and developer tooling tailored for Java EE 6 application development, with CDI as the central piece.”i encara una mica després, referint-se a Forge el defineixen com “JBoss Forge is an incremental project enhancement API and shell.” De fet, la forma de treballar amb Forge té més a veure amb definir des del forge les entitats i les accions, que no pas fer una enginyeria inversa d’un model existent. O sigui que hem fet servir el Forge no de la forma com “estava prevista” (en canvio seam-gen de Seam2, sí que estava més pensat per a això).

La definició anterior de Seam, a més, feia aparèixer la sigla màgica CDI. CDI, Context and Dependency Injection. CDI i Java EE 6 (HTML | PDF). No és ara el moment per parlar-ne. Però caldrà fer-ho.

Al proper post faré de nou l’aplicació de Biblioteca amb el Seam 2 i el seam-gem. Tot i que es tracta de la versió anterior manté tot l’interès ja que, en cap cas, es pot considerar que Seam 2 sigui obsolet. De fet, com he comentat abans, per una qüestió de compatibilitat amb versions de JDK i Java EE podem ben bé trobar-nos amb que no es pugui fer servir la versió Seam 3, que demana últimes versions.

Com instal·lar XAMPP a Ubuntu.

A l’hora de fer presentacions i demos d’aplicacions web, pot ser molt útil disposar d’una versió de la demo en un servidor web en localhost, potser en una clau usb.

També pot ser molt útil un servidor web d’aquest tipus a l’hora de preparar sessions de formació.

És possible trobar per Internet diverses distribucions que d’aquest tipus que combinen Apache amb  MySQL i PHP, tant sobre Linux (LAMP), com sobre Windows (WAMP), per exemple XAMPP o MoWeS Portable.

MoWeS Portable empaqueta, a més de la plataforma AMP, altres aplicacions que utilitzen aquesta infraestructura, com Joomla! o Drupal. Ara bé, MoWeS Portable només està disponible per a Windows.

XAMPP, en canvi, s’ofereix per a Linux i Windows.

En el post d’avuí el que faig és instal·lar el XAMPP a un netbook Linux.

No cal dir que la plataforma AMP es pot instal·lar des del Centre de Programari de l’Ubuntu. Però la instal·lació de XAMPP és encara més senzilla.

Dit i fet. El primer pas és descarregar-se el paquet d’instal·lació. El  puc trobar en aquesta adreça:  http://sourceforge.net/projects/xampp/files/BETAS/xampp-linux-1.7.7.tar.gz/download. Són uns 77MB.

Aquesta versió incorpora:   Apache, MySQL, PHP amb PEAR, Perl, ProFTPD, phpMyAdmin, OpenSSL, GD, Freetype2, libjpeg, libpng, gdbm, zlib, expat, Sablotron, libxml, Ming, Webalizer, pdf class, ncurses, mod_perl, FreeTDS, gettext, mcrypt, mhash, eAccelerator, SQLite i IMAP C-Client.

En particular Apache 2.2.21, MySQL 5.5.16, PHP 5.3.8, i phpMyAdmin 3.4.5.

Per instal·lar  n’hi ha prou amb desempaquetar el tar.gz. Cal tenir en compte que als fitxers d’instal·lació s’assumeix que la home del XAMPP serà /opt/lampp. Això NO vol dir que només es pugui instal·lar en aquesta carpeta. Això l’únic que vol dir és que caldrà que /opt/lampp sigui la “home” del XAMPP i això es podrà aconseguir amb un enllaç simbòlic des de /opt/lampp al directori d’instal·lació que triï.

Si la carpeta de destinació del XAMPP es troba en una clau usb caldrà que aquesta clau estigui formatada amb un sistema de fitxers que permeti els enllaços simbòlics, per exemple  ext2,ext3 o ext4.

A l’hora de fer l’enllaç simbòlic caldrà tenir en compte el punt de muntatge del dispositiu. Per exemple, al meu netbook amb Ubuntu 11.04, el punt de muntatge és /media.

Per a poder instal·lar correctament el XAMPP caldran, a més, permisos de root. I també per a posar en marxa i aturar els diversos components de la distribució.

Tenint en compte tot l’anterior, instal·lo el XAMPP a la meva carpeta home, on he deixat el tar.gz:

sudo tar xvfz xampp-linux-1.7.7.tar.gz -C .

Amb la ordre anterior es crea una carpeta lampp amb els dversos components del XAMPP.

Ara creo l’enllaç simbòlic:

sudo ln -s /home/albert/lampp /opt/lampp

I engego per primer cop el servidor. Aquesta primera arrencada acaba d’instal·lar i configurar els components.

albert@athena:~$ sudo /opt/lampp/lampp start
Starting XAMPP for Linux 1.7.7…
XAMPP: Starting Apache with SSL (and PHP5)…
XAMPP: Starting MySQL…
XAMPP: Starting ProFTPD…
XAMPP for Linux started.
albert@athena:~$ 

I per revisar la nova instal·lació en tinc prou amb obrir un navegador i apuntar-lo al localhost:

El directori arrel del servidor web es troba a /opt/lampp/htdocs (en el meu cas, mercès a l’enllaç simbòlic, és /home/albert/lampp/htdocs).

Per aturar el XAMPP puc fer:

albert@athena:~$ sudo /opt/lampp/lampp stop
Stopping XAMPP for Linux 1.7.7…
XAMPP: Stopping Apache with SSL…
XAMPP: Stopping MySQL…
XAMPP: Stopping ProFTPD…
XAMPP stopped.
albert@athena:~$ 

I per a eliminar la instal·lació sense deixar rastres, amb el XAMPP aturat, n’hi ha prou amb fer:
sudo rm -r lampp
És possible engegar i aturar individualment els diversos components del XAMPP. Examinant el fitxer $HOME/lampp/lampp es poden  trobar les diverses opcions disponibles. La forma d’invocar-les, en general, és: 
sudo /opt/lampp/lampp opció

Com fer servir MySQL amb Python. Mòdul MySQL-DB

Aquest post és molt similar al’anterior, però en aquest la base de dades és MySQL. Per a desenvolupar aplicacions que facin servir MySQL amb Python, el primer pas és instal·lar algun mòdul que permeti accedir-hi amb Python.

El mòdul més popular per accedir a MySQL amb Python és MySQL-DB (http://sourceforge.net/projects/mysql-python/).

Com en d’altres ocasions, és possible instal·lar aquest mòdul a la una distribució Ubuntu des del”Centre de Programari de l’Ubuntu”.

També instal·lo l’extensió de debug, tot des del “Centre de Programari de l’Ubuntu”

És imprescindible llegir la documentació (recordem que amb pydoc podrem consultar la documentació o presentar-la en format html).

La documentació online la trobem a http://mysql-python.sourceforge.net/MySQLdb.html

A continuació, repetiré el senzill experiment del post anterior que consistia en connectar-se a una base de dades existent i executar-hi consultes, però, en aquesta ocasió, fent servir una base de dades MySQL.

Primer de tot, amb l’Anjuta, creo un projecte nou del tipus Python generic.

Hi enganxaré el següent script. Remarcar-ne només l’us dels parametres charset=’utf8′ i use_unicode=True en el connect. SCalen per a recuperar correctament dades de tipus text que puguin tenir accents, dièresis… La resta de l’script és molt senzill i els comentaris expliquen que fa el codi.

 #!/usr/bin/python
# coding: latin-1
#

import MySQLdb
import sys

def main():
    print “Connectant a la base de dades localhost / proves”
      
    try:

        # obté una connexió, si no es pot connectar, llença una excepció
        # charset=’utf8′, use_unicode=True -> necessaris per a recuperar dades amb accents
        v_conn=MySQLdb.connect(host=’localhost’, user=’root’, passwd=’password’, db=’proves’, charset=’utf8′, use_unicode=True)
        print “Connectat!\n”
      
        # conn.cursor retorna un objecte cursor, per a fer les consultes.
        v_cur=v_conn.cursor()
      
        #executa una query
        v_cur.execute(“select id,valor,traduccio from taula1”)
      
        # obté totes les files
        v_files = v_cur.fetchall()

        # mostra les files
        for v_fila in v_files:
            print str(v_fila[0]) + ” ; ” + v_fila[1] + ” ; ” + v_fila[2]

        # tanca el cursor
        v_cur.close()
      
        # tanca la connexió
        v_conn.close()
 
      
    except:
    # obté informació de l’excepció
        e_exceptionType, e_exceptionValue, e_exceptionTraceback = sys.exc_info()
        # mostra la informació i acaba.
        sys.exit(“error, %s” % (e_exceptionValue))

# final
if __name__ == “__main__”:
    sys.exit(main())

Des del mateix Anjuta puc provar:

EXECUTING:
/home/albert/wp-python/prova-Mysql/src/python_mysql.py
———————————————-
Connectant a la base de dades localhost / proves
Connectat!

1 ; valor 1 ; traducció 1
2 ; valor 2 ; traducció 2
3 ; valor 3 ; traducció 3
4 ; valor 4 ; traducció 4
5 ; valor 5 ; traducció 5
6 ; valor 6 ; traducció 6

———————————————-
Program exited successfully with errcode (0)
Press the Enter key to close this terminal …

Un senzill experiment de com accedir a MySQL amb scripts de Python fent servir el mòdul MySQLdb.

Com accedir a PostgreSQL (o MySQL, o FireBird) amb Lazarus / 31 juliol 2010

Com accedir a PostgreSQL (o MySQL, o FireBird) amb Lazarus

Tanco la serie de “com accedir a una base de dades del tipus xxxx amb Lazarus” amb el post d’avui, en el que desenvolupo una aplicació que accedeix a una taula d’una base de dades del tipus PostgreSQL.

L’entorn és Ubuntu Lucid Lynx 10.04. Amb el Centre de Programari de l’Ubuntu m’he instal·lat  PostgreSQL 8.4 i PgAdmin III. Que pel poc que he vist, és una molt bona eina d’administració i de consulta i força intuitiva.

El primer pas ha estat canviar el password de l’usuari postgres. Per això he fet des d’un terminal

sudo -u postgres psql postgres

i, a continuació, dins de la consola de sql

\password postgres

La barra de l’inici és important. Li indico el nou password: per exemple, “masterkey”. (consulteu l’ajuda al setup de PostgreSQl a Ubuntu).

Un cop fet  això, amb pgAdmin ja podré registrar el servidor Localhost i crear-hi una nova base de dades que anomenaré ‘proves’. A proves, dins l’esquema public, hi creo una taula taula1, amb les mateixes columnes que en posts anteriors:  id (numèrica i PK), valor (text) i traducció (text).

Puc fer servir pgAdmin per a informar amb dades la taula.

I ara creo l’aplicació amb Lazarus. Idèntica a la del post  accedir amb Lazarus a SQLite. Amb un parell de diferències. En aquesta ocasió, els components d’accés seran uns altres:

Poso un component de Connexió a Postgres del tipus TPQConnection (objecte PQConnection1)
Un objecte TSQLTransaction (SQLTranasaction1) i un TSQLQuery (SQLQuery1) i els connecto entre ells.
En particular:
PQConnection1. UserName: postgres
PQConnection1.password: masterkey
PQConnection1.hostname: localhost
PQConnection1.databasename: proves
PQConnection1.transaction: SQLTransaction1

SQLTransaction1. Database: PQConnection1

SQLQuery1.database: PQConnection1
SQLQuery1.transaction: SQLTransaction1
SQLQuery1.SQL: select id,valor,traduccio from taula

La resta és un camp memo i tres botons Carregar (Button1Click), Netejar (Button2Click) i Sortir (Button3Click).

El codi del form és:

unit unProvaPostgres01;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, pqconnection, sqldb, FileUtil, LResources, Forms, Controls,
  Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    PQConnection1: TPQConnection;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  sId, sValor, sTraduccio, sLinea: String;
begin
  (* obre connexions a la BD *)
  PQConnection1.Open;
  SQLQuery1.Open;

  (* itera a través de la BD *)
  SQLQuery1.First;
  while not SQLQuery1.EOF do begin
    sId := SQLQuery1.FieldByName(‘id’).AsString;
    sValor := SQLQuery1.FieldByName(‘valor’).AsString;
    sTraduccio := SQLQuery1.FieldByName(‘traduccio’).AsString;
    sLinea := sId + ‘; ‘ + sValor + ‘; ‘ + sTraduccio;
    Memo1.Append(sLinea);
    SQLQuery1.Next;
  end;

  // tanca la query
  SQLQuery1.Close;
  PQConnection1.Close;

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Memo1.Clear;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Application.Terminate;
end;

initialization
  {$I unprovapostgres01.lrs}
end.
EL codi anterior funciona exactament igual amb bases de dades del tipus FireBird / InterBase, o amb Bases de dades del tipus MySQL (si més no, fins a la 5.0), només que canviant el component TPQConnection per un TIBConnection per a les FireBird/InterBase, o per un TMySQL40Connection per a les MySQL4.0, TMySQL41Connection per a MySQL4.1 o TMySQL50Connection per a les MySQL50.

Amb les bases de dades del tipus MySQL 5.1 el control de connexió disponible amb Lazarus SqlDB funciona a mitges. No tanca bé. Suposo que es podria buscar algun control alternatiu, però cal trobar-lo. És una mala notícia perquè la versió de MySQL del repositori de programari d’Ubuntu per a Lucid és la 5.1

En tot cas, aquest és el HelloWorld de la connexió de Lazarus a Postgres (i a FireBird i fins a les MySQL 5.0).