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