Category: java

  • FizzBuzz: una sfida per programmatori

    Un quesito che viene spesso richiesto ai programmatori è quello di scrivere un programma FizzBuzz:

    Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

    La difficoltà principale, se così vogliamo chiamarla, è quella di leggere attentamente i requisiti e trasformarli in if condizionali del linguaggio scelto. Nel mio caso, Java:

    import junit.framework.Assert;
    
    public class FizzBuzz {
        public static void main(String args[]) {
            for (int i = 1; i <= 100; i++) {
                if (i % 3 == 0 && i % 5 == 0) {
                    System.out.println("fizzbuzz");
                    Assert.assertTrue(divisibleBy3(i) && divisibleBy5(i));
                } else if (i % 3 == 0) {
                    System.out.println("fizz");
                    Assert.assertTrue(divisibleBy3(i) && !divisibleBy5(i));
                } else if (i % 5 == 0) {
                    System.out.println("buzz");
                    Assert.assertTrue(!divisibleBy3(i) && divisibleBy5(i));
                } else {
                    System.out.println(i);
                    Assert.assertTrue(!divisibleBy3(i) && !divisibleBy5(i));
                }
    
            }
        }
    

    L’algoritmo si può complicare a piacere. In una curiosa implementazione, viene richiesto di non usare operazioni come la moltiplicazione e la divisione. L’autore del post risolve il problema utilizzando una coda circolare, sfruttando il fatto che i numeri seguono un comportamento periodico.
    Nel risolvere lo stesso problema, ho deciso di utilizzare un approccio diverso. Infatti, mi sono ricordato che esistono dei criteri per stabilire a priori se un numero è divisibile per determinati numeri (in particolare per 3 e per 5). E così ho scritto due metodi per testare se un numero passato come parametro è divisibile per 3 o per 5:

        public static boolean divisibleBy3(int num) {
            String s = new Integer(num).toString();
            while (s.length() != 1) {
                int j = 0;
                for (int i = 0; i < s.length(); i++) {
                    j += Integer.parseInt(s.substring(i, i + 1));
                }
                s = new Integer(j).toString();
            }
            if (s.equals("3") || s.equals("6") || s.equals("9"))
                return true;
            return false;
        }
    
        public static boolean divisibleBy5(int num) {
            String s = new Integer(num).toString();
            String lastDigit = s.substring(s.length() - 1, s.length());
            if (lastDigit.equals("5") || lastDigit.equals("0"))
                return true;
            return false;
        }
    }
    

    E applicarlo al FizzBuzz è un’operazione elementare.

  • Java: come scrivere un build.xml di ant per compilare e pacchettizzare (WAR/EAR)

    Come sapete, tutti i Java application server (come ad es. Tomcat) richiedono il deploy di un applicativo sottoforma di un pacchetto EAR. Ma come è composto un pacchetto EAR?

    Un pacchetto EAR non è altro che un file jar (che a sua volta è un file zip) che contiene al suo interno:

    • un descrittore di deploy, sotto la directory META-INF (application.xml) che contiene informazioni di gestione riguardo all’applicazione in corso di deploy, come il nome, il contextpath, etc.
    • generalmente, contiene un file WAR che contiene, al suo interno, il modulo web J2EE dell’applicazioni.

    A sua volta, un file WAR è un file JAR composto da:

    • il file web.xml sotto la directory WEB-INF che definisce la struttura dell’applicazione web.
    • i file compilati (.class) dell’applicazione posti sotto WEB-INF/classes

    Risalendo a ritroso, per creare un EAR è necessario:

    1. Compilare i files dell’applicazione;
    2. Spostarli sotto WEB-INF/classes insieme ai files della webapp (jsp, files statici, etc.)
    3. Creare un WAR (jar)
    4. Creare un EAR inglobando anche il meta-descrittore del deploy

    Per fare tutto questo è sufficiente usare ant (o meglio maven, ma questo ve lo spiegherò in un altro post!) con diversi target. Vediamo un esempio che ho realizzato:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="prjTest" default="main" basedir="./">
    
    <property name="component-name" value="prjTest" />
    <dirname property="workspace.path" file="${ant.file.prjTest}/.." />
    <dirname property="ear.dir" file="${ant.file.prjTest}" />
    <property name="target.dir" value="${ear.dir}/target" />
    <property name="deploy.dir" value="${ear.dir}/deploy" />
    <property name="deploy.file" value="prjTest.ear" />
    
    <target name="init">
    <mkdir dir="${target.dir}/classes" />
    <mkdir dir="${deploy.dir}" />
    </target>
    <target name="clean">
    <delete dir="${target.dir}" />
    <delete dir="${deploy.dir}" />
    <delete dir="${workspace.path}/prjTest/WebContent/WEB-INF/classes" />
    </target>
    
    <path id="myclasspath">
    <fileset dir="${workspace.path}/prjTest/WebContent/WEB-INF/lib">
    <include name="**/*.jar" />
    </fileset>
    </path>
    
    <target name="main" depends="clean,init">
    <javac srcdir="${workspace.path}/prjTest/JavaSource" destdir="${target.dir}/classes" includes="**/*.java"
    source="${source}" target="${target}"
    classpathref="myclasspath">
    </javac>
    
    <copy todir="${workspace.path}/prjTest/WebContent/WEB-INF">
    <fileset dir="${target.dir}">
    <include name="**/*" />
    <exclude name="**/.metadata/*" />
    </fileset>
    </copy>
    <copy todir="${workspace.path}/prjTest/WebContent/WEB-INF/classes">
    <fileset dir="${workspace.path}/prjTest/JavaSource">
    <include name="**/*.properties" />
    </fileset>
    </copy>
    
    <war destfile="${target.dir}/prjTest.war" webxml="${workspace.path}/prjTest/WebContent/WEB-INF/web.xml">
    <fileset dir="${workspace.path}/prjTest/WebContent" />
    </war>
    
    <ear destfile="${deploy.dir}/prjTest.ear" appxml="${workspace.path}/prjTest/META-INF/application.xml">
    <fileset dir="${target.dir}" includes="*.jar,*.war" excludes="**/.metadata/*" />
    </ear>
    </target>
    </project>
    

    Come potete vedere il target chiamato “main” si occupa di:

    • compilare tutte le classi del progetto (javac) usando il classpath di riferimento
    • copiare i files di configurazione (come il già menzionato web.xml) sotto /WEB-INF (copy)
    • copiare i compilati delle classi sotto /WEB-INF/classes (copy)
    • creare un archivio WAR (war) usando i files specificati in fileset e usando il web.xml specificato sotto webxml
    • creare un archivio EAR (ear) usando i files specificati in fileset usando il meta-application specificato in appxml e copiando i files da fileset.

    Questo è lo scheletro di build.xml che uso per pacchettizzare velocemente un’applicazione J2EE (infatti basta lanciare ant build.xml main) da linea di comando per compilare, copiare tutti i files necessari e creare WAR ed EAR!).

  • Eclipse: impostare un template per l’inserimento di un Logger log4j

    Mi capita spesso, in Eclipse, di inserire il codice per abilitare il logging di una classe tramite log4j:

    private static Logger logger = Logger.getLogger(Klass.class);
    

    Utilizzano i templates, una funzionalità di Eclipse, possiamo evitare di riscrivere tutte le volte questa semplice istruzione. Per impostare un template, in Eclipse, è sufficiente recarsi su: Window > Preferences > Java > Editor > Templates e creiamo un nuovo template.

    Nel campo pattern inseriamo:

    private static Logger logger = Logger.getLogger( ${enclosing_type}.class );
    ${:import(org.apache.log4j.Logger)}
    

    A questo punto, per inserire il logger, è sufficiente utilizzare lo shortcut CTRL+Space per visualizzare gli autocompletamenti, e selezionare “logger” dal menu.

  • Linux: come installare Java Media Framework (JMF) evitando l’errore “tail: cannot open `+309′ for reading: No such file or directory”

    Ultimamente ho dovuto installare il Java Media Framework di Sun. Tralasciando che la libreria è obsoleta (ultima versione datata 2003) e (quindi) non più mantenuta, la documentazione è molto limitata (esempi banali), javadoc non completi e l’utilizzo(!) di AWT in alcune parti, ho deciso di provare ad installarla sulla mia macchina Linux.
    I passi che ho seguito sono i seguenti:

    • Scarico il file
      jmf-2_1_1e-linux-i586.bin

      dal sito di Sun

    • chmod +x jmf-2_1_1e-linux-i586.bin
    • sh ./jmf-2_1_1e-linux-i586.bin

    Tutto sembra andare per il meglio quando incontro quest’errore (e dal numero di risultati che Google ritorna per questa chiave di ricerca direi che molta gente ha avuto lo stesso problema):

    Do you agree to the above license terms? [yes or no]y
    Permit recording from an applet? (see readme.html) [yes or no] y 
    Permit writing local files from an applet? (recommend no, see readme.html) [yes or no]n
    
    Unpacking...  tail: cannot open `+309' for reading: No such file or directory
    Extracting...  ./install.sfx.3639: line 1: ==: No such file or directory
    ./install.sfx.3639: line 3: syntax error neUQU599ù;···ÿrþÑÑÑ¢_Âò«KK)C{<>úú<<¿è
    QQRLÙÜÌLÅ^sfx.36 88ø$èåõÕ®¢¬,àöè´iÑ*ÒÒÒV~ámn.à7w^ÝÂÆ,;M¢`ÞòA$D¨®¨¨ @ ɺÎwA'
    

    Dopo aver capito cosa stava succedendo, ho capito anche come risolvere questo problema e poter installare la JMF sulla mia macchina; ecco le istruzioni:

    • Aprite il file
      jmf-2_1_1e-linux-i586.bin

      con un editor di testo, ad esempio vim (vim jmf-2_1_1e-linux-i586.bin)

    • digitate /tail (questo fa in modo che vim vi porti sulla prima occorrenza di “tail” che trova all’interno dello script )
    • A questo punto dovreste trovare una linea del tipo:
      tail +309 $0 > $outname

      modificatela in:

      tail -n +309 $0 > $outname

    Salvate il file e chiudete vim (digitate :wq seguito da Enter) e riavviate l’installazione di JMF (sh ./jmf-2_1_1e-linux-i586.bin)

    Nota: esistono framework alternativi a JMF (e probabilmente anche migliori, non mi azzardo comunque a dare una valutazione senza averli provati); ad esempio sono incuriosito da FMJ (altri framework alternativi a JMF).

  • Come rendere Eclipse IDE più veloce e reattivo

    Ho sempre trovato Netbeans IDE molto più veloce e reattivo di Eclipse. Per rendere Eclipse più veloce, ho pensato di applicare le impostazioni della JVM con le quali Netbeans viene lanciato e applicarle ad Eclipse. Ho ottenuto dei risultati molto buoni, in generale Eclipse ora è molto più veloce e scattante.

    Vediamo ora come configurare Netbeans per implementare la modifica dei parametri della JVM:

    • cercate il file eclipse.ini. La sua locazione dipende dal vostro sistema operativo e da dove avete installato Eclipse. Su Windows, ad esempio, si trova nella stessa cartella di eclipse (hint: C:\eclipse o C:\Programmi\Eclipse); su Linux, date un’occhiata a /opt/eclipse (di solito è la directory più indicata per installarlo).
    • una volta trovato il file eclipse.ini, apritelo con un editor di testo e aggiungete in fondo al file queste impostazioni di configurazione (copia/incolla, il segno – deve essere incluso):

      -Xms512m
      -Xmx512m
      -XX:PermSize=256m
      -XX:MaxPermSize=256m
      -Xverify:none
      -XX:+UseConcMarkSweepGC
      -XX:+CMSClassUnloadingEnabled
      -XX:+CMSPermGenSweepingEnabled

    • salvate e chiudete il file. Fine!

    Per i più curiosi, vediamo di spiegare cosa rappresentano le opzioni di configurazione che abbiamo specificato:

    • le prime quattro opzioni permettono di specificare la dimensione massima di memoria che Eclipse può utilizzare
    • la quinta opzione specifica alla JVM di non verificare il bytecode generato
    • per le ultime tre opzioni, vi rimando al Netbeans performance tuning tips; in generale le tre opzioni servono per fare il tuning del Garbage Collector della JVM.

    Ci possono essere altre opzioni “utili” che potrebbero incrementare la velocità di Eclipse. È d’obbligo specificare, però, che le performance ottenute potrebbero variare da computer a computer, in relazione a molteplici fattori, quali sistema operativo, versione della JVM, versione di Eclipse, etc. Come si dice in gergo, YMMV.

    Comunque, quello che io ho ottenuto è un aumento considerevole della velocità e della reattività di Eclipse, e difficilmente tornerò alle impostazioni di default.

  • Tecniche di progettazione agile con Java (design pattern, refactoring, test): la recensione

    Tecniche di Progettazione Agile con JavaIn questi giorni ho letto un libro di Sandro Pedrazzini intitolato “Tecniche di progettazione agile con Java: design pattern, refactoring, test” (Ed. Tecniche nuove, 2006 – 29.90 €).

    Sono sempre stato molto attratto dall’Agile development, dall’eXtreme Programming e dai suoi metodi e soprattutto anche dalla metologia TDD (Test Driven Development); oltre all’immancabile “Thinking in Java”, non ho mai potuto il piacere di leggere dei libri inerenti quest’argomento. Fino a quando non ho preso questo libro.

    Infatti, i libri italiani (accademici e non) non affrontano facilmente un argomento così innovativo, interessante e delicato quale la programmazione agile. Questo libro è però una piacevole eccezione: i lettori vengono introdotti passo passo alla progettazione agile, alle tecniche di refactoring e ai design pattern utilizzando numerosi esempi (in Java – sarebbe interessante una versione di questo libro dedicata al Python). Al lettore non viene lasciato alcun dubbio: più di una volta, durante la lettura del libro, mi è venuto un dubbio riguardante il codice scritto. Con mia grande sorpresa, quasi sempre nella pagina successiva c’era un box (o una nota) di chiarimenti.

    È davvero un buon libro e scritto nell’ottica di poter servire ai lettori: gli argomenti sono espressi in modo chiaro e semplice, e soprattutto dal punto di vista del lettore, cioè dal punto di vista di chi legge per imparare! (e non come alcuni libri dove chi scrive lo fa per dimostrare quanto è bravo). I capitoli sono compatti (come le classi scritte da un buon programmatore XP?) e si leggono molto facilmente. Gli esempi sono curati e molto chiari.

    In definitiva si tratta di un libro che consiglio, da leggere e da tenere nella propria “biblioteca” per ogni futura evenienza.