AMP: HTML to its full potential

Problemi con il caricamento delle pagine web, fastidiosi reflow, scarsa responsività?
Arriva AMP (Accelerated Mobile Pages): un framework HTML open source sviluppato in Google che fornisce una modalità semplice di creazione di pagine web che sono veloci, dal caricamento fluido e che danno priorità all’UX prima di tutto, primariamente per i dispositivi mobile.

Se avete notato, vedrete che quando effettuate una ricerca su Google con un dispositivo mobile come lo smartphone, quando cliccate sul link del risultato che volete visitare, può accadere che non compaia subito la pagina target ma venga invocato il sito ampproject.org in modo tale da rendere i risultato in modo veloce e fluido. Questo dipendentemente dal fatto che il sito sia stato attrezzato per utilizzare questo framework per ottimizzare le pagine con AMP.

AMP definisce una serie di tags estesi (che si chiamano componenti) che vengono gestiti da una libreria JavaScript obbligatoria che ogni pagina AMP deve caricare all’inizio della sezione <head> che hanno la proprietà di caricarsi velocemente nel browser e completamente prima di venire visualizzate, fornendo un’ottima esperienza utente (UX).

Per esempio, uno dei problemi che molti siti web mostrano (soprattutto se non ottimizzati per viewport del tipo smartphone) è il caricamento progressivo delle risorse della pagina web e il passaggio attraverso una fase in cui la pagina si ridisegna in continuazione: viene caricato un blocco di testo, poi un’immagine e viene ricalcolato il blocco di testo per aderire al layout… questo lavorio intermedio, piuttosto fastidioso, è detto HTML reflow e AMP fornisce degli strumenti che consentono di visualizzare la pagina solamente al termine delle determinazioni della geometria da parte del motore grafico del browser e del caricamento di tutte le risorse (font, testo, immagini).

Tecnicamente si tratta di ridefinire un set di pagine web dalla estensione .amp.html che utilizzano i componenti amp anziché i tag html standard (per esempio, l’utilizzo di <amp-img> anziché del tag <img>). Il rendering di questi tag è realizzato con la libreria Javascript che si trova nel CDN di ampproject.org.

Ma la potenza di AMP non si ferma ai siti web: può essere applicata in modo verticale a blog, stories, siti di ecommerce, ads e addirittura email!

Fonti: Search Engine Land, AMP Project, AMP dev

Qual è la differenza tra un programma e uno script?

script
script

Scrivendo gli ultimi articoli ho pensato di chiarire la differenza tra linguaggi di scripting e di programmazione. Il criterio di differenza più netto che ho trovato in rete è quello di suddividere in queste due categorie i linguaggi di programmazione allo stesso modo in cui si suddividono i linguaggi tra compilati ed interpretati.

Ma ho trovato parecchie inesattezze su quest’ultima classificazione, per una buona parte dei linguaggi attualmente disponibili.

La verità è che la differenza non è più così netta per tutta una serie di linguaggi molto popolari.

PHP non è un linguaggio interpretato come scritto da più parti, ma ha il suo bel bytecode generato a runtime da un compilatore che fa parte del core Zend. In pratica il compilatore Zend compila il sorgente in bytecode che viene poi interpretato dalla macchina virtuale Zend. Quindi non è veramente del tutto un linguaggio interpretato né del tutto compilato come si può dire del C.

Una risorsa che riporta un chiaro diagramma sul funzionamento di PHP è disponibile qui.

Anche Java viene trasformato in bytecode ed eseguito da una macchina virtuale (Oracle JVM, IcedTea etc).

La stessa cosa si può dire per Python in quanto anche qui ho una macchina virtuale che esegue bytecode (i file .pyc che vengono creati a runtime).

Quindi il codice che scriviamo non viene tradotto ed eseguito instantaneamente come succedeva per il BASIC, bensì viene compilato in bytecode e il bytecode viene interpretato.

C’è una importante differenza tra interpretazine dei bytecode e i programmi compilati puri come il C: il binding delle variabili, ossia il calcolo dell’indirizzo delle variabili, non è eseguito alla compilazione (anzi in realtà al momento dell’esecuzione del linker) ma all’esecuzione della virtual machine, quindi runtime. Nel C invece viene calcolata la posizione di memoria delle variabili in modo relativo nel codice hello.o e poi il linker le rende assolute nel contesto esecutivo del sistema operativo.

Javascript è un linguaggio di scripting poiché viene eseguito dal browser che diventa una sorta di “sistema operativo”. Ma anche questa nozione è superata. Il browser come Chrome in realtà opera una traduzione in bytecode, tramite il motore (engine, un altro modo di chiamare l’interprete) V8, degli script collegati alla pagina web. V8 è l’evoluzione dell’interprete JavaScript dei primi browser in un compilatore bytecode allo stesso modo di Java, PHP e Python. V8 è usato anche da node.js.

Un altro criterio distintivo potrebbe essere l’interazione con l’utente. Generalmente gli script consistono in una serie di comandi automatizzati che implementano la logica di un programma inteso come macchina di Von Neumann (inizializzazione di variabili, decisioni, cicli) e che vengono eseguiti in modalità batch, una modalità in cui il programma parte (spesso da solo, su innesco di uno scheduler come cron), fa una serie di operazioni e il risultato può essere verificato da un operatore a distanza di tempo e anche senza interazione alcuna con il software (ad esempio andando a vedere i log o i risultati in un database). In questa categoria si inseriscono gli script bash, potentissimi programmi (o script?) Unix/Linux.

Riferimenti web

Pillole Git: come applicare una patch

git
git

Ho due applicazioni residenti in due cartelle diverse che condividono uno stesso file (ad esempio il file contiene una stessa istruzione sql che viene emendata).

È chiaro che in partenza una situazione del genere non è nemmeno consigliabile. Però questa è la condizione del software del mio cliente e per non dover fare una profonda ristrutturazione devo metterci una… “patch”. Chiedo venia.

A parte gli scherzi, devo apportare la stessa modifica a due file uguali in due applicazioni diverse.

  • Estraggo la patch applicata al primo repository
$ git diff [ID COMMIT1] [ID COMMIT2] > diff.patch
  • Sposto il file ottenuto che contiene la patcj da applicare (diff.patch) nella cartella del secondo repository
$ mv diff.patch [altraCartella]
  • Applico la patch al secondo repository Git
$ git apply diff.patch

Se la patch è applicabile Git lo farà.

Se i file sono diversi non lo farà.

Infatti il contenuto della patch è

marcob@jsbach[15:29:18]:altraCartella$ cat diff.patch 
diff --git a/inviti/inv610.db.inc.php b/inviti/inv610.db.inc.php
index 9d9b678..797f68d 100644
--- a/inviti/inv610.db.inc.php
+++ b/inviti/inv610.db.inc.php
@@ -272,7 +272,7 @@ where
 	and d.id_tipo = f.id
-	and f.cod in (1, 2, 4, 5)
+	and f.cod in (1, 2, 3, 4, 5)

Git controlla prima che l’hash del secondo file (di arrivo) sia uguale al file da emendare: se sono diversi, vuol dire che non posso applicare la patch e Git terminerà.

Questa volta mi è andata di lusso.

Riferimenti

GSP: meccanismo di inclusione nei layout di Groovy

Layout di Groovy
Layout di Groovy

Lavorando coi layout di Groovy on Grails (le cosiddette pagine GSP: Groovy Server Pages) un web designer può efficientemente creare una struttura di inclusione che fattorizza in modo ottimale le parti di html. Cioè può raccogliere a fattore comune tutte le parti di layout che sono comuni a tutte le funzionalità legate al singolo controller e personalizzare le parti dedicate al singolo metodo.

Usiamo la prassi “usa una Convenzione piuttosto che Configurare” (convention over configuration). Questo frammento di progetto è l’esposizione casuale di una citazione (quote) tratta da una tabella, assieme al suo autore.

  • il layout si chiamerà come il controller: se abbiamo definito un controller QuoteController troveremo un template nei layouts con lo stesso nome quote (utilizzando il programma create-controller Grails creerà già da solo un controller e un layout per default):
grails-app/views/layouts/quote.gsp
  • All’interno della view dedicata alla citazione poi dovremo convenire di chiamare il blocco div che vogliamo personalizzare con il nome del layout:
grails-app/views/quote/random.gsp

in questo modo

<div id="quote">
    <q>${content}</q>

    <p>${author}</p>
</div>
  • A sua volta il nome della view è il nome del metodo del controller che viene invocato dalla url:
http://localhost:8080/qotd/quote/random

Memorizziamo che

  • controller -> layout e
  • metodo -> view e,
  • all’interno della view, div -> controller

Link utili su layout di Groovy

Groovy on Grails

Groovy on Grails

Il framework MVC Groovy on Grails si ispira anche onomatopeicamente a Ruby on Rails ed è la composizione di un linguaggio di programmazione per JVM (Groovy) su un framework MVC opzionalmente corredato da Spring (per il controllo della sicurezza) e Hibernate (lo strato ORM verso il database) che è Grails.

Groovy on Grails

Il linguaggio di programmazione è Groovy che però è molto simile a Java, avendo poi rispetto questo una serie di “ammorbidimenti” (vedi l’articolo Programmare in Groovy).

Groovy on Grails

Grails è un framework MVC che può essere associato a Spring per il controllo degli accessi e Hibernate come ORM. È un framework Open Source full-stack per applicazioni web basate su JVM. Adotta Apache Groovy come linguaggio di programmazione e il paradigma “meglio convenzione che configurazione” per consentire un’esperienza di programmazione estremamente produttiva e “aerodinamica”.

Ho scritto alcune guide come Creare un progetto Grails da linea di comando oppure con l’utilizzo della IDE Intellj IDEA di JetBrains. Uso la versione Ultimate che, tra le altre belle cose, ha che è possibile avere contemporaneamente anche un ambiente di sviluppo PHP attraverso l’attivazione di un plugin. In effetti JetBrains produce anche PHPStorm e quindi PHPStorm= IDEA + PHP Plugin.

Oltre a questo, anche una introduzione a Groovy come linguaggio di programmazione derivato da Java e una sezione di Q&A.

Groovy on Grails Q&A

Indice

  • Problems copying method. Incompatible JVM?
  • casServerUrlPrefix cannot be null
  • Aggancio al CAS non riuscito
  • ERROR pool.ConnectionPool

Vari errori che mi sono capitati

Problems copying method. Incompatible JVM?

Si manifesta quando si vuole eseguire l’applicazione da riga di comando con

$ grails run-app

Ho trovato che il problema è la versione di Spring, avevo la 1.2.0 e in StackOverflow consigliano la 1.2.4:

$ wget https://repo.spring.io/release/org/springframework/springloaded/1.2.4.RELEASE/springloaded-1.2.4.RELEASE.jar -O springloaded-1.2.1.RELEASE.jar

casServerUrlPrefix cannot be null

Devo proteggere la mia applicazione con accesso di login e mi aggancio per questo ad un server CAS. La configurazione che ho fatto (minimale) è di inserire nel file BuildConfig.groovy, nella sezione plugins la riga

compile ":spring-security-cas:2.0.1"

Eseguendo il build:

$ grails s2-quickstart test1 Utente Ruolo Requestmap

SI verifica un errore (e Tomcat non parte)

Exception starting filter CAS Single Sign Out Filter Message: casServerUrlPrefix cannot be null.

Ora la configurazione dei parametri CAS era stata effetuata regolarmente nel file Config.groovy (tutti questi file si trovano nella cartella grails-app/conf del progetto Grails):

environments {
...
    custom {
        grails.plugin.springsecurity.cas.serverUrlPrefix="https://cas.remotesite.com/cas"
        grails.plugin.springsecurity.cas.active = true
        grails.plugin.springsecurity.cas.loginUri = "/login"
        grails.plugin.springsecurity.cas.serverUrlPrefix = "https://cas.remotesite.come/cas"
        grails.plugin.springsecurity.logout.afterLogoutUrl = "https://splashdown.remotesite.com/logout.php"
    }
...
}

E parimenti è stata fatta la configurazione del core di Spring che ometto.

Per farla breve l’errore era una ulteriore configurazione da aggiungere nel file BuildConfig.groovy: nella sezione dependencies

        compile "org.jasig.cas.client:cas-client-core:3.3.3", {
            excludes 'commons-codec', 'commons-logging', 'junit', 'log4j', 'opensaml', 'servlet-api', 'spring-beans',
                    'spring-context', 'spring-core', 'spring-test', 'xmlsec' }

Riferimenti: https://github.com/grails-plugins/grails-spring-security-cas/issues/9

Aggancio al CAS non riuscito

In questa situazione CAS viene invocato richiama l’host di ritorno passando il token di sessione, ma il client lato applicazione lo ignora e fa riferimento ad un suo db locale, un database H2.

L’url del db è scritto in DataSource.groovy ed è jdbc:h2:prodDb

ERROR pool.ConnectionPool

Mancano i driver che vanno aggiunti al file conf/BuildConfig.groovy:

    dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes e.g.
        runtime 'mysql:mysql-connector-java:5.1.27'
        // runtime 'org.postgresql:postgresql:9.3-1100-jdbc41'
        test "org.grails:grails-datastore-test-support:1.0-grails-2.3"
    }

La riga relativa a mysql di default è commentata: decommentarla. Eventualmente aggiungere il parametro di Oracle se invece si usa Oracle: si devono aggiungere i jar di odbc e ora sotto lib

marcob@jsbach[11:35:58]:betablog$ ll lib/
 totale 3140
 drwxrwxr-x  2 marcob marcob    4096 ago 26 18:07 ./
 drwxrwxr-x 15 marcob marcob    4096 ago 26 18:05 ../
 -rw-rw-r--  1 marcob marcob 1555682 ago  5 16:47 ojdbc14.jar
 -rw-rw-r--  1 marcob marcob 1646178 ago  5 16:47 orai18n.jar

Programmare in Groovy

Groovy logo
Groovy logo

Groovy è un linguaggio debolmente tipizzato (consente la definizione implicita delle variabili e l’aritmetica implicita – in cui il tipo del risultato è dato da una serie di regole quando i tipi degli addendi non sono congruenti, come illustrato tra poco) derivato da Java con in più le performance e la flessibilità di un linguaggio di scripting come Python ad esempio. È un derivato del Java con una nuova sintassi tale da renderlo molto familiare ai programmatori Java. Vi posso assicurare che dopo un po’ che lo si usa si ha la sensazione che non sia poi così tanto diverso da PHP.

Le caratteristiche di Groovy risolvono una serie di problematiche di produttività ed eleganza con un buon compromesso sulla tipizzazione.

Essenzialmente è un linguaggio “Java light” che rispetto a Java ha alcuni rilassamenti:

  • Si possono definire i tipi delle variabili “in corsa” senza specificarne il tipo che viene dedotto al momento della compilazione (come avviene anche per PHP 7)
    def pi = 3.14
    e pi sarà un Float
  • La tipizzazione non è rigida come con Java, praticamente scompare la differenza tra classe e tipo primitivo:
    int a=1
    equivale a
    Integer a = 1
  • non sono necessari i ; alla fine dell’istruzione
  • overload degli operatori per gli oggetti. Ad esempio si potrà scrivere indifferentemente l’operatore == tra due int o due Integer, o addirittura tra un int e un Integer:
int a=2            // in Java sarebbe un tipo primitivo
print(a)

Integer b=2        // in Java sarebbe una classe
print(a.equals(b)) // stampa true
print(a==b)        // stampa true

Per testare costrutti Groovy si può utilizzare la consolle che si può far partire da IDE selezionando Tools > Groovy console:

Uso della console per scivere programmi Groovy...
Uso della console per scivere programmi Groovy…

e cliccando sulla freccetta bianca in alto a sinistra si compila ed esegue il programma:

... ed esecuzione su console di programmi Groovy.
… ed esecuzione su console di programmi Groovy.

Tips on Groovy programming

Ci sono alcune pratiche utili che consentono di sviluppare in modo coerente.

Io sono partito da questa esigenza: voglio che ogni modello (o dominio come viene chiamato in Grails) debba possedere uno standard, ad esempio voglio che tutti i modelli siano corredati dai campi ch riportano lo username del creatore dell’oggetto, e i timestamp di creazione e modifica.d

Grails ha il notevole supporto ai template per ogni oggetto del paradigma MVC: dai model, ai controller alle alle view.

Per installare nella propria applicazione i template si ricorre al comando

$ grails install-templates
| Templates installed successfully
$

Questo comando semplicemente copia i template dell’installazione di Grails dentro alla cartella src/templates e si suddivide in quattro cartelle:

  • artifacts che contiene i file Controller.groovy, DomainClass.groovy, Filters.groovy, …
  • scaffolding che contiene le pagine gsp di layout delle views standard
  • testing in cui vengono messi i test di unità
  • war che contiene il package ada esportare per migrazioni ad altre istanze di Tomcat

Questo articolo è solo un abbozzo e deve essere completato.

Risorse utili

Creare un progetto Grails

Da linea di comando (oppure posizionando il puntatore sopra la cartella della IDE “grails-app/domain” e scegliendo New > Grails Domain Class)

$ grails create-domain-class Contact

Grails crea la classe agenda/Contact con un po’ di default, noi la personalizziamo così

package agenda

class Contact {

    static constraints = {
    }

    String nome
    String cognome
    String azienda
    String email
    Date dataNascita

}

Poi creiamo un controller definendo come default lo scaffold (Grails crea views, metodi e orm per eseguire il CRUD di base).

Anche qui possiamo agire da linea di comando oppure, posizionandoci con il mouse sopra grails-app/controllers e scegliendo New > Grails Controller

$ grails create-controller

Anche qui personalizziamo l’artefatto:

package agenda

class ContactController {

    def scaffold = Contact

    def index() { }
}

L’unica personalizzazione è la riga 5 in cui diamo la direttiva del controller di creare metodi e viste per lo scaffold della classe Contact.

Ora si tratta di far girare l’applicazione o cliccando sul pulsantino verde in alto a destra oppure dando il comando

$ grails run-app

e puntare il browser a http://localhost:8080/agenda/

Il bello è che l’applicazione ha già una certa funzionalità di crud, infatti posso già invocare il controller cliccando su agenda.ContactController

Il Controller, a fine salvataggio mi da conferma del salvataggio:

Peccato che però la lista sia vuota

Occorre infatti configurare un supporto dati permanente, come un database. Out-of-the-box Groovy utilizza Hibernate con questa configurazione:

dataSource {
    pooled = true
    jmxExport = true
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
}

// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
            url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
        }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
        }
    }
...
}

Ho preso spunto da Mokabyte

Tre modi di creare un’applicazione Groovy on Grails.

Creare nuovi progetti con il framework MVC per il mondo Java Groovy on Grails è un’operazione che può essere svolta in diversi modi:

Creazione da IDE

Ho sperimentato per prima la prima modalità IDE, creando l’applicazione Test1:C

Proficiency in Groovy on Grails
Creare un nuovo progetto con Intelij IDEA

Il wizard richiede di impostare la versione di Grails da utilizzare, la Java Virtual Machine che eseguirà la compilazione e il tipo dell’applicazione (se app o se plugin)

Per questa applicazione uso Java 1.8 come JVM e Grails 2.3.11 per allinearmi con le versioni utilizzate dal Cliente. Alla fine mi viene chiesto il nome dell’applicazione:

Parte il build dell’applicazione utilizzando la versione di Grails 2.3.1 selezionata:

/usr/lib/jvm/jdk1.8.0_111/bin/java -Dgrails.home=/home/marcob/.sdkman/candidates/grails/2.3.11 -Dtools.jar=/usr/lib/jvm/jdk1.8.0_111/lib/tools.jar -Dgroovy.starter.conf=/home/marcob/.sdkman/candidates/grails/2.3.11/conf/groovy-starter.conf -Dbase.dir=/home/marcob/IdeaProjects/Test1 -Dfile.encoding=UTF-8 -classpath /home/marcob/.sdkman/candidates/grails/2.3.11/lib/org.codehaus.groovy/groovy-all/jars/groovy-all-2.1.9.jar:/home/marcob/.sdkman/candidates/grails/2.3.11/dist/grails-bootstrap-2.3.11.jar org.codehaus.groovy.grails.cli.support.GrailsStarter --main org.codehaus.groovy.grails.cli.GrailsScriptRunner --conf /home/marcob/.sdkman/candidates/grails/2.3.11/conf/groovy-starter.conf "idea-print-project-settings -plain-output"

 |Loading Grails 2.3.11
 |Configuring classpath
 .
 |Environment set to development
 ....
 |Installing zip scaffolding-2.0.3.zip…
 ...
 |Installed plugin scaffolding-2.0.3
 ..........

---=== IDEA Grails build settings ===---
 #
 Tue Aug 13 12:12:01 CEST 2019
 grails.work.dir=/home/marcob/.grails/2.3.11
 grails.project.work.dir=target/work
....

Compile.0=/home/marcob/.sdkman/candidates/grails/2.3.11/lib/org.codehaus.groovy/groovy-all/jars/groovy-all-2.1.9.jar
 Compile.1=/home/marcob/.sdkman/candidates/grails/2.3.11/dist/grails-plugin-rest-2.3.11.jar
....

Runtime.0=/home/marcob/.sdkman/candidates/grails/2.3.11/lib/org.codehaus.groovy/groovy-all/jars/groovy-all-2.1.9.jar
 Runtime.1=/home/marcob/.sdkman/candidates/grails/2.3.11/dist/grails-plugin-rest-2.3.11.jar
....

Test.0=/home/marcob/.sdkman/candidates/grails/2.3.11/lib/javax.servlet/javax.servlet-api/jars/javax.servlet-api-3.0.1.jar
 Test.1=/home/marcob/.sdkman/candidates/grails/2.3.11/lib/org.codehaus.groovy/groovy-all/jars/groovy-all-2.1.9.jar
....

Provided.0=/home/marcob/.sdkman/candidates/grails/2.3.11/lib/javax.servlet/javax.servlet-api/jars/javax.servlet-api-3.0.1.jar
 Build.0=/home/marcob/.sdkman/candidates/grails/2.3.11/lib/xalan/serializer/jars/serializer-2.7.1.jar
 Build.1=/home/marcob/.sdkman/candidates/grails/2.3.11/dist/grails-bootstrap-2.3.11.jar
....

---=== End IDEA Grails build settings ===---

Ometto per comodità la maggior parte del log che non presenta messaggi d’errore.

Alla fine l’applicazione è creata e viene popolato l’albero dei file all’interno della directory

~/IdeaProjects/Test1

Creazione dal sito di Grails

Si accede a https://start.grails.org

Si seleziona innanzitutto il tipo di progetto: Applicazione o plugin: la stessa possibilità c’è nella IDE ma per iniziare partiamo dalle Applicazioni.

Si sceglie il nome dell’applicazione e la versione di Grails: purtropppo le versioni selezionabili non sono vecchie come quelle che usa il mio Cliente quindi scelgo la 3.2.13 (che ho anche a bordo della mia macchina):

marcob@jsbach[12:32:28]:IdeaProjects$ sdk list grails
 Available Grails Versions
 4.0.0               3.1.15              3.0.2               2.2.2          
  4.0.0.RC2           3.1.14              3.0.1               2.2.1          
  4.0.0.RC1           3.1.13              3.0.0               2.2.0          
  4.0.0.M2            3.1.12              2.5.6             * 2.1.5          
  4.0.0.M1            3.1.11              2.5.5               2.1.4          
  3.3.10              3.1.10              2.5.4               2.1.3          
  3.3.9               3.1.9               2.5.3               2.1.2          
  3.3.8               3.1.8               2.5.2               2.1.1          
  3.3.7               3.1.7               2.5.1               2.1.0          
  3.3.6               3.1.6               2.5.0               2.0.4          
  3.3.5               3.1.5               2.4.5               2.0.3          
  3.3.4               3.1.4               2.4.4               2.0.2          
  3.3.3               3.1.3               2.4.3               2.0.1          
  3.3.2               3.1.2               2.4.2               2.0.0          
  3.3.1               3.1.1               2.4.1               1.3.9          
  3.3.0               3.1.0               2.4.0               1.3.8           
>*3.2.13              3.0.17            * 2.3.11              1.3.7          
  3.2.12              3.0.16              2.3.10              1.3.6          
  3.2.11              3.0.15              2.3.9               1.3.5          
  3.2.10              3.0.14              2.3.8               1.3.4          
  3.2.9               3.0.13              2.3.7               1.3.3          
  3.2.8               3.0.12              2.3.6               1.3.2          
  3.2.7               3.0.11              2.3.5               1.3.1          
  3.2.6               3.0.10              2.3.4               1.3.0          
  3.2.5               3.0.9               2.3.3               1.2.5          
  3.2.4               3.0.8               2.3.2               1.2.4          
  3.2.3               3.0.7               2.3.1               1.2.3          
  3.2.2               3.0.6               2.3.0               1.2.2          
  3.2.1               3.0.5               2.2.5               1.2.1          
  3.2.0               3.0.4               2.2.4               1.2.0          
  3.1.16              3.0.3             * 2.2.3                                  =======================================================================
 - local version
 - installed 
   - currently in use 

Come si vede, ho installato le versioni 2.1.5, 2.2.3, 2.3.11, 3.2.13 e quest’ultima è quella preselezionata nella sessione di shell in cui ho lanciato il comando

Tra le features, lascio le scelte standard: Hibernate5 in particolare è lo strato software che permette di astrarre dal livello database (ORM, Object Relationship Mapping).

Premendo il pulsante Generate viene scaricato il package myapp.zip:

Lo scarico e unzippo dentro a ~/IdeaProjects/Test1. Dopo di che lo apro con la IDE e questa si deve riscaricare tutti i package dipendenti, ad esempio Gradle (che è il tool per fare il build della applicazione che manca nel file zip)

Download https://services.gradle.org/distributions/gradle-3.4.1-bin.zip (70,31 MB)
 Download https://services.gradle.org/distributions/gradle-3.4.1-bin.zip finished succeeded, took 57 s 539 ms
 Gradle Daemon started in 840 ms
 Download https://repo.grails.org/grails/core/org/grails/grails-gradle-plugin/3.2.13/grails-gradle-plugin-3.2.13.pom
...

Creazione da linea di comando

L’ultimo modo per creare l’applicazione è da linea di comando. Essa assomiglia molto alla modalità php artisan per creare le applicazioni in PHP/Laravel. Innanzitutto si scarica SDKMan:

Installazione di SDKMan

$ curl -s "https://get.sdkman.io" | bash

Installazione di Grails

$ sdk install grails 4.0.1

Verifico:

$ grails --version

| Grails Version: 4.0.1
| JVM Version: 1.8.0_77

Creare l’applicazione

$ grails create-app it.betaingegneria.apps.myApp

Dopo di che si può sviluppare con l’IDE che si vuole.

Build and Go!

Una volta terminata la fase di startup dell’applicazione è il momento di programmare e costruire l’applicazione vera e propria. Ma a questo punto siamo già davanti ad una applicazione di base funzionante. Usiamo gradle (come artisan) e facciamo il build aprendo un terminale da dentro la directory del progetto

marcob@jsbach[16:12:15]:myapp$ ./gradlew bootRun
 Starting a Gradle Daemon (subsequent builds will be faster)
 :compileJava NO-SOURCE
 :compileGroovy
 :buildProperties
 :processResources
 :classes
 :findMainClass
 :bootRun
 Grails application running at http://localhost:8080 in environment: development
   Building 85% > :bootRun 

Quando lo script ha raggiunto la fase “running”, puntare il browser all’indirizzo http://localhost:8080

Proficency in Groovy on Grails: come si presenta l'applicazione Groovy on Grails una volta avviata
Come si presenta l’applicazione Groovy on Grails una volta avviata

Attenzione! c’è un comando in più da dare: prima di avviare il build, rendere eseguibile lo script gradlew:

marcob@jsbach[16:11:48]:myapp$ chmod a+x gradlew

Importazione in Intellij IDEA

Gradle Daemon started in 1 s 722 ms
 CONFIGURE SUCCESSFUL
 Total time: 10.864 secs
 Manifest.writeTo(Writer) has been deprecated and is scheduled to be removed in Gradle 4.0. Please use Manifest.writeTo(Object) instead.

Guida di stile

Indice

Pillole Linux: il comando wget

wget: comando per scaricare pagine web
wget: comando per scaricare pagine web

wget è un programma Linux che effettua il download di una risorsa web agendo allo stesso modo dei crawlers dei motori di ricerca e la deposita in un file in locale nel computer in cui si è lanciato il comando.

Digitando

$ wget https://www.mysite.org

scarico in locale la pagina indice:

marcob@jsbach:mysite$ ll
 totale 20
 drwxr-xr-x 2 marcob marcob  4096 ago  7 15:01 ./
 drwxr-xr-x 4 marcob marcob  4096 ago  7 15:00 ../
 -rw-r--r-- 1 marcob marcob 11395 ago  7 15:01 index.html

Se c’è una gerarchia di directory posso scaricare anche quella, cioè scaricare tutti i file le directory e le sottodirectory, con l’opzione -r (recursive) e specificando il numero di livelli di gerarchia a cui voglio scendere al massimo; per esempio se voglio fermarmi al terzo:

$ wget -r -l3 https://www.mysite.org

Spesso però i siti vengono impostati in modo da bloccare questo tipo di download massivo, ma wget è molto potente: possiamo inviare nella richiesta anche degli header HTTP personalizzati con l’opzione ‐‐header, ad esempio fingendoci un browser vero:

$ wget -r -l3 --no-parent --header="Accept: text/html" --user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0" https://www.mysite.org

Tuttavia il web server può sempre bloccare lo user agent quando il numero di pagine richieste al secondo è troppo elevata. Con queste opzioni ci presentiamo al server come se fossimo un browser Firefox per sistema operativo Mac OS X. Inoltre specificando ‐‐no-parent evitiamo di fare il download anche delle eventuali cartelle soprastanti quella di cui vogliamo fare il download.

Come ultimo esempio, potendo inviare header HTTP a piacere, possiamo inviare l’header di autenticazione per siti protetti con autenticazione. Ovviamente dobbiamo avere un account in quel sito e possiamo evitare di mandare in chiaro la password in http utilizzando l’opzione ‐‐ask-password:

$ wget -r -l10 --no-parent --user=myuser --ask-password --header="Accept: text/html" --user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0" http://www.mysite.org

Risorse web