Arduino Starter Kit

1 Un post sobre Arduino

Des de fa alguns anys que dins del món de programari lliure, o del moviment maker, o des d’entorns educatius i formatius de tecnologia, se sent parlar i es desenvolupa una activitat creixent al voltant d’Arduino (i de Raspberry Pi, Scratch, Processing…)

Em venia de gust provar l’Arduino i això em va dur a comprar, fa uns mesos, un Arduino Starter Kit per a fer-ne els experiments i captar-ne les “sensacions”. Finalment, he trobat temps per completar els experiments i és el moment d’explicar què m’he trobat.

L’Starter Kit deu ser, segurament, la forma més suau d’introduir-se a l’Arduino. És una caixa que inclou una placa Arduino One, una placa protoboard, components electrònics diversos, cables i ponts de connexió i un manual amb quinze experiments -cap d’ells complex, però algun de força vistós- per a realitzar amb el material inclòs.

Clarament l’Arduino Starter Kit està orientat a un públic jove. Les nenes i nens de ESO no haurien de tenir cap dificultat en la realització dels experiments i comprendre la lògica de funcionament dels circuits i els diferents components utilitzats. En cap cas es tracta d’experiments perillosos. Potser els circuits que involucren el motor de continua són els més “complexos” i els que poden presentar major dificultat de muntatge, però els resultats son espectaculars.

Però no us penseu que Arduino és tracta d’una joguina. Les noies i els nois més grans, a nivells de Batxillerat, però també universitaris, poden trobar a l’Arduino una plataforma excel·lent per a la realització de projectes. Fora dels entorns formatius, Arduino ha esdevingut una de les plaques preferides pels aficionats a l’electrònica i pel moviment Maker. Arduino es presenta en diferents versions i existeix una versió industrial per a l’us professional.

2 Però què és Arduino?

(traduccio lliure de https://www.arduino.cc/en/Guide/Introduction)

“Arduino és una plataforma de prototipatge de codi obert basada en hardware i software senzill i fàcil d’usar. Les plaques Arduino són capaces de llegir entrades: com la llum a un sensor, un dit prement un botó, o una piulada de Twitter, i transformar-les en sortides: activant un motor, encenent un LED, o publicant alguna cosa a Internet. Es pot indicar a la placa què ha de fer tot enviant-li instruccions al microcontrolador que porta muntat. Per a aconseguir-ho es fa us del llenguatge de programació de l’Arduino (basat en el llenguatge Wiring), i en l’entorn de desenvolupament integrat d’Arduino (Integrated Development Enviroment, o IDE), basat en l’entorn Processing.

Amb el pas dels anys Arduino ha estat el cervell de milers de projectes, desde objectes quotidians fins a instruments científics complexos. Una comunitat mundial de ‘makers’ -estudiants, aficionats, artistes, programadors i professionals- s’ha aplegat al voltant d’aquesta plataforma de codi obert. Les seves contribucions hab afegit una quantitat increible de coneixement accessible que pot ser de gran ajuda tant per als principiants com per als més experts.

Arduino va neixer al Ivrea Interaction Design Institute com una eina d’utilització fàcil per al prototipatge ràpid adreçada a estudiants sense fonaments en electrònica i programació. Tan aviat com va arribar a una comunitat més gran, la placa Arduino va començar a canviar per adaptar-se a noves necessitats i desafiaments, diversificant la seva oferta desde plaques simples de 8 bits, fins productes per a aplicacions de Internet of Things (IoT), wearables, impressió 3D i sistemes encastats. Totes les plaques Arduino són completament de codi obert, permetent als usuaris construir-les pels seus propis mitjans i adaptar-les als seus requeriments particulars. El programari també és de codi obert i evoluciona amb les constribucions dels usuaris d’arreu del món.

Mercès a la seva accessibilitat i simplicitat d’us, Arduino s’utilitza en milers de projectes i aplicacions diferents. El programari d’Arduino és d’us senzill per als principiants però, a l’hora, prou flexible per usuaris experimentats. Es pot executar en Mac, Windows i Linux. Els professors i els estudiants el fan servir per construir instruments científics barats, o per provar principis de física i química, o per a iniciar-se en la programació i la robòtica. Els dissenyadors i els arquitectes construeixen prototipus interactius. Músics i artistes el fan servir en instal·lacions i per experimentar amb instruments musicals nous. Els ‘Makers’, per descomptat, el fan servir per construir molts dels projectes que s’exhibeixen a les ‘Maker Faire’, per exemple. Arduino és una eina clau per a l’aprenentatge de novetats. Tothom – nens, aficionats, artistes, programadors – es pot posar mans a l’obra ja sigui seguint les instruccions pas a pas d’un kit, o compartint idees amb altres membres de la comunitat Arduino.

Hi han molts altres microcontroladors i plataformes de microcontrolador per a la construcció de sistemes físics interactius (“physical computing”). Parallax Basic Stamp, BX-24 de Netmedia, Phidgets, Handyboard del MIT, i molts altres que ofereixen funcionalitats similars. Totes aquestes eines encapsulen els detalls més farragosos de la programació de microcontroladors i el empaqueten en una interficie d’usuari més senzilla d’utilitzar. Arduino també simplifica el procés de treball amb microcontroladors i, a més, ofereix alguns avantatges per als professors, estudiants, i aficionats que no tenen els altres sistemes:

  • Barat – Les plaques Arduino són relativament barates si es comparen amb altres plataformes de microcontroladors. La versió més barata d’Arduino es pot muntar a mà, i els mòduls de version ja muntades, no arriben als 50 dòlars.
  • Multiplataforma – L’entorn de programació d’Arduino s’executa a Windows, Macintosh OSX, i distribucions Linux. La majoria de plataformes de microcontroladors estan limitades a Windows.
  • Entorn de programació senzill – L’entorn de programació és fàcil d’usar pels principiants, però prou flexible com per a que els usuaris avançats el puguin fer servir eficaçment. Per als mestres, l’entorn integrat està basat en l’entorn de programació ‘Processing’, per tant, els estudiants que estiguin aprenent a programar en aquest es trobaran que els serà familiar la forma de treballar de l’IDE d’Arduino (veure nota).
  • Codi obert i programari extensible – El programari Arduino es codi obert i es pot extendre. El llenguatge de programació es pot ampliar mitjançant llibreries C++, i la gent aque vulgui comprendre els detalls més tècnics poden fer els salt des del llenguatge de l’Arduino IDE al llenguatge de programació C per AVR en que està basat. També es pot afegir codi AVR-C directament als programes d’Arduino si es vol.
  • Codi obert i maquinari extensible – Els esquemes de les plaques Arduino es publiquen amb llicència Creative Commons, per tant els dissenyadors mes experimentats poden fer les seves pròies versions dels mòduls, extendre-les o millorar-les. Fins i tot, un principiant pot construir la seva pròpia versió dels mòduls en una placa protoboard, per a comprendre’n el funcionament i per estalviar diners.”

Nota: realment l’IDE de l’Arduino està basat en el IDE Wiring (basat en el llenguatge C), que al seu temps ho està en el IDE de Processing (basat en llenguatge Java)

3 Especificacions d’Arduino One

Les podeu trobar a la pàgina oficial. Les reprodueixo a continuació:

Technical specs
Microcontroller ATmega328P
Operating Voltage 5V
Input Voltage (recommended) 7-12V
Input Voltage (limit) 6-20V
Digital I/O Pins 14 (of which 6 provide PWM output)
PWM Digital I/O Pins 6
Analog Input Pins1 6
DC Current per I/O Pin 20 mA
DC Current for 3.3V Pin 50 mA
Flash Memory 32 KB (ATmega328P) of which 0.5 KB used by bootloader
SRAM 2 KB (ATmega328P)
EEPROM 1 KB (ATmega328P)
Clock Speed 16 MHz
Length 68.6 mm
Width 53.4 mm
Weight 25 g

I també l’esquemàtic.

4 Els circuits.

L’Starter Kit proposa la construcció de quinze circuits molt senzills. Per a cada circuit es proporciona:

  • la llista de components a utilitzar
  • l’esquema
  • la foto del circuit muntat
  • la descripció pas a pas del muntatge dels components
  • el codi C comentat que cal compilar i carregar a l’Arduino
  • com provar el circuit
  • propostes d’ampliació i variacions

4.1 Experiment 1.

S’expliquen els contactes de la protoboard; S’enuncien els rudiments dels circuits elèctrics i la llei d’Ohm, i es fan circuits mínims en serie i paral·lel. L’Arduino només es fa servir per proporcionar l’alimentació dels circuits.

4.2 Experiment 2.

És un experiment mínim que permet introduir l’Arduino IDE. Es programa una seqüència d’encesa i apagat de tres leds fent servir sortides digitals. S’aprèn a compilar i carregar els programes a la placa. Ens planteja l’estructura bàsica dels programes Arduino, amb la funció setup() que s’executa al començament de l’execució i que s’aprofita per a inicialitzar l’estat de la placa; i la funció loop() que és una funció que s’executa contínuament, i que és on es programa la funcionalitat desitjada. Les funcions setup() i loop() apareixen sempre en tots els programes d’Arduino.

S’introdueix una tècnica per reconèixer els canvis d’estat als ports d’entrada de l’Arduino.

4.3 Experiment 3.

S’introdueix el sensor de temperatura TMP36 que es capaç de proporcionar un rang de tensions de sortida que varia proporcionalment a la temperatura en graus centígrads. Es mostra l’ús de les entrades analògiques i una tècnica simple d’escalat de valors. S’introdueix el Monitor Sèrie, que permet obtenir informació i missatges provinents de la placa Arduino, i també per enviar senyals a la placa. Es fan servir les sortides digitals per simular un termòmetre fet amb leds.

4.3.1 Comunicació entre Arduino i Host pel port sèrie (USB) amb altres llenguatges

La comunicació sèrie entre l’ordinador (el host) i la placa Arduino mitjançant el port sèrie (USB) es pot fer amb varietat de llenguatges, no només amb l’Arduino IDE.

En particular, és molt senzill fer la comunicació amb aplicacions desenvolupades amb C/C++ perquè es fa servir la llibreria C estàndard. És dir, amb C/C++ n’hi ha prou amb obrir el port /dev/ttyACM0 amb fopen per a lectura/escriptura i fer servir la resta de funcions de I/O de la la llibreria estàndard: fread, fwrite, fclose…

Alternativament, també es poden fer servir les crides de baix nivell: open, write, read, close… la tria d’un o altre grup de funcions, doncs, dependrà d’altres criteris, com pot ser el grau d’abstracció que es requereixi en la comunicació entre host i Arduino. En general, però, sempre caldrà tenir en compte mantenir la consistència amb el mètode triat (Llibreria Estàndard de C, o Crides al Sistema),

Amb Python, la comunicació entre Arduino i Host es pot fer fàcilment amb la llibreria pySerial.

La llibreria s’ha de carregar. En el meu cas que faig servir una distribució Lubuntu 15.04 he de fer:

sudo apt-get install python-serial

El següent és un exemple bàsic que permet llegir els missatges que venen de la placa Arduino:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import serial
 
ser = serial.Serial('/dev/ttyACM0', 9600)
while True:
   print ser.readline()

Amb Java, es pot fer servir la llibreria RxTx. Es tracta d’un jar amb classes java i d’una so (per Linux, Mac) o dll (per Windows) que cal instal·lar. Val a dir que aquesta llibreria va inclosa amb l’entorn Processing, així que si teniu instal·lat aquest entorn ja teniu la RxTx al vostre sistema.

4.4 Experiment 4.

En aquest experiment es fan servir tres fotoresistències per a modular els senyals dels components blau, ved i vermell d’un LED RGB de càtode comú: en funció del grau d’il·luminació de cadascuna de les fotoresistències s’aconsegueix que la llum del LED variï entre el blanc (tots els sensors totalment il·luminats), tons i barreges de colors (diferents intensitats de llum sobre cada sensor), o l’apagat (amb els sensors de llum tapats).

Per a simular les sortides de diferents intensitats amb les sortides digitals s’aprofita que les sortides 3,5,6,10 i 11 de l’Arduino admeten la modulació PWM, (és dir, regular el cicle de treball del pols digital i, per tant, modular-ne el valor del component de CC). En la programació del codi es té en compte el temps necessari per a la conversió AD a les entrades connectades als sensors.

4.5 Experiment 5.

El servomotor és l’estrella de l’experiment 5. L’alimentació de 5V de l’arduino és suficient per alimentar el servomotor. Al tractar-se d’una càrrega inductiva cal protegir la placa dels corrents espúris produits pel servo: en aquest circuit s’afegeixen un parell de condensadors de desacoblament,

Al codi cal destacar

  • L’utilització de la llibreria Servo, que encapsula la utilització de sevomotors de Parallax.
  • L’us de la funció map() (veure nota) que permet fer un mapeig escalat lineal entre un rang d’entrada i un de sortida.

Per a saber més de motors i servos, se’ns recomana el llibre Making Things Move de Dustyn Roberts i l’adreça http://robives.com/mechs

nota: aquesta funcio map() no té res a veure amb la funció homònima que es pot trobar als llenguatges que segueixen el paradigma de programació funcional!

4.6 Experiment 6.

Del moviment al sò. Conceptualment és similar a l’experiment 4. Es fa servir una fotoresistència per modular el senyal que ataca un brunzidor piezoelèctric. El senyal del sensor es converteix AD a un valor que es fa correspondre amb map() (veure nota) a un valor dins el rang de control de la sortida PWM que ataca al brunzidor.

La novetat en aquest circuit és que en comptes de fer servir la funció analogWrite() es fa servir la més adequada tone(): Amb analogWrite() la freqüència que s’envia per la sortida és fixa però amb un cicle de treball (relació entre temps en estat alt i període del senyal) variable; amb tone() el cicle de treball és sempre del 50%, però canvia la freqüència del senyal.

Al codi també s’introdueix la funció millis() per controlar un temporitzador.

4.7 experiment 7.

Un altre experiment amb el brunzidor. En aquesta ocasió se substitueix el sensor de llum per una escala de resistències combinada amb uns interruptors, de forma que a la pulsació de cada interruptor li correspon un valor de tensió en l’entrada AD de l’Arduino. A cada valor d’entrada se li fa correspondre una freqüència, amb la que s’ataca al brunzidor.

la novetat al codi és la utilització d’un array de C per mantenir la taula de freqüències, i la utilització de noTone() per silenciar el brunzidor quan no hi ha cap interruptor premut.

Una taula amb les freqüències de les notes musicals es pot consultar a http://arduino.org/frequencies.

4.8 Experiment 8.

En aquest experiment es fa servir un interruptor d’inclinació per a simular un rellotge de sorra: al moure l’interruptor que està connectat a una entrada digital que s llegeix amb digitalRead(), es restaura l’estat de les sortides digitals que estan connectades a uns leds. Aleshores, a la funció loop(), en cada iteració s’observa l’hora actual que s’obté amb millis() i es compara amb l’hora en que s’ha encès el darrer LED. Si l’interval de temps supera un valor prefixat, s’encén el següent LED i s’actualitza la marca.

4.9 Experiment 9.

Es presenta el motor de continua. El motor de CC és de velocitat i sentit de gir variables. la velocitat de gir es pot controlar variant la tensió aplicada a les seves connexions (dins d’uns límits), i el sentit de gir es pot canviar invertint-ne la polaritat.

Tanmateix, fins i tot amb el petit motor inclòs a l’Starter Kit, l’Arduino no és capaç de proporcionar prou corrent per a alimentar motors directament: Arduino One no pot proporcionar més de 40mA per les sortides digitals.

El que es fa al circuit és connectar el motor a una font externa i controlar-ne l’alimentació fent servir un transistor MOSFET IRF520 com a interruptor electrònic, connectant-ne la porta a una de les sortides PWM i fent el control efectiu de l’encesa i apagada amb un interruptor connectat a una de les entrades digitals.

Al manual del kit proposen fer servir una pila de 9V per a la font externa. També es pot fer servir una font d’alimentació de les que es poden trobar a qualsevol basar xinès.

Addicionalment, es fa servir un díode rectificador N4007 connectat en oposició a l’alimentació del motor, per a proporcionar un camí de descàrrega per als corrents auto-induits quan aquest es desconnecta de l’alimentació i es va frenant fins aturar-se.

4.10 Experiment 10.

A l’experiment anterior es presentava el motor de CC i es muntava un circuit molt senzill per a engegar-lo i aturar-lo, però s’indicava que és possible regular-ne la velocitat i l sentit de gir. En aquest experiment es fa servir un circuit integrat L293D de driver per a motors per aconseguir aquest control.

L’ús de l’L293D simplifica el control dels motors: un xip substitueix el circuit del MOSFET i al díode de protecció. Però, a més, és possible realitzar el control de velocitat i la inversió de gir (un pont H) amb aquest CI.

És una bona idea revisar l’especificació de l’L293D per revisar diferents modalitats de connexió, o la connexió de fins a quatre motors amb aquest driver.

4.11 Experiment 11.

Es presenta el dispositiu LCD de visualització LCM1602C, es tracta d’un pantalla LCD de 16×2 caràcters. El muntatge connecta les sortides digitals de l’Arduino al display LCD per a mostrar missatges que canvien aleatòriament quan es mou l’interruptor d’inclinació connectat a una de les entrades digitals. És un projecte similar al de l’experiment 8, només que en comptes d’enviar els missatges aleatoris pel monitor sèrie, els mostra a l’LCD.

La lògica de comunicació entre Arduino i l’LCD s’encapsula a la llibreria LiquidCrystal. La llibreria s’explica amb detall a la url: http://arduino.org/lcd.

Pel que fa al muntatge, val a dir que hi ha alguna etiqueta de l’esquema al manual que no coincideix exactament amb l’etiqueta impresa al component LCD i potser pot produir alguna confusió. En tot cas, una revisió de les especificacions de l’LCM1602C haurien de ser suficients per esvair qualsevol dubte en el cablatge.

4.12 Experiment 12.

Un altre experiment amb el servomotor. En aquesta ocasió es fa servir el brunzidor piezoelèctric com a sensor, en lloc d’actuador. El brunzidor, a més de produir so, també el pot captar i, per tant, en aquesta ocasió es connecta a una entrada analògica de l’Arduino, enlloc de a una sortida.

El circuit de l’experiment fa un comptador de tocs (per exemple, el soroll de picar de mans).

El programa és un exemple de com implementar una senzilla màquina d’estats. El funcionament implementat va fent transicions des de l’estat de repòs (leds taronja i verd apagats, led vermell encès, servo en posició de “tancat”), a l’estat d’un toc vàlid captat (leds verd i vermell apagats, led taronja encès, servo “tancat”), dos tocs vàlids captats (mateixes condicions), i tres tocs vàlids captats (leds vermell i taronja apagats, led verd obert, i servo en posició d'”obert”), on roman fins que es rep un reset que torna a l’estat de repòs original.

4.13 Experiment 13.

l’Starter Kit ens proposa la construcció d’un “component” capacitiu amb paper d’alumini que es pugui fer servir amb la llibreria CapacitiveSensor de Paul Badger.

El component capacitiu no és més que una làmina de paper d’alumini.

El principi de funcionament d’aquest “sensor” és la càrrega i descàrrega de les capacitats paràsites que apareixen al circuit. Per a major detall, podeu consultar http://playground.arduino.cc/Main/CapacitiveSensor

També és interessant que, a diferència d’altres llibreries usades en els experiments, cal descarregar la CapacitiveSensor d’Internet i instal·lar-la correctament a l’Arduino IDE per a poder fer-la servir.

4.14 Experiment 14.

És possible “parlar” amb l’Arduino amb varietat de llenguatges, entorns i aplicacions, com podeu comprovar a http://playground.arduino.cc/Main/Interfacing.

A l’experiment 14 s’envia un senyal variable des de l’arduino pel monitor sèrie (pel port USB). El senyal és genera amb un divisor de tensió fet amb un potenciòmetre connectat a una entrada analògica, però en aquesta ocasió no es manipula cap sortida si no que el valor capturat s’envia pel port sèrie.

La novetat de l’experiment és que en comptes de capturar la dada enviada per la placa amb el Monitor Sèrie de l’Arduino IDE es fa servir una petita aplicació desenvolupada amb Processing. De la wiki: “Processing és una aplicació de codi obert amb un llenguatge per a la programació d’imatges, animació, i so. El processing és un projecte de codi lliure iniciat per Ben Fry (Institut Ample) i Casey Reas (UCLA Design / Media Arts), i és desenvolupat per artistes i dissenyadors com a alternativa a eines de programari patentades en el mateix camp, com Macromedia Flash o Director.”

Processing i Arduino IDE són molt similars. El paral·lelisme va més enllà del look-and-feel de l’entorn: els programes amb l’Arduino IDE són, bàsicament, un setup() i un loop(); amb Processing tenim també un setup() que s’executa un cop a l’inici de l’execució; i un draw(), que al igual que loop() s’executa contínuament.

Processing compta amb moltes llibreries realitzades i depurades per usuaris i compartides amb la comunitat, igual que l’Arduino IDE. En particular, compta amb una llibreria procesing.serial basada en la RxTx per a realitzar comunicacions pel port USB (serie). Internament, RxTx es basa en una llibreria nadiua al sistema operatiu hoste, que s’encapsula amb el mecanisme JNI de Java, i unes classes java que exposen la interfície de programació.

El programa proposat amb Processing escolta el port serie i, segons les dades que va rebent (entre 0 i 255, que corresponen als nivells de tensió variables amb el potenciòmetres connectat a l’entrada analògica de l’Arduino) es va canviant el color de fons d’una pantalla que mostra una imatge del logo d’Arduino.

4.14.1 Experiment 14 Amb Python, Pygame i pySerial

El cas és que m’he trobat un parell de problemes al codi del manual: el primer és que la imatge que es fa servir és referencia a través d’una URL. Aquesta URL ja no està disponible i cal canviar-la per una altre que que sí es pugui accedir. I segon: em fa l’efecte que el codi que es fa servir no està actualitzat a la darrera versió de la llibreria.

Vistes aquestes “dificultats” he optat per buscar una solució alternativa. Processing està molt bé, però com Python m’agrada molt, he assajat una solució amb Python i les llibreries Pygame i pySerial. Vet aquí el codi:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygame, sys, serial
from pygame.locals import *

if __name__ == "__main__":
    pygame.init()
    FPS = 25 # frames per second setting
    fpsClock = pygame.time.Clock()
    
    # set up the window
    board = pygame.display.set_mode((400, 300), 0, 32)
    pygame.display.set_caption('Arduino')

    # set up serial port
    ser = serial.Serial("/dev/ttyACM0", baudrate=9600)
    
    while True: # the main loop
        if ser.isOpen():
            A0_385 = ser.read(385) # 385 = 9600 / FPS
            A0 = ord(A0_385[0])
            FILL_COLOR = (A0, A0, A0)
        
            board.fill(FILL_COLOR)
        
        for event in pygame.event.get():
            if event.type == QUIT:
                ser.close()
                pygame.quit()
                sys.exit()

        pygame.display.update()
        fpsClock.tick(FPS)

Els programes fets amb Pygame tenen aquesta mateixa estructura setup-loop que es pot trobar als programes de Processing, o als programes de l’Arduino. És fàcil, doncs, “anar” de l’un a l’altre.

Val a dir que m’he trobat amb una dificultat que no havia previst: les diferents velocitats entre la producció de dades de la placa i la velocitat de consum, donada pel nombre d’iteracions per segon del bucle de lectura de dades i d’actualització de pantalla, que està controlat per fpsClock.tick(FPS).

La solució ha estat “descartar frames” que és el que aconsegueixo amb:

A0_385 = ser.read(385) # 385 = 9600 / FPS
A0 = ord(A0_385[0])
FILL_COLOR = (A0, A0, A0)

És dir llegeix 385 caràcters el buffer (385 = bauds / fps), però només té en compte el primer. Més que una dada precisa que permeti buidar el buffer de lectura en cada iteració, 385 (o 400) és, més aviat, un ordre de magnitud que es podria ajustar.

En tot cas, aquest valor funciona bastant bé, i movent el potenciòmetre de la placa, aconsegueixo que el color de fons de la pantalla variï gradualment en una escala de grisos entre el blanc i el negre.

4.14.2 Una “variació” de l’experiment 14 amb Scratch for Arduino

Scratch for Arduino (S4A) és un desenvolupament realitzat al Citilab de Cornellà.

De la pàgina web http://s4a.cat/index_ca.html: “Què és S4A? S4A és una modificació d’Scratch que permet programar la plataforma de hardware lliure Arduino d’una manera senzilla. Proporciona blocs nous per tractar amb sensors i actuadors connectats a una placa Arduino. També compta amb un panell de sensors similar al de la PicoBoard.

La finalitat principal del projecte és atreure gent al món de la programació. Un altre objectiu és proporcionar una interfície d’alt nivell per a programadors d’Arduino amb funcionalitats tals com la interacció amb un conjunt de plaques mitjançant esdeveniments d’usuari.”

Som-hi. Realment, aquest versió de l’experiment no segueix ben bé la mateixa lògica perquè amb S4A no puc llegir directament el monitor sèrie. El que faig es llegir el senyal de l’entrada analògica amb un sensor d’Scratch, i faig servir aquest valor per moure un sprite amb el gat d’Scratch per la pantalla.

El procés és el següent.

Descarrego i instal·lo l’S4A i el firmware de connexió (el programa d’interfície amb Scratch que realment s’executa a la placa Arduino i que és el que controla el port serie).

El circuit a la placa Arduino és el de l’experiment 14 tal com apareix al manual: un potenciòmetre fent de divisor de tensió entre Vcc i GND amb la pota de control connectada a l’entrada analògica A0.

Connecto per USB l’ordinador i l’Arduino i fent servir l’Arduino IDE carrego el firmware a la placa.

Ara engego l’S4A. No ha d’haver cap problema. L’S4A reconeix una placa Arduino connectada.

Aleshores, amb l’Scratch preparo una nova variable v_posx:

1-variable

aquest bloc per a “l’escenari”:

2-escenari

aquest per al gat:

3-gat

Li dono a la bandereta verda i, efectivament, ara tinc un gat corrent per la pantalla controlat pel potenciòmetre del circuit a la placa Arduino. Fixeu-vos en el valor de la variable de l’entrada A0 a les imatges.

4.15 Experiment 15.

I per acabar la revisió de l’Starter Kit, a l’experiment 15 se’ns anima a buscar aquelles andròmines velles que siguin susceptibles d’algun tipus de control electrònic i tractar d’imaginar com es podrien connectar a l’Arduino, i s’aprofita per presentar l’opto-acoblador 4N35.

60 anys de Lisp. Old rockers never die.

El programador no neix. Es fa.

La formació d’un bon programador passa per diverses etapes. En la etapa inicial hom aprèn un llenguatge. Normalment un llenguatge d’iniciació. Un llenguatge d’iniciació serveix, més que res, per comprendre conceptes de programació.  I no és tan important el seu rendiment o la seva aplicació en problemes reals.

Avui, per exemple, es fa servir, a nivell de ESO i secundària, el llenguatge Scratch (un fantàstic i versàtil entorn d’aprenentatge) com a llenguatge d’iniciació.

A nivells més avançats, hi ha més varietat. Sobretot als EUA es fa servir molt -com a llenguatge d’iniciació per a universitaris, repeteixo- el Lisp, en alguna de les seves encarnacions: Scheme, Racket, CLisp

Lisp és proper al llenguatge matemàtic, té una sintaxi mínima i no imposa gaires restriccions en quant a paradigmes de programació, tot plegat el fa molt versàtil per a presentar conceptes informàtics. Alguns dels millors i més influents manuals de programació fan servir el Lisp. Cal llegir al menys una vegada en la vida el llibre porpra: Structure and Interpretation of Computer Programs.

Potser sorprenentment, el Lisp es un llenguatge que es troba amb  facilitat a entorns productius Unix. Guile (Scheme), un altre dialecte de Lisp, és el llenguatge d’extensió oficial de les aplicacions GNU (un llenguatge d’extensió és, per entendre’ns, un llenguatge de macros). També es pot trobar Lisp sent part indestriable i indissoluble de l’Emacs, l’editor de texts més versàtil mai creat. Emacs, en ell mateix, està en molt bona part programat amb Emacs Lisp. La forma d’estendre Emacs és, evidentment, amb l’Emacs Lisp. La presència universal d’Emacs posa el Lisp allà on hi hagi un Emacs instal·lat.

Lisp (inventat per John McCarthy entre 1956 i 1958) és el segon llenguatge informàtic més antic encara en servei (el més antic, encara en servei, és Fortran. La primera especificació de Fortran va ser escrita per IBM a  1954). Aquesta timeline de la wiki us pot ajudar a situar-lo en el temps.

Estem parlant, doncs,  d’un llenguatge informàtic amb 60 anys d’història. Es diu de pressa. En termes informàtics tant de temps equival al pas  de vàries eres geològiques.

Però el millor del cas és que l’evolució del Lisp continua: és relativament senzill programar un interpret de Lisp i això fa que es puguin trobar dialectes per a multitud de plataformes. Concretament, per a la JVM en aquests moment hi ha una versió de Lisp que destaca sobre les altres: Clojure.

Clojure és un dialecte de Lisp que funciona sobre la JVM. Tot i que no imposa el paradigma, presenta una orientació envers la Programació Funcional (FP) [i Clojure FP ]. Val a dir que és possible fer FP, en general, amb dialectes comuns de Lisp.

Com a punt molt fort, es relaciona de forma senzilla amb la JVM, de forma que té accés a la infinitat de llibreries i frameworks de Java i, a l’hora, és senzill des de Java  invocar Clojure, o fer servir des de Java les classes desenvolupades amb Clojure.

Més enllà de la curiositat de portar Lisp a la JVM, sembla que Clojure està fent-se, poc a poc, això sí, amb una part de mercat en l’anàlisi de dades (on a hores d’ara dominen R i Python amb Pandas, sense comptar amb el clàssic SQL, o l’omnipresent Java).

Però, tornant al principi, en la formació d’un programador el primer pas acostuma a ser algun llenguatge d’iniciació que ràpidament es complementa amb l’aprenentatge de llenguatges més utilitzats professionalment i amb llenguatges de paradigmes diferents.

La programació amb diferents paradigmes dona una visió completa al programador. Li obre la ment. L’habilita per enfocar els problemes des de punts de vista diferents. Per això, un bon programador ho és de forma independent als llenguatges que conegui , tot i que, evidentment, el més probable i el més recomanable és que tingui alguns llenguatges preferents  que domini. I també que aquestes preferències vagin canviant amb el pas del temps. El bon programador és poliglot, i sempre té un ull posat en els nous llenguatges i paradigmes que van apareixent.

Dins la caixa d’eines del programador hom pot trobar, doncs,  diferents llenguatges per a diferents propòsits. Alguns llenguatges seran molt demandats professionalment, i altres, no tant, o gens ni mica. Però en l’arsenal mental del programador, aquesta varietat expressiva és riquesa i versatilitat.

Per acabar, l’objectiu del post d’avui era redescobrir Lisp i perquè crec que pot tenir interès dedicar un temps a aquest llenguatge. Com usuari que sóc d’Emacs (Emacs Lisp) i d’eines GNU (Guile i Scheme), Lisp té un caràcter pràctic. Com programador Java i que ha treballat més o menys amb anàlisi de dades, Clojure també em crida l’atenció.

La paraula clau és poliglotisme. Us deixo un enllaç: http://hyperpolyglot.org/. Es tracta d’un lloc web que ofereix taules de comparació entre llenguatges més o menys afins. En concret, us proposo fer un cop d’ull a aquestes taules:

Llenguatges d’Scripting : Node.js, PHP, Python i Ruby. [full 1]i [full 2].

Llenguatges d’anàlisi numèric i estadístic: MATLAB (i Octave), R, NumPy i Julia. [full 1] i [full 2].

Comparació entre dialectes de Lisp: Common Lisp, Racket (Scheme), Clojure, Emacs Lisp .

Què és Open Data?

Què és Open Data?  Viquipèdia:

Dades obertes(Open Data en anglès) són tots aquells conjunts de dades que es posen a disposició del públic i poden ser reutilitzats sense cap restricció.

Les dades són distribuïdes en un format obert que permet la seva manipulació sense cap restricció tècnica amb programari obert i sota una llicència i/o condicions d’ús que no impedeixen als usuaris finals revisar-les, remesclar-les i redistribuir-les a tercers.

Les dades haurien de satisfer certes condicions associades a la seva descripció, traçabilitat, qualitat, privacitat i interoperabilitat.

Té un esperit semblant al d’altres moviments “Oberts” i a comunitats com les de codi obert i d’accés obert. No obstant això, no estan vinculades i existeixen moltes combinacions possibles. La pràctica i la ideologia en si estan ben establertes (per exemple en la tradició mertoniana de la ciència), però el terme “Dades obertes” en si és recent.

En alguns casos les dades obertes es poden considerar més aviat com a Metadades obertes i encara no hi ha una formalització coherent.”

És dir, institucions, organitzacions de tota mena, empreses… posen a disposició de public dades, o meta-dades, per a la seva explotació lliure per terceres parts.

Quines dades obertes puc consultar? Seria força inútil exposar dades sense dir què són, per tant, les organitzacions que exposen dades obertes les acompanyen d’un catàleg que pren la forma d’un lloc web. Per exemple, el catàleg de l’Open Data de l’Ajuntament de Barcelona es troba a http://w20.bcn.cat/opendata/. El de la Generalitat a http://www20.gencat.cat/portal/site/dadesobertes

I un catàleg de catàlegs? Podem fer servir DataCatalogs.org, amb catàlegs d’Open Data d’organitzacions d’arreu del món.

Què es pot fer amb aquestes dades? Aprofitar-les. Desenvolupar aplicacions per a mòbils que les facin servir, per exemple. Creuar-les i enriquir-les amb altres dades, obertes o privades. Transformar les dades en informació útil, en definitiva. Hom pot veure-hi clarament una oportunitat de negoci i, més enllà, es veu clarament també com l’Open Data s’alinea amb les noves formes de fer servir la tecnologia que portaran i ens portaran a les Smart Cities.

Dono la veu als experts: a continuació encasto una conferència de la 24a sessió web que va tenir lloc al Centre d’Estudis Jurídics i Formació Especialitzada el dia 25 de maig de 2011, a càrrec de José Manuel Alonso, codirector del Grup d’eGovernment al Consorci W3C i membre del CTIC. Aquestes sessions s’emmarquen dins dels programes de formació del Departament de Justícia de la Generalitat de Catalunya i estan alliberades amb llicència Creative Commons de reconeixement de l’autor.

Més informació sobre aquesta conferència la podeu trobar a aquest enllaç.

Vet aquí el vídeo:

També podeu consultar la presentació SlideShare.
I la síntesi de la conferència.

Conferència Smart Cities a càrrec de Pilar Conesa a la FIB.

Aquesta tarda he assistit a una conferència sobre Smart Cities a càrrec de Pilar Conesa a la sala d’actes de la FIB.

Pilar Conesa és una veu autoritzada dins el món de les Smart Cities, com podem constatar al seu curriculum. Destacar que actualment és directora d’Anteverti, empresa dedicada a la planificació estratègica d’smart cities, i també és la diretora de l’Smart Cities World Congress, event de referència internacional que organitza Fira de Barcelona. Repeteixo, doncs, es tracta d’una veu autoritzada.

La conferència ha estat una introducció als conceptes principals de les smart cities. He trobat útil la definició del vocabulari associat a les smart cities: smart grids, smart mobility, smart building, smart metering… entre d’altres; o la necessitat d’un enfocament multidisciplinar, tecnològic, sens dubte, però també econòmic, polític, social… de la planificació de les smart cities; o el requeriment d’un enfocament “a mida” per a cada ciutat, o mancomunitat de municipis petits que es plantegin l’evolució a la smart city.

Ha plantejat, a més, la necessitat d’aquesta evolució com una resposta al desafiament immens que representa la crisi. L’econòmica, potser avui la més visible, però no pas l’única ni la més greu a la que ens enfrontem, doncs també hi són l’energètica i la climàtica.

Ens ha dit  -també ho penso i per això he anat a la conferència-  que les smart cities, amb aquest nom o amb un altre, han vingut per a quedar-se. Caldrà  millorar l’eficiència energètica, ambiental, econòmica de les ciutats. L’escassedat dels recursos energètics i de tota mena portaran inevitablement a solucions en la línia de les smart cities.

A la vegada, les smart cities suposaran i reclamaran uns canvis profunds en la forma com es viu en elles. Canvis en el dia a dia. He trobat molt interessant la necessitat de ciutadania intel·ligent, de col·laboració ciutadana, del “compartir enlloc de posseir”, o al canvi, opino que el més radical de tots, que suposaran les smart grids: la generació distribuïda d’energia i la xarxa de transport intel·ligent (en la línia del que anunciava Jeremy Rifkin a “L’economia de l’Hidrogen”). També com aquestes noves formes de fer també abocaran a nous models de gestió, de contractació (potser basada en SLAs)o,  també, en  canvis en els models de retribució.

Potser el dubte més gran que m’ha quedat ha estat: i com queda la democràcia en tot això? Les smart cities pretenen un triple objectiu: millorar la qualitat de vida dels ciutadans, millorar l’eficiència energètica i ambiental, millorar la eficiència econòmica de la ciutat. Tots tres elements simultàniament. Però hi ha un cas paradigmàtic: A la Xina s’estan fent inversions milionàries en Smart Cities. Sens dubte que els ciutadans xinesos tindran més qualitat de vida. Però, seran més lliures? o, pel contrari, estaran més controlats?

Les smart cities poden ser ciutats eficients per a ciutadans lliures, o bé presons daurades. Potser caldria, en algun moment, parlar dels reptes ètics que poden representar incrementar la sensorització de les ciutats.

Avui tots som “traçables” fins extrems insospitats. Amb les smart cities encara ho serem molt més. Això no és dolent en si mateix, a menys, és clar que aquest volum d’informació s’empri amb la intenció d’incrementar el control i, donat el cas, reprimir les dissidències. Enfront l’administració el ciutadà sempre és el dèbil. Com es gestionarà la privacitat?

Encara relacionat amb el punt anterior, m’ha xocat el concepte de “ciutadà sensor”. La idea pot ser molt bona si el ciutadà accepta i està d’acord en ser captador i font de dades. Però i si ho es sense saber-ho? i amb quines finalitats? qui se n’aprofitarà? ho relaciono amb un programa de TV que vaig veure fa poc que parlava de neuro-marqueting.

Més: a dia d’avui, quanta i quina informació personal, però ciutadans sensors, ja està en mans i és gestionada estrictament des d’interessos privats?  En l’extrem oposat, l’Open Data, l’exposició pública de bases de dades de diferents tipus, per a la seva explotació per part de terceres parts, també planteja preguntes interessants. Queda pendent un post sobre Open Data.

Els “ciutadans sensors” són primer de tot, persones. No som objectes. Convindria tenir això sempre en ment al planificar les ciutats intel·ligents..

En tot cas, ha estat un privilegi poder assistir a aquesta conferència.

He trobat aquesta conferència que Pilar Conesa va donar a Vilajuïga, a alcaldes i regidors empordanesos. Us donarà una idea força aproximada de com ha anat la conferència d’avui.

http://vimeo.com/39598540

A més del vídeo anterior, hi ha un material addicional interessant: la presentació de Pilar Conesa ha estat realitzada amb Prezi. He buscat a veure si trobava el prezi de la presentació i he trobat que en té unes quantes de preparades:


Smart Cities. La ciudad colaborativa.

Smart Cities. Oportunitat de desenvolupament professional per als fibers.
Smart Cities. La tecnologia al servicio de la ciudad colaborativa.
Smart Cities a la UOC. Innovación y tecnología para una ciudad sostenible.
Smart City y sostenibilidad ambiental.

Finalment, al torn de debat, des del públic s’ha suggerit un parell d’d’apunts interessants per als emprenedors: la FIB ha convocat un concurs d’Apps per a Smart Cities; Segon: iCity Project, que pretén l’apertura de infraestructures (també els recursos TIC) i espais públics per a la co-creació d’aplicacions i serveis d’interès públic per terceres parts

Tornar a programar amb Java

Crisi és canvi. Els canvis requereixen una ment oberta. Les activitats professionals canvien i, potser, ens cal recuperar i actualitzar coneixements.

Posem un cas, i d’això va aquest post:  imaginem que fa pocs anys érem capaços de desenvolupar aplicacions java de servidor; vam passar a dirigir un equip de desenvolupament i vam abandonar les tasques més tècniques, o potser vam fer un canvi de tecnologia. Avui, però, les circumstàncies ens porten a haver d’afrontar de nou desenvolupaments amb Java, o tornar a aquesta tecnologia o, senzillament, volem deixar-nos aquesta porta oberta. Ens hem de posar al dia en Java. Suposem que vam deixar Java quan els temps del JDK 1.4.2

 

Llenguatge Java

Partim , doncs, d’un coneixement previ del llenguatge, potser una mica rovellat, però res que no s’arregli amb unes poques hores de revisar codi. Cal dir que la versió actual de JDK és la 1.7, o Java 7. El Java 7 té algunes construccions que no tenia el JDK 1.4.2. Potser les més cridaneres són les anotacions, les templates, alguna sintaxi nova pels bucles. Amb el futur Java 8 (estava previst per al Java 7, però va caure) s’espera l’arribada de les “closures” i característiques de programació funcional. L’evolució del llenguatge la podeu trobar a http://en.wikipedia.org/wiki/Java_version_history.

Per a un repàs del JDK, pot anar bé aquest enllaç: http://docs.oracle.com/javase/tutorial/java/index.html

Aquestes característiques s’utlitzen als frameworks més actuals. Ara bé, juntament amb aquestes característiques noves també estan els POJO, els Plain Old Java Object, els objectes java “de tota la vida”, i els frameworks més moderns procuren que una de els seves característiques sigui, justament, que es poden fer servir amb els POJOs.

Refrescar la sintaxi és el primer pas.

 

Java SE, EE, ME i Android

En aquest punt podem triar camins, hi han tres vies principals mantingudes per Oracle i una quarta per Google. cada via té el seu SDK respectiu, Els SDK son paquets amb eines i llibreries java que implementen unes especificacions estandaritzades de tecnologies relacionades amb un determinat tipus d’aplicacions:

  • Les aplicacions java d’escriptori, el Java SE;  La Standard Edition. El JDK de tota la vida.
  • Les aplicacions java de servidor, el Java EE; la Enterprise Edition. Servlets, EJB, Servidors d’aplicacions…
  • Les aplicacions de mobilitat i per a sistemes encastats, el Java ME; la Micro Edition, java als telefons mòbils no Android, a dispositius i sensors “smart” de tota mena, targetes intel·ligents,  televisors…
  • Les aplicacions Android. Els dispositius Android  defineixen un entorn de desenvolupament i un runtime d’execució en que el principal llenguatge de desenvolupament, no l’únic, és java.

L’ambient en que es desenvolupen les aplicacions de servidor és la Java EE. Realment, EE i SE no estan separades i Java EE és, més aviat, un superconjunt de java SE que l’amplia amb llibreries i packages orientats al desenvolupament enterprise.

Java EE es troba actualment en la versió 6, la Java EE 6.

Una bona referència és The Java EE 6 Tutorial (PDF). Aquest tutorial és força més dens que l’anterior.<

 

Patrons de disseny i Frameworks

El desenvolupament d’aplicacions Java EE amb entitat demana, a més de l’SDK, llibreries i frameworks de suport. La tria del framework i arquitectura adequats és, segurament, el factor d’èxit més important en el desenvolupament d’aplicacions EE. En aquest sentit, és molt bo repassar la bibliografia disponible sobre patrons de disseny. Un repàs ràpid a http://www.oodesign.com/.  El llibre clàssic sobre patrons de disseny és el “Design Patterns: elements of reusable object-oriented software“.Però el més important són els frameworks. Res no impedeix fer una aplicació només amb jsp i servlets fets a ma al més pur old-style, però no és una bona idea. Serà mollt més productiu fer servir un framework que, ell tot sol, ja doni una bona part de la feina feta.

 

Spring

El framework més utilitzat per a desenvolupar aplicacions web l’Spring Framework, que és part del projecte Spring. Spring Framework fa funcionar juntes tot un conjunt de mòduls i llibreries: des deLog4j, fins a Hibernate, passant per Struts. Per dir-ne només algunes. Cadascuna de les caixetes que surten a la imatge de sota gairebé és un món. És recomanable fer-lis un cop d’ull. No dic de conèixer-les en detall, però sí saber “de què van” per a que, si arribat el moment, saber per on agafar-ho.

spring-overview

Aquest tutorial explica com fer pas a pas una aplicació Spring basada en el patró MVC: http://www.davidmarco.es/tutoriales/spring-mvc-sbs/

Els manuals de referència de la darrera versió (a dia d’avui) de l’Spring Framework en HTML / PDF

Spring encara pot fer les coses més fàcils. Amb Spring ROO si volem crear una aplicació nova, en comptes de crear l’estructura des de zero, disposem una eina per a crear de forma automàtica l’esquelet (i alguns organs vitals) de l’aplicació. La generació automàtica de codi ara rep el nom d’scaffolding. Un anglicisme més.

Per cert, vinculat a Spring, però fent una vida apart, hi ha Groovy,  (i Grails, Groovy on Rails) que és  essencialment un java interpretat, és dir, sense declaració de tipus. Groovy permet desenvolupar scripts, interactuar amb objectes java… Ja n’he parlat en posts anteriors. Cal esmentar-lo.

 

Eines

A més dels frameworks, les eines són importants. No cal que presenti Eclipse. Degut a que és un IDE open-source es fa servir com a base per a crear IDES específics. En concret hi ha un Eclipse IDE for Java EE developers , o un Spring Tool Suite que no és més que un Eclipse “tunejat” per Spring.

A l’Eclipse hi podem afegir plugins que resolen qüestions com el control de fonts i el treball en grup. El plugin Subclipse, per exemple,  permet atacar repositoris de fonts Subversion. El que està de moda ara és Git.

A més dels IDE ens calen servidors locals de desenvolupament. N’hi han un munt, els servidors de servlets i JSP Tomcat o Jetty, passant pels servidors d’aplicacions amb contenidor EJB, com GeronimoGlassFish o JBoss. Tots ells poden ser, a més, servidors de producció. L’administració de servidors és un món en ella mateixa.

 

L’equip de desenvolupament java

Això em porta a un altre punt que crec que cal considerar: què vol dir “fer java” o “ser un javero”. Java és un llenguatge que permet nivells molt alts d’abstracció. A més, quan afegim frameworks, els nivells d’abstracció encara poden ser més alts. Què vol dir això? que, en realitat, el “programador java estricte” no existeix. Com a mínim estem parlant de perfils d’analista programador. Senzillament perquè el llenguatge permet centrar-se més en la solució, que no haver de pensar en la tecnologia. Un analista-programador en java ha de ser capaç de programar, i ha de tenir un coneixement suficient de les arquitectures i frameworks sobre els que treballa.

En un equip de desenvolupament java, a mida que es vagi fent gran, caldrà anar introduint perfils més especialitzats i tècnics. Administradors de Respositori de Fonts, Administradors dels Servidors d’Aplicacions, amb capacitat per instal·lar i fer el manteniment d’aquests servidors. Especialistes en els frameworks, per prestar suport, instal·lar els frameworks i posar en marxa les arquitectures, o extendre els frameworks amb noves capacitats. Són rols que hauria d’assumir algú de l’equip de desenvolupament amb formació o experiència específica.

Finalment, la gestió del projecte: de l’equip, de l’usuari, de l’agenda i del cost. En definitiva, la metodologia de treball (metodologies àgils? o pesades com RUPquè triar?). Si en comptes de projectes, parlem de manteniments, aleshores potser ens cal recordar ITIL i com implementar-lo; i els diferents programaris que el poden suportar, per exemple, de gestió d’incidències, com BMC Remedy o, a un altre nivell, Mantis BT.

 

On es fa servir Java? té futur això?

I, per acabar, cap a on crec que aniran les coses:

A dia d’avui, els perfils java estan buscats. La demanda ve impulsada per la telefonia mòbil, i per la irrupció del mercat “smart”. La propera revolució, si no m’equivoco, serà la de les Smart Cities. Les ciutats intel·ligents, verdes, segures, netes i eficients, potser més democràtiques i tot. Les Smart cities funcionaran sobre una gran xarxa de telecomunicacions que interconnectaran dispositius i sensors de tota mena i fluxos d’energia en “smart” grids de forma que estarem parlant de la “Internet de les coses”. En tot aquest maremàgnum de servidors, Data Ware Houses, Temps Real, sensors i disposotius smart (evidentment amb els smartphones com a dispositius estrella) el Java està molt ben posicionat per a ser el llenguatge dominant.

 

Pot ser una bona idea posar-se al dia en Java.

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.

Smart City Expo World Congress 2012. Barcelona, del 13 al 15 de novembre.

Aquesta propera setmana, del 13 al 15 de novembre es celebrarà a Barcelona la Fira Smart City Expo World Congress.

Que a Barcelona es celebrin fires no és cap novetat. El que sí que pot sonar novedós, tot i que ja fa temps que se’n parla, és el concepte d’Smart City.

Què és una smart ciy? la smart city és la ciutat intel·ligent. La ciutat que aplica les tecnologies TIC per captar informació diversa amb els sensors adequats per prendre el pols a les constants vitals de la ciutat, i processar-ne aquesta informació amb l’objectiu de fer que la ciutat sigui  més eficient, més neta, més democràtica i, en definitiva, més habitable i respectuosa amb el medi ambient.

Podem  posar matisos a la definició anterior: per exemple, la pàgina http://smartcity-telefonica.com/ pren el subtítol “un primer paso hacia la Internet de las cosas”. És dir, la  Internet of Things, o  IoT, mireu http://www.iot-i.eu/public/front-page .

També podem consultar la web del projecte http://smartbarcelona.cat/ que compta amb el suport de la Unió Europa i de la Generalitat de Catalunya i que pretén “definir, dissenyar i desenvolupar un model de referència d’una plataforma de gestió de xarxa i dades sensorials per a Smart Cities, i finalment validar-lo en una ciutat important com és Barcelona, amb l’objectiu final que aquest model pugui ser adoptat per qualsevol altra ciutat arreu del món”. Val a dir, però,  que la web en qüestió em sembla excessivament estàtica i sembla abandonada (no hi ha cap notícia  en cap dels tres idiomes!).

De nou, podem consultar una altre web relacionada amb Telefónica: http://sociedadinformacion.fundacion.telefonica.com.En  aquesta web trobem l’article ¿Qué son las ‘Smart Cities’ o Ciudades Inteligentes? per José Manuel Hernández Muñoz de Telefónica I+D, que planteja de forma força entenedora què és una smart city, quins projectes hi han rel·lacionats , o quins avatanges aporta al ciutadà.

El matís ecològic és important i es parla també de les smart green cities. Aquesta passada setmana es va celebrara  Tarragona el I Congrés d’Eficiència Energètica i Smart Green Cities celebrat durant dos dies al Palau Firal. El congrés va comptar amb la participació de Jeremy Rifkin, autor  de “La era del acceso”, “El fin del trabajo” o “La economía del Hidrógeno”, entre d’altres, i assessor d’Al Gore i Bill Clinton. Amb aquest congrés es pretén llançar el projecte de convertir Tarragona en la smart green city de referència al Mediterrani i es vincula aquest projecte amb els Jocs del mediterrani que es celebraran a la ciutat el 2017. Estic buscant per alguna banda la “Declaració de Tarragona” que es va llegir al congrés per enllaçar-la aquí, però de moment, no l’he sabut trobar, o no està disponible per al públic.

El projecte Tarragoní ens recorda l’existència de projectes similars, per exemple http://www.smartcities.info/aim que involucra  ciutats de diversos països de la regió del mar del nord.

Finalment, les Smart Cities són objecte d’anàlisi i reflexió arreu del món. Podeu consultar les següents adreces

Universitat d’Stanford:  http://sprie.gsb.stanford.edu/research/smart_green_cities

Massachussets Institute of Technology – MIT: MIT Cities, http://cities.media.mit.edu/

Smart cities, doncs. Les TIC aplicades a fer ciutats més netes, eficients i, esperem, democràtiques. Una oportunitat de negoci? segurament sí. Però encara més important, una gran oportunitat per començar a canviar models.

Recordem: aquesta propera setmana, del 13 al 15 de novembre es celebrarà a Barcelona la Fira Smart City Expo World Congress. Feu un cop d’ull al programa. El preu de les acreditacions varia des dels 30€, passe de visitant d’un sol dia només per a l’exposició, fins al passe de tres dies, amb accés a totes les conferències i esdeveniments, per 700€.

En tot cas, sempre podrem esperar a que els diferents expositors i conferenciants publiquin els vídeos i presentacions de la seva participació. Com aquests vídeos corresponents a l’exposició de l’any passat

http://www.casadomo.com/

http://www.domonetio.com/

http://www.esmartcity.es/

Com preparar un entorn de desenvolupament per a Python for Android.

En un post anterior vaig presentar el Python for Android (Py4A), que és un python per a dispositius Android que funciona sobre l’Scripting Layer For Android (SL4A).

En aquell post presentava diversos scripts que es podien executar sobre el dispositiu Android. O sobre l’emulador d’Android que es troba disponible a l’Android SDK.

Tanmateix, en eaquell post no parlava dels entorns disponibles per a desenvolupar els scripts. Com puc desenvolupar amb Py4A de forma còmoda?

Prerequisits

Evidentment, és prerequisit tenir instal·lat a la tablet l’SL4A i el Py4A.
A l’ordinador que farem servir per desenvolupar cal tenir el JDK 1.6 de Java, com a mínim. El JDK permetrà instal·lar, a continuació l’Android SDK, el qual ens proporciona les eines que ens interessen: l’adb i el ddms. El DDMS és, en realitat, una aplicació Java.

L’Android SDK proporciona un parell d’eines que seran útils per a desenvolupar scripts Python: l’Android Debug Bridge (adb) i el Dalvik Debug Monitor Server (ddms).

Per a poder aprofitar les dues eines esmentades caldrà posar l’SL4A en “mode servidor”. Amb la combinació del “mode servidor”, l’adb, el ddms, i un cable usb serem capaços de desenvolupar scripts python al nostre ordinador i executar-los de forma immediata al dispositiu Android o a l’emulador de l’Android SDK.

Connectar el dispositiu per USB.

El que ve a continuació està basat en https://help.ubuntu.com/community/AndroidSDK

El primer pas ha estat aconseguir que l’adb i el ddms reconeixessin la meva tablet. Es tracta d’un model barat de fabricació xinesa: una tab-playtabpro de Point-of-View, que munta un sistema operatiu Android 4.0.3.

Activar depuració USB
Per a fer-ho, he connectat la tablet a l’ordinador amb el cable USB. NO he activat l’emmagatzematge USB. Quan s’activa l’emmagatzematge USB, per seguretat, hi han tot un seguit d’opcions que es desactiven a la tablet. En particular, es perd la visibilitat de sdcard. Repeteixo: NO he activat l’emmagatzematge USB. Aleshores he posat la tablet en mode de “depuració USB”. Per a fer això he anat a la configuració de la tablet, a les “opcions de desenvolupador” dins del submenú “Sistema” i allà he marcat “Depuració d’USB”, com es veu a la imatge:

ID Vendor
(de http://developer.android.com/tools/device.html)
En un terminal he executat l’ordre lsusb (estic fent les meves proves amb un Linux Lubuntu 12.04).

albert@athena:~$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 003: ID 058f:6254 Alcor Micro Corp. USB Hub
Bus 003 Device 002: ID 1631:5400 Good Way Technology 
Bus 003 Device 003: ID 1631:5002 Good Way Technology 
Bus 003 Device 004: ID 045e:00f6 Microsoft Corp. Comfort Optical Mouse 1000
Bus 001 Device 008: ID 0781:5535 SanDisk Corp. 
Bus 002 Device 006: ID 18d1:0003 Google Inc. 

Observo el dispositiu Bus 002 Device 006: ID 18d1:0003 Google Inc. És la meva tablet. M’interessa l’ID 18dl. Aquest paràmetre el faré servir per a crear un fitxer de filtre amb

sudo leafpad /etc/udev/rules.d/51-android.rules

Si el fitxer no existeix, aleshores el crea. Cal afegir la línia següent. En negreta, el ID Vendor que he trobat amb lsusb

SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666", GROUP="plugdev"

i li donem els permisos adequats amb

sudo chmod a+r /etc/udev/rules.d/51-android.rules

Finalment, el fitxer que he creat:

albert@athena:~$ ls -al /etc/udev/rules.d/51-android.rules
-rw-r--r-- 1 root root 70 ago 17 19:25 /etc/udev/rules.d/51-android.rules
albert@athena:~$ 

Amb l’anterior ja hauria de tenir prou com per a poder activar el DDMS i l’ADB

Si tot ha anat bé, Engegant el DDMS (l’script ddms el trobaré a HOME_ANDROID_SDK/platform/tools/) el dispositiu apareixerà “online”, com a la imatge de sota.

En cas de no haver-se pogut establir la connexió, apareixeran ?????????.???. Caldrà revisar què és el que no hem fet bé.

En aquest moment, amb el DDMS ja podem fer coses com:
– còpies de la pantalla del dispositiu Android.
– enviar i rebre fitxers a i del dispositiu.
– analitzar el consum de memòria de les aplicacions del dispositiu
– analitzar el tràfic de xarxa de les aplicacions.
– emular l’entrada i sortida de trucades telefòniques, SMS, simular ubicació per a testejar el posicionament.
– …

Python en Server Mode

A continuació he posat l’SL4A en Server Mode. Primer de tot, obro SL4A

Per comoditat, preestableixo el port del Server Mode a 50000 (ha de ser un port lliure, i els port “alts”, per sobre de 32768 acostumen a estar-ho). Com alternativa, si poso 0 al valor del port, aleshores el SL4A és el que tria el port. En aquest últim cas, però, com em caldrà després, hauré de revisar quin port ha establert.

Per a fer-ho, primer de tot, al SL4A obro el menú de preferències:

Trio l’opció Server Port:

I l’estableixo a 50000.

A continuació, obro la vista d'”Interpreters”

Activo el mode Servidor (Start Server)

I l’inicio en mode “Privat”

En aquest moment, el SL4A – Py4A ja està iniciat en mode servidor, com podem veure a la notificació:

Vull confirmar que el port del servidor és el 50000. Si faig click a l’icona de l’SL4A s’obre la notificació que em mostra els scripts de SL4A que estan en funcionament:

I obtinc el port. Efectivament és el 50000.

Ja gairebé ho tinc tot a punt.

android.py

Finalment, he d’obtenir de la carpeta d’android el fitxer android.py i l’he de copiar a l’ordinador. Aquest android.py s’ha d’importar en els scripts de Py4A i, per tant, haurà de ser “visible” des de l’interpret de python de l’ordinador. Android.py actua com a proxy entre l’interpret de Python i l’SL4A. Aquesta comunicació quan el SL4A està en server mode es fa per RPC, de forma que realment no cal que l’interpret i el SL4A resideixin a la mateixa màquina. Aquest fet és el que permet desenvolupar a l’ordinador i executar a la tablet.

Per a obtenir el fitxer android.py de la tableta faré servir el File Explorer del ddms.

El fitxer es troba a /sdcard/com.googlecode.pythonforandroid/extras/python

Aleshores fent servir el botó “Pull File From Device”, El botó amb l’icona del disquet del File Explorer, puc copiar android.py a la carpeta de fonts python amb la que treballaré. En el meu cas l’he copiat a /home/albert/workspace/wk-python/prova-py4a

adb forwardind
Finalment, obro un terminal i em poso a la carpeta de fonts, i faig el següent:

albert@athena:~/workspace/wk-python/prova-py4a$ /home/albert/android-sdk-linux/platform-tools/adb start-server
albert@athena:~/workspace/wk-python/prova-py4a$ /home/albert/android-sdk-linux/platform-tools/adb forward tcp:9999 tcp:50000
albert@athena:~/workspace/wk-python/prova-py4a$ export AP_PORT=9999

El port 9999 és troba a la major part de la literatura sobre SL4A, però és per convenció.

Fixem-nos que les quatre línies anteriors sempre seran les mateixes, o sigui que les puc posar en un script.

Dit i fet, el meu script per engegar l’entorn d’sl4a és aquest.

#!/bin/bash

/home/albert/android-sdk-linux/tools/ddms &
/home/albert/android-sdk-linux/platform-tools/adb start-server
/home/albert/android-sdk-linux/platform-tools/adb forward tcp:9999 tcp:50000
export AP_PORT=9999
idle &

Li en dono els permisos d’execució (chmod a+x sl4a)

A L’script primer engego el ddms per si em cal passar scripts de l’ordinador a la tablet, o per si cal controlar l’us de memòria, comunicacions, o per si vull fer còpies de pantalla… Després engeo l’adb i li passo els ports 9999, i 50000 (el que he preestablert per al SL4A Server Mode). Finalment, exporto la variable AP_PORT i, finalment, engego IDLE, l’IDE de pyhton construit amb TkInter.

En cas que no el tingueu instal·lat, IDLE es pot instal·lar amb Synaptic, o des del Centre de Programari de l’Ubuntu

Finalment, des de l’IDLE faig la prova canònica:

I, com no podria ser d’una altre forma, funciona 😉

Hem construït un entorn de desenvolupament per a SL4A i Py4A amb:
Un cable USB
Un ordinador amb
Lubuntu 12.01
JDK1.6
Android SDK
IDE de Python IDLE
Una tablet barata.

Albert Baranguer – 26.08.2012

HTML5. WebSockets amb Jetty

Continuant amb l’exploració de l’HTML5, avui parlo dels WebSockets. I per a il·lustrar-lo, faré un petit exercici amb websockets fent servir el servidor java Jetty.

La idea de l’exemple l’he tret del projecte http://code.google.com/p/phpwebsocket/. El client html és pràcticament idèntic. La part del servidor, en el meu exemple, l’he implementada amb Java; estant en PHP en l’original.

Els WebSockets permeten realitzar la comunicació bidireccional i full-duplex sobre un canal TCP, entre la pàgina web i el servidor de forma molt més eficient que amb l’esquema de petició-resposta de l’HTML, o que la comunicació amb AJAX o, més explí­citament, mitjançant Comet.

El protocol WebSocket es descriu a la RFC6455.

A dia d’avui, aquest protocol es troba implementat per les darreres versions dels principals navegadors:  Chrome, Internet Explorer, Firefox i Safari.

A més, el servidor ha de soportar també els WebSockets de servidor.

En si mateix el protocol recorda una crida HTTP, però no ho és:

Exemple de petició des del client:

GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

Exemple de resposta del servidor:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

Des del punt de vista del desenvolupament parlem, doncs, de clients i servidors de WebSockets.
HTML5 ofereix una API (normalitzada pel W3C) per a desenvolupar clients d’aplicacions basades en WebSocket.

Per la banda del servidor, els llenguatges més utlitzats, com Java o php aporten classes, mètodes i funcions per a crear i utilitzar websockets de servidor.

Sobre servidors Java: jWebSocket, Apache Tomcat i Jetty també tenen implementacions de sockets de servidor.
Sobre servidors PHP: phpWebSockets

Podem trobar implementacions de servidor WebSocket amb altres llenguatges. Per exemple amb Python una cerca ens proporciona: pywebsocket, o WebSocket for Python (ws4py).

Per a fer un experiment senzill utilitzaré el servidor de java servlets Jetty (versió 8) que proporciona una implementació java de WebSockets de servidor. Podeu revisar aquest article: Jetty WebSocket Server, i aquest altre: Jetty/Feature/WebSockets.
Per descomptat, el javadoc: http://download.eclipse.org/jetty/stable-8/apidocs/

Per a provar els WebSockets he creat un petit projecte amb Eclipse, amb la següent estructura de carpetes:

A la carpeta src hi creo el package java amb la següent classe: com.stsoftlliure.proves.html5.websockets.ProvaWebSocket

Fitxer ProvaWebSocket.java:

package com.stsoftlliure.proves.html5.websockets;

import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketServlet;
import org.eclipse.jetty.util.log.Log;
public class ProvaWebSocket extends WebSocketServlet  {

   private static final long serialVersionUID = 8442112605629206192L;


    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
    throws ServletException ,IOException  {
      response.getOutputStream().println("aquesta és la resposta");
      Log.info("[doGet] No fa res");
    }

    public WebSocket doWebSocketConnect(HttpServletRequest request,
                                        String protocol) {
      Log.info("[doWebSocketConnect] entra a doWebSocketConnect");
      return new ProvaServerWebSocket();
    }

    // inner class que implementa la interface WebSocket
    class ProvaServerWebSocket implements WebSocket.OnTextMessage {
      // la connexió
      Connection wsConn;
      Date dataInici;

      public ProvaServerWebSocket() {
         dataInici = new Date();
      }

      @Override
      public void onClose(int arg0, String arg1) {
         // TODO Auto-generated method stub
         Log.info("[onClose] arg0:" + arg0 + "; arg1: " + arg1);
         wsConn.close(arg0, arg1);
      }

      @Override
      public void onOpen(Connection wsConn) {
         this.wsConn = wsConn;
         try {
            Log.info("[onOpen] wsConn:" + wsConn);
            wsConn.sendMessage("Estic connectat!");
         } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.debug("Error: " + e.toString());
         }
      }

      @Override
      public void onMessage(String sMessage) {
         // TODO Auto-generated method stub
         Log.info("[onMessage] Missatge rebut: " + sMessage);
            // fa el tractament:
         // to do
         // help, hola, nom, edat, data, adeu
 
         try {
            if (sMessage.trim().equalsIgnoreCase("help")) {
               wsConn.sendMessage("ordres acceptades: help, hola, nom, edat, data, adeu");
            }

            if (sMessage.trim().equalsIgnoreCase("hola")) {
               wsConn.sendMessage("Hola! benvingut al servidor WebSocket!");
            }

            if (sMessage.trim().equalsIgnoreCase("nom")) {
               wsConn.sendMessage("Jo em dic ProvaWebSocket.class");
            }

            if (sMessage.trim().equalsIgnoreCase("edat")) {
               wsConn.sendMessage("En funcionament des de: " + dataInici);
            }

            if (sMessage.trim().equalsIgnoreCase("data")) {
               wsConn.sendMessage("ara són les: " + (new Date()));
            }

            if (sMessage.trim().equalsIgnoreCase("adeu")) {
               wsConn.sendMessage("Adéu siau!");
               wsConn.close();
            }
         } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.debug("Error: " + e.toString());
         }
      }
   }
}

Algunes remarques a la classe anterior:

– La classe és un servlet del tipus nou WebSocketServlet.
– Els WebSocketServlet implementen el doGet. El puc invocar directament i obtinc una resposta HTML. Però la funcionalitat apareix amb el nou mètode doWebSocketConnect. A doWebSocketConnect és on treballa el socket de servidor.
-Quan es rep una nova connexió, el mètode doWebSocketConnect el que fa és instanciar la inner class ProvaServerWebSocket, que implementa la interface WebSocket.OnTextMessage.
– La interface WebSocket té altres subinterfaces, a més de la OnTextMessage, per a tractar altres tipus de connexions. Les subinterfaces de WebSocket són: WebSocket.OnBinaryMessage, WebSocket.OnControl, WebSocket.OnFrame, WebSocket.OnTextMessage.
– en la connexió onOpen, obtinc l’objecte Connection wsConn. Que serà propiament el canal full duplex entre servidor i client.
– El tractament d’un missatge rebut el faig en implementar el mètode public void onMessage(String sMessage). sMessage és el missatge rebut des del client. Les respostes al client s’envien mitjançant l’objecte Connection wsConn obtingut en l’event onOpen. En aquest exemple, simplement analitzo quin missatge rebo i, depenent del missatge, envio una o altre resposta al client.
– A la sortida onClose, tanco la connexió

Senzill i net, oi?

L’altre part és la pàgina del client. Una pàgina HTML5 que fa servir websockets ha d’implementar els mètodes que responen als esdeveniments de connexió, alliberament, recepció i enviament de missatges al servidor. Vet aquí la pàgina HTML que dialoga amb el servidor:

Fitxer prova.html

<html>
<head>
<title>WebSocket</title>

<style>
 html,body{font:normal 0.9em arial,helvetica;}
 #log {width:440px; height:200px; border:1px solid #7F9DB9; overflow:auto;}
 #msg {width:330px;}
</style>

<script>
var socket;

function init(){
  var host = "ws://localhost:8080/websockets2/servlet/WebSocket";
  try{
    socket = new WebSocket(host);
    log('WebSocket - status '+socket.readyState);
    socket.onopen    = function(msg){ log("Welcome - status "+this.readyState); };
    socket.onmessage = function(msg){ log("Received: "+msg.data); };
    socket.onclose   = function(msg){ log("Disconnected - status "+this.readyState); };
  }
  catch(ex){ log(ex); }
  $("msg").focus();
}

function send(){
  var txt,msg;
  txt = $("msg");
  msg = txt.value;
  if(!msg){ alert("El missatge no pot ser nul"); return; }
  txt.value="";
  txt.focus();
  try{ socket.send(msg); log('Enviat: '+msg); } catch(ex){ log(ex); }
}

function quit(){
  log("Adéu!");
  socket.close();
  socket=null;
}

// Utilities
function $(id){ return document.getElementById(id); }
function log(msg){ $("log").innerHTML+="<br>"+msg; }
function onkey(event){ if(event.keyCode==13){ send(); } }
</script>

</head>
<body onload="init()">
 <h3>WebSocket</h3>
 <div id="log"></div>
 <input id="msg" type="textbox" onkeypress="onkey(event)"/>
 <button onclick="send()">Send</button>
 <button onclick="quit()">Quit</button>
 <div>Commands: help, hola, nom, edat, data, adeu</div>
</body>
</html>

Alguns comentaris: com es veu, la pàgina és senzilla, la clau del funcionament està al mètode init

function init(){
  var host = "ws://localhost:8080/websockets2/servlet/WebSocket";
  try{
    socket = new WebSocket(host);
    log('WebSocket - status '+socket.readyState);
    socket.onopen    = function(msg){ log("Welcome - status "+this.readyState); };
    socket.onmessage = function(msg){ log("Received: "+msg.data); };
    socket.onclose   = function(msg){ log("Disconnected - status "+this.readyState); };
  }
  catch(ex){ log(ex); }
  $("msg").focus();
}

El qual crea l’objecte socket, el connecta al host, adonem-nos del protocol “ws”; i enllaça els esdeveniments del socket: onopen, onmessage, onclose amb les funcions que els tracten.

L’enviament de missatges al servidor es realitza amb la funció send, que invoca al mètode send de l’objecte socket.

function send(){
  var txt,msg;
  txt = $("msg");
  msg = txt.value;
  if(!msg){ alert("El missatge no pot ser nul"); return; }
  txt.value="";
  txt.focus();
  try{ socket.send(msg); log('Enviat: '+msg); } catch(ex){ log(ex); }
}

Amb l’anterior ja tinc tot el codi. Poso la pàgina prova.html a la carpeta webcontent del projecte Eclipse. A més, en la carpeta webcontent també hi posaré la carpeta WEB-INF, amb una subcarpeta classes buida, la carpeta lib amb les llibreries que em calen i el web.xml.

En resum, a webcontent hi trobo:

webcontent/
    prova.html
    WEB-INF/
        classes/
        lib/
            jetty-util-8.1.2.v20120308.jar
            jetty-websocket-8.1.2.v20120308.jar
        web.xml

Les llibreries a la carpeta lib corresponen a la versió 8 del Jetty i es poden trobar a la seva carpeta lib. He vist que cal incloure-les al war. Em pensava que es referenciarien automàticament al fer deploy al Jetty, però no ha estat així.

El web.xml és força estàndar:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<display-name>tailor</display-name>
	<servlet>
		<servlet-name>WebSocket</servlet-name>
		<servlet-class>com.stsoftlliure.proves.html5.websockets.ProvaWebSocket</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>WebSocket</servlet-name>
		<url-pattern>/servlet/*</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>prova.html</welcome-file>
	</welcome-file-list>
</web-app>

Si de cas, remarcar el mapeig de /servlet/* a WebSocket. Aquesta és l’explicació de
var host = “ws://localhost:8080/websockets2/servlet/WebSocket”;
a la funció init.

Amb Jetty, a més, m’ha calgut establir el “context.” Al projecte, el fitxer de context l’he guardat a la carpeta homònima. És el següent fitxer.

websockets2.xml:

<?xml version="1.0"  encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/websockets2</Set>
  <Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/websockets2.war</Set>
</Configure>

Compte amb els salts de línia. El fitxer XML de context potser no queda “bonic” tal com està, però us podeu trobar amb problemes estranys si afegiu salts de línia.

Amb el fitxer anterior li estem dient quin és el war que ha de desplegar i quin nom tindrà el context. Amb aquest fitxer de context acabem de completar l’explicació del

var host = “ws://localhost:8080/websockets2/servlet/WebSocket”;

Ara és evident:

ws:// – Protocol websocket. Amb websockets segurs, serà wss://
localhost:8080 – Host i port del servidor websocket
websockets2 – El context, o l’aplicació web.
servlet/WebSocket – el Servlet servidor de WebSocket

Finalment, per automatitzar el muntatge i ddesplegament al servidor jetty local de l’apliació, faig servir el següent build.xml d’ant:

<project name="websocket" default="deploy" basedir=".">
  <description>
  proves amb websockets 2
  </description>

  <!-- estableix propietats globals -->
  <property name="src" location="src"/>
  <property name="bin" location="bin"/>
  <property name="war" location="war"/>
  <property name="webcontent" location="webcontent" />
  <property name="context" location="context" />
  <property name="build" location="build"/>
  <property name="lib" location="/home/albert/jetty/lib" />
  <property name="deploy" location="/home/albert/jetty/webapps" />
  <property name="deploy-context" location="/home/albert/jetty/contexts" />


  <target name="init">
    <!-- time stap -->
    <tstamp/>
    <!-- Crea el directory bin utilitzat en la compilació -->
    <mkdir dir="${bin}"/>
  </target>


  <target name="compile" depends="init" description="compila els fitxers font" >
    <!-- Compila les fonts java de ${src} en ${build} -->
    <javac srcdir="${src}" destdir="${bin}">
      <classpath>
       <pathelement location="${lib}/jetty-websocket-8.1.2.v20120308.jar"/>
       <pathelement location="${lib}/servlet-api-3.0.jar"/>
       <pathelement location="${lib}/jetty-util-8.1.2.v20120308.jar"/>
      </classpath>
   </javac>
  </target>

  <target name="build" depends="compile" description="genera el build">
    <!-- Crea el directori de distribució -->
    <delete dir="${build}" />
    <mkdir dir="${build}"/>

    <!--  copia webcontent a build -->
    <copy todir="${build}" >
        <fileset dir="${webcontent}" />
    </copy>
    
    <!--  copia bin a classes -->
    <copy todir="${build}/WEB-INF/classes">
        <fileset dir="${bin}" />
    </copy>
  </target>
     
  <target name="war" depends="build" description="genera el war">   
    <delete file="${war}/websockets2.war" />
    <jar jarfile="${war}/websockets2.war" basedir="${build}"> 
      <include name="**/*"/>
    </jar>
  </target>
  	
  <target name="deploy" depends="war" description="deploy del war i del context">
    <delete file="${deploy}/websockets2.war" />
    <delete file="${deploy-context}/websockets2.xml" />
  	<copy file="${war}/websockets2.war" todir="${deploy}" />
  	<copy file="${context}/websockets2.xml" todir="${deploy-context}" /> 
  </target>

</project>

Aleshores, ses d’Eclipse puc executar el build.xml que compila la classe, construeix el war i el copia a la carpeta webapps del meu Jetty local.

Per provar l’aplicació només en cal engegar el Jetty i obrir el navegador amb suport de websockets (en el meu cas, el Chrome) i apuntar-lo a l’adreça http://localhost:8080/websockets2

I el resultat és el següent.

I, efectivament, puc mantindre el diàleg amb el servidor:

Els vídeos de la deSymfony2012

Des de fa uns dies ja estan penjats els vídeos de les conferències de la deSymfony 2012 celebrada a Castelló a mitjans de juny passat.

Recordem que Symfony és un framework MVC (i algunacosa més) per a desenvolupar aplicacions amb php.

La deSymfony és la “La conferencia hispana más importante sobre Symfony y la segunda a nivel mundial.”

Molt remarcable la presència i la presentació de Fabien Potencier, el creador de Symfony i CEO de SensioLabs.

Font: http://desymfony.com/videos. Els enllaços porten a les respectives pàgines de les presentacions a deSymfony.com, on es pot trobar el ppt de la presentació i el vídeo corresponent al YouTube.

Vídeos de la 1ra jornada,  divendres 15 de juny

Vídeos de la 2na jornada,  dissabte 16 de juny