giovedì 20 settembre 2012

NodeJs REPL

Quando approcciamo ad una nuova tecnologia una delle cose fondamentali è la possibilità che abbiamo per poterne testare le potenzialità e sentirsi subito "attivi".
NodeJS, oltre ad essere una potentissima piattaforma Server Side per la costruzione di sevizi, fornisce uno ambiente di runtime come Perl, Pyton e Ruby, per poter eseguire e testare le nostre applicazioni.
REPL (Read-Eval-Print-Loop), così viene chiamato l'ambiente interattivo di cui sopra, permette quindi il testing delle nostre applicazioni, ma non solo, perché essendo NodeJS un wrapper dell'engine V8, permette di testare anche programmi scritti in Javascript.
Per poter testare le nostre applicazioni, oltre a scrivere dei semplici comandi possiamo testare delle funzioni javascript che andranno a popolare le pagine web delle nostre applicazioni, oppure, semplicemente testare i nostri programmi scritti con nodeJS semplicemente richiamando il nome del file creato dopo l'istruzione node. Per esempio se inseriamo il codice scritto di seguito in un file chiamato inizializzaMySQL.js:


var mysql = require('mysql');                                                     

var TEST_DATABASE = 'techqueue_mysql_test';
var TEST_TABLE = 'nodejs_test';
var client = mysql.createClient({
  user: 'root',
  password: 'root',
});

client.query('CREATE DATABASE '+TEST_DATABASE, function(err) {
  if (err && err.number != mysql.ERROR_DB_CREATE_EXISTS) {
    throw err;
  }
});


client.query('USE '+TEST_DATABASE);

client.query(
  'CREATE TABLE '+TEST_TABLE+
  '(id INT(11) AUTO_INCREMENT, '+
  'title VARCHAR(255), '+
  'text TEXT, '+
  'created DATETIME, '+
  'PRIMARY KEY (id))'
);

client.query(
  'INSERT INTO '+TEST_TABLE+' '+
  'SET title = ?, text = ?, created = ?',
  ['prova titolo 1', 'Testo di prova di nodejs', '20/09/2012 15:00:00']
);

var query = client.query(
  'INSERT INTO '+TEST_TABLE+' '+
  'SET title = ?, text = ?, created = ?',
  ['secondo titolo', 'Testo nel secondo record', ' 20/09/2012 16:00:00 ']
);

client.query(
  'SELECT * FROM '+TEST_TABLE,
  function selectCb(err, results, fields) {
    if (err) {
      throw err;
    }

    console.log(results);
    console.log(fields);
    client.end();
  }
);


Possiamo eseguirlo e testarlo (ovviamente avendo preventivamente installato mysql server e configurato opportunamente lo script), scrivendo semplicemente:

> node inizializzaMySQL.js

Da sottolineare il fatto che nella prima istruzione gestiamo l'importazione del modulo 'mysql' per poter utilizzare le sue funzioni. 
In nodejs per poter utilizzare le librerie che non sono comprese nel core, bisogna importarle nel sistema utilizzando un "gestore di pacchetti", denominato npm. Quindi, se vogliamo installare il modulo per gestire il dbms mysql, dovremmo scrivere:

> npm install mysql

Quindi non ci resta che installare e provare le nostre funzioni.
Buon lavoro

martedì 29 maggio 2012

Step into NodeJS

NodeJS è un modo di eseguire JavaScript al di fuori del browser web. Esso è un wrapper ad alte prestazioni per il runtime JavaScript di Google Chrome V8 (Javascript engine scritta in C++ che permette l'esecuzione di codice JS in modalità stadalone o embedded in un'applicazione C++). 
NodeJS permette la gestione dell'engine V8 per permettergli di lavorare meglio in contesti diversi dal browser, per lo più da fornendo API aggiuntive che sono ottimizzate per specifici casi d'uso.


V8 utilizza alcune delle tecniche più innovative nella tecnologia del compilatore. Ciò consente spesso di poter scrivere codice in un linguaggio di alto livello come ad esempio JavaScript ed avere comportamenti paragonabili a codice scritto in un linguaggio di basso livello come C, con una frazione del costo di sviluppo. Questa focalizzazione sulle prestazioni è un aspetto fondamentale di NodeJS.



Javascript (dai veri cultori del codice, spesso bistrattato), è un linguaggio event-driven e NodeJS utilizza questo a suo vantaggio per la produzione di server altamente scalabili. Utilizzando un'architettura chiamata events-loop, rende la programmazione server altamente scalabile facile e sicura. 

Una caratteristica molto importante di NodeJS è la riduzione drastica della complessità per lo sviluppatore pur essendo molto potente e performante. Riusciamo, infatti, a raggiungere prestazioni impressionanti senza molta fatica.
Per supportare l'approccio events-loop (nella programmazione ad eventi  il flusso del programma è determinato soprattutto dal verificarsi di eventi esterni), NodeJS fornisce una serie di librerie "non bloccanti". 
In sostanza, si tratta di interfacce di tipo event-driven per risorse come il file system o un database. Quando si effettua una richiesta al filesystem, NodeJS anziché aspettare il disco rigido che recuperi il file, l'interfaccia non-blocking, semplicemente notifica quando ha accesso alla risorsa, nello stesso modo in cui si comporta un browser web, per esempio, all'evento onclick.
L'installazione è estremamente semplice, Node gira su Windows, Linux, Mac e altri sistemi operativi POSIX (come Solaris e BSD). NodeJS si può scaricare dal sito del progetto o il repository GitHub.

Colleghiamoci al sito scelto e scarichiamo l'ultima release. Prendiamo come esempio il download della versione tar.gz 


> tar xzf node-v0.6.6.tar.gz

 La x sta per estrai (piuttosto che comprimere), z dice a tar di decomprimere utilizzando l'algoritmo 
  di GZIP, e f indica che stiamo scompattato il file indicato come argomento finale.


Il passo successivo consiste nel configurare il codice per il sistema. 
NodeJS utilizza il sistema configure/make. Lo script di configurazione, ispezionando il sistema, trova i percorsi necessari per gestire le dipendenze di cui ha bisogno.


> ./configure


Il successivo passo di installazione è quello di fare il make del progetto. Questo compila nodo e costruisce la versione binaria che verrà utilizzato in una costruzione sottodirectory della directory dei sorgenti che abbiamo usato


> make


Il passo finale è quello di installare NodeJS. Se vogliamo installarlo come superuser, l'istruzione da eseguire è la seguente:


> sudo make install


Nei prossimi post approfondiremo vari aspetti e usi di questo splendido e innovativo modo di scrivere software di qualità con un occhio alle performance...

mercoledì 9 febbraio 2011

Android Base: Un esempio di Intent Esplicito.

In un’Intent Esplicito specifichiamo l’Activity target invocandola direttamente. Tale gestione è utile nel caso si vogliano gestire messaggi all’interno delle proprie applicazioni.
A differenza delle Intent Implicite in cui dichiariamo il tipo di Intent che vogliamo sia gestita e deleghiamo alla piattafroma Android il compito di trovare l’Activity in grado di operare sui dati di cui abbiamo bisogno, ora definiamo a tempo di compilazione chi sarà ad “occuparsi dei nostri dati”.


Chiarirò tutto con un semplice esempio.
Supponiamo di avere due Activity:
·         InvokeActivity
·         InvokedActivity

Che, ovviamente, rappresentano l’Activity chiamante e quella chiamata.
Partiamo dalla definizione della nostra applicazione col seguente AndroidManifest.xml :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="it.delfio.android.activity.intents" android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".InvokeActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".InvokedActivity" android:label="@string/app_name">
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="3" />
</manifest>



L’InvokeActivity contiene un bottone “Invoca Activity” (da inserire nel file xml di layout: main.xml) che, una volta cliccato, permette di invocare l’Activity target.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent" android:layout_height="wrap_content">
       <TextView 
           android:layout_width="fill_parent" android:layout_height="wrap_content"
           android:text="@string/testoInvokeActivity" android:layout_weight="1"/>
        <Button android:text="@string/invokeButtonText"
              android:id="@+id/invokeButton" android:layout_gravity="center_horizontal"
              android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</LinearLayout>


Di seguito il codice dell’InvokeActivity con in evidenza la gestione dell’evento onClick lanciato alla pressione del bottone con id invokeButton                     

package it.delfio.android.activity.intents;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class InvokeActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
   Button invokeButton = (Button)findViewById(R.id.invokebutton);
   invokeButton.setOnClickListener(new OnClickListener() { 
     public void onClick(View v) {
        Intent explicitIntent = new Intent(InvokeActivity.this,InvokedActivity.class);
        startActivity(explicitIntent);
     }
   });
  }
}


Recuperiamo il pulsante che permetterà di lanciare il nostro Intent attraverso l’istruzione:

                     (Button)findViewById(R.id.invokebutton)

Di seguito, attraverso il costruttore :

                  Intent(InvokeActivity.this,InvokedActivity.class)

Possiamo specificare l’Activity sorgente e quella destinazione della chiamata, che verrà fatta sempre attraverso la chiamata:

                 startActivity(explicitIntent);

Definiamo nel file /res/values/string.xml tutte le stringhe che utilizzaremo nell’applicazione:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="testoInvokeActivity">Activity che lancia una Intent Esplicita</string>
    <string name="app_name">Prova Intent Esplicita</string>
<string name="invokeButtonText">Invoca Activity   </string>
<string name="testoInvokedActivity">Activity chiamata esplicitamente. Non abbiamo configurato nessun Intent Filter, quindi per invocare la seconda Activity bisogna chiamarla esplicitamente.</string>
</resources>


Alla pressione del bottone, come accennato in precedenza viene lanciata l’Intent a cui risponderà la nostra seconda InvokedActivity, il cui layout è definito dal file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent" android:layout_height="wrap_content">
    <TextView android:text="@string/testoInvokedActivity"
      android:layout_width="fill_parent" android:layout_height="wrap_content" >
    </TextView>
</LinearLayout>


Che contiene un unico campo testo da visualizzare appena viene invocata e visualizzata attraverso il semplice codice:

package it.delfio.android.activity.intents;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class InvokedActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.invokedactivity);
  }
}


Infine, provando a lanciare la nostra semplice applicazione sull’emulatore, dovremmo ottenere:



giovedì 3 febbraio 2011

Android Base: Intent e Intent Filter. Un esempio di Intent Implicito.

Nel precedente Post ho parlato di Intent e di Intent Filter, senza specificare di cosa si trattasse.
Gli Intent sono dei messaggi asincroni che permettono alle varie Activity di inviare o ricevere dati da e verso altre Activity o Servizi.
Per esempio un'applicazione può fare richiesta, attraverso un'intent, di informazioni relative ad un contatto, mentre un Intent Filter mi permette di registrarmi su un determinato tipo di dato (praticamente dico che posso gestire un certo tipo di dati).
Ci sono due tipi di Intent:

  • Impliciti
  • Espliciti
Gli Intent Espliciti chiamano direttamente il componente di cui hanno bisogno (per esempio una classe Java), mentre gli Intent impliciti chiedono al sistema do eseguire un servizio (per esempio aprire un Browser).
Quando selezioniamo un dato in un'applicazione e richiediamo un certo servizio Android determinerà le applicazioni adatte a gestirlo e proporrà  all'utente una scelta. La determinazione di quali applicazioni presentare nella scelta é basata sugli Intent Filter, rappresentati dalla classe "android.content.IntentFilter". Gli Intent Filter sono in genere definiti tramite l'AndroidManifest.xml. Un componente utilizza gli Intent Filter per definire quali Intent sia in grado di gestire, se non viene configurato nessun Intent Filter, significa che possiamo chiamare il componente solo in modo esplicito.
Per chiarire meglio la differenza tra i due tipi di Intent, facciamo degli esempi.

Intent Implicito

Supponiamo che voglia aprire un URL e vogliamo fare in modo che il sistema inserisca tra le scelte possibili per gestirlo, la nostra Activity.
Creaiamo, a tale scopo, il package it.delfio.android.activity.intents con l’Activity ImplicitManager. Partendo dalla definizione di un view Layout:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"    android:layout_height="fill_parent">

<Button android:id="@+id/Bottone1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Call browser"  android:onClick="IntentManager">
</Button>
</LinearLayout>


Per poter utilizzare alcuni tipi di Intent bisogna configurarli sul file manifest della nostra applicazione. Dobbiamo, quindi, avere:



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="it.delfio.android.intents"
      android:versionCode="1" android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".IntentsManager"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="9" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>


La nostra Activity che gestirà la chiamata alla Intent sarà:


package it.delfio.android.activity.intents;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class ImplicitManager extends Activity {
       /** Called when the activity is first created. */
       @Override
       public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.main);
       }

       public void callIntent(View view) {
         Intent intent = null;
         if (R.id.Bottone1==view.getId()) {
          intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.google.it"));
          startActivity(intent);
          startActivityForResult(intent, -1);          
         }
       }
      
       @Override
       public void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (resultCode == Activity.RESULT_OK && requestCode == 0) {
           String result = data.toURI();
           Toast.makeText(this, result, Toast.LENGTH_LONG);
         }
       }
}



Ho inserito nella mia Activity un metodo che permette di gestire gli eventuali dati di ritorno provenienti dalla Activity che ha gestito l’Intent (per esempio nel caso della scelta di un nominativo dalla rubrica). In questo caso avrei dovuto lanciare l’Intent tramite il comando:

            startActivityForResult(intent, 0);

Il secondo parametro rappresenta il request code. Far partire una Activity con un valore negativo di questo parametro equivale a lanciare il metodo startActivity(intent).  Da notare che per Intent come Intent.ACTION_VIEW, Intent.ACTION_MAIN e altre (che non prevedono un valore di ritorno), non ha senso chiamare l’activity con tale metodo che, tra l’altro, potrebbe ritornare un valore non atteso. Per esempio, nel caso di lancio di una Activity che prevede l’avvio sullo stesso thread del chiamante, otterremo come risposta un risultato di  CANCEL.

Nel prossimo articolo parlerò delle Intent Esplicite che meritano un Post a parte.