V parte: un esempio pratico

Introduzione

Come visto nel corso degli articoli precedenti, i file pom.xml (Project Object Model, modello ad oggetti del progetto) contengono i meta-dati del progetto memorizzati secondo il formato xml. Pertanto, è importante dar luogo ad una loro corretta configurazione, non solo per consentire una efficace gestione del progetto, ma anche per minimizzare l'impiego di tempo destinato per la relativa manutenzione. Gli esempi presentati in questo articolo sono stati selezionati per una serie di motivi. In primo luogo, corredando con la dimensione pratica le illustrazioni teoriche degli articoli precedenti, dovrebbero concorrere ad aumentare il grado di comprensione della struttura del file pom.xml, molto articolata e non sempre di immediata comprensione, soprattutto in relazione ad un utilizzo in progetti di medie-grandi dimensioni. Inoltre, dovrebbero evidenziare come, anche per progetti non semplici ed abbastanza articolati, non sia assolutamente necessario impostare tutti gli elementi di questo file ed anzi, come i vari file tendano ad essere piuttosto semplici, soprattutto dopo aver impostato correttamente il pom genitore. Infine, le varie configurazioni riportate dovrebbero prestarsi ad essere riutilizzate, con minime variazioni, in altri progetti, magari in quelli in cui lavorano i vari lettori che, attualmente, non fanno uso di Maven. In effetti, è assolutamente normale preparare i vari file POM per un primo progetto, è poi, con minime variazioni, riutilizzarli in progetti successivi. I vari file pom riportati sono stati corredati con pochissime informazioni supplementari, questo perché la struttura del file è stata abbondantemente discussa nel corso degli articoli precedenti (cfr.: [7] e [8]). Pertanto si rimanda a questi per maggiori informazioni. Inoltre, sebbene i vari file pom riportati di seguito sono stati attinti da un progetto reale, alcune informazioni, come per esempio gli indirizzi URL dei vari server, sono state volontariamente alternate per ovvi motivi di sicurezza/privatezza. Infine, viste le dimensioni dei singoli file pom, per ovvi motivi di spazio, in questo articolo è stato possibile presentarne solo una piccola selezione.

Breve presentazione del progetto

I file pom presentati di seguito appartengono al progetto del sistema Sentinel disegnato per fornire servizi di sicurezza necessari alla gestione di sistemi software di medie grandi dimensioni costituiti da una rete di sistemi cooperanti. I principali servizi forniti sono:

  • autenticazione: il sistema verifica che l'utente/sistema (subject) connesso sia veramente chi/cosa dichiara di essere
  • autorizzazione: il sistema verifica che il profilo del subject precedentemente autenticato sia abilitato ad eseguire il determinato servizio (o insieme) richiesto
  • data-privacy: il sistema verifica che il subject riceva o tenti di manipolare solo il sottoinsieme di dati di cui possiede l'autorizzazione
Figura 1 - Organizzazione del progetto in sotto-progetti. Le linee tratteggiate rappresentano relazioni di dipendenza
Figura 1 - Organizzazione del progetto in sotto-progetti. Le linee tratteggiate rappresentano relazioni di dipendenza

Il progetto Sentinel è stato organizzato nei seguenti sotto-progetti mostrati in figura 1:

  • sentinel-security-dto: questo progetto contiene le classi DTO (Data Transfer Object). Questi non sono altro che normali POJO con specifico significato architetturale. In particolare sono utilizzati come parametri dell'interfaccia business del sistema. Trattandosi di un sistema di sicurezza, in questo contesto i servizi business sono quelli della sicurezza descritti poc'anzi. Questi DTO possono essere utilizzati direttamente dai vari client (invocazione RMI) o per mezzo di serializzazioni/deserializzazioni XML/Web Service (invocazioni: JMS, HTTP)
  • sentinel-client-api: la libreria prodotta da questo progetto incapsula i DTO del punto precedente e vi aggiunge una serie di servizi messi a disposizione dei sistemi client, come per esempio il marshalling e unmarshalling dei messaggi XML. Ciò permette ai vari client di interagire con il sistema Sentinel impostando una serie di oggetti Java (i DTO del punto 1) e quindi trasformarli da e verso XML attraverso i servizi offerti da questa libreria
  • sentinel-admin-dto: è un progetto molto simile al primo (sentinel-security-dto), con l'eccezione che i DTO contenuti in questo sono utilizzati dai servizi di amministrazione del sistema Sentinel. I due insiemi di DTO sono stati separati in quanto i client business del sistema (gli altri sistemi che necessitano di usufruire dei servizi di sicurezza), tipicamente, non sono assolutamente abilitati ad eseguire i servizi di amministrazione, riservati ai sistemi UI di Sentinel
  • sentinel-admin-ui: contiene il codice necessario per l'implementazione dell'interfaccia grafica di Sentinel. La tecnologia utilizzata è AJAX, tramite il framework Echo2. Questo progetto, il cui obiettivo è consentire agli utenti abilitati di configurare Sentinel, utilizza gli stessi servizi di Sentinel per risolvere i propri requisiti di sicurezza. Sebbene Sentinel riesegua al proprio interno i vari controlli di sicurezza, questi sono utilizzati anche dalla GUI per migliorare l'esperienza dell'utente. Per esempio, servizi di cui l'utente non possiede i necessari permessi non sono mostrati, i dati vengono pre-filtrati, etc. Questo progetto quindi necessita sia dei DTO amministrativi sia quelli relativi alla sicurezza
  • sentinel-server: questo progetto non richiede ulteriori spiegazioni: si tratta dell'implementazione server side del sistema di Sentinel. Come si può notare si tratta di un jar giacché è stato implementato utilizzando Spring. Qualora si fosse deciso di utilizzare un application server, sarebbe stato necessario dar luogo ad un ear file
  • sentinel-security-endpoint: questo progetto include la servlet invocata dai sistemi client per accedere ai servizi Sentinel qualora il protocollo utilizzato sia HTTP (precisamente HTTPS)
  • sentinel-test-client: l'obiettivo di questo progetto dovrebbe essere auto-esplicativo

File pom genitore

Una caratteristica molto potente e unica di Maven, come visto abbondantemente nel corso degli articoli precedenti, è la possibilità di relazionare tra loro i progetti con veri e propri legami di ereditarietà. Questo permette di definire tutta una serie di impostazioni comuni nel file pom genitore e di ereditarle automaticamente nei vari file pom discendenti. La conseguenza è che è possibile sia centralizzare la gestione di molte informazioni (non si tratta solo di evitare una serie di copy&paste, ma anche di assicurarsi che i vari sotto-progetti utilizzino determinate librerie, che le relative versioni sia quelle selezionate, ecc.), sia di semplificare la stesura dei vari pom per i sotto-progetti. Ciò fa sì che questi ultimi, per la maggior parte dei casi, si possano limitare ad accettare le impostazioni del pom genitore. Progetti di dimensioni medio-grandi richiedono di predisporre il file system destinato ad ospitare i vari progetti secondo una determinata gerarchia di directory, in cui la prima, in questo caso denominata sentinel, è la radice dell'intero progetto. Proprio in questa va memorizzato il file pom genitore. Da questa directory poi è possibile dar luogo una sub-directory per ogni sotto-progetto. Per esempio: ...\sentinel\sentinel-client-api, nella cui root va memorizzato il relativo file pom.

Ed ecco un lungo listato: il pom genitore.

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mb.security.sentinel</groupId>
  <artifactId>sentinel</artifactId>
  <version>1.4-SNAPSHOT</version>
  <name>Sentinel Security System</name>
  <url>http://mbit0164570.develop.mb.net:8085/display/security/home</url>
  <packaging>pom</packaging>

  <developers>
    <developer>
      <id>vettitlu</id>
      <name>Luca Vetti Tagliati</name>
      <email>LucaVT@gmail.com</email>
      <roles>
        <role>Project Lead</role>
        <role>Lead Architect</role>
        <role>Senior Developer</role>
      </roles>
      <properties/>
    </developer>
    <developer>
      <id>pulitig</id>
      <name>Giovanni Puliti</name>
      <email>gpuliti@mokabyte.it</email>
      <roles>
        <role>Project Manager</role>
        <role>Senior Developer</role>
      </roles>
      <properties/>
    </developer>
    <developer>
      <id>saliolaf</id>
      <name>Francesco Saliola</name>
      <email>fsaliola@mokabyte.it</email>
      <roles>
        <role>Relationship Manager</role>
      </roles>
      <properties/>
    </developer>
  </developers>

  <scm>
    <connection>scm:svn:https://subversion.mb.it/svn/security/trunk/sentinel/</connection>
    <developerConnection>scm:svn:https://subversion.mb.it/svn/security/trunk/sentinel/</developerConnection>
    <url>https://subversion.mb.it/svn/security/trunk/sentinel/</url>
  </scm>

  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-site-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jxr-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-report-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-clover-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-project-info-reports-plugin</artifactId>
        <reportSets>
          <reportSet>
            <reports>
              <report>index</report>
              <report>dependencies</report>
              <report>project-team</report>
              <report>scm</report>
            </reports>
          </reportSet>
        </reportSets>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
        <configuration>
          <linkXref>true</linkXref>
          <sourceEncoding>utf-8</sourceEncoding>
          <minimumTokens>100</minimumTokens>
          <targetJdk>1.5</targetJdk>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptors>
            <descriptor>${basedir}/src/assemble/devDeploy.xml</descriptor>
          </descriptors>
          <finalName>${artifactId}</finalName>
          <outputDirectory>${basedir}/target/release</outputDirectory>
          <appendAssemblyId>false</appendAssemblyId>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-release-plugin</artifactId>
        <configuration>
          <tagBase>https://subversion.mb.it/svn/security/tags</tagBase>
        </configuration>
      </plugin>
    </plugins>
  </reporting>

  <modules>
    <module>constraint-lib</module>
    <module>security-dto</module>
    <module>security-endpoint</module>
    <module>admin-dto</module>
    <module>admin-ui</module>
    <module>test-client</module>
    <module>client-api</module>
    <module>server</module>
    <module>system-test</module>
    <module>security-infrastructure</module>
  </modules>

  <dependencies>
    <!--all components must use junit as unit testing framework-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.jakarta-log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.13</version>
      <type>jar</type>
    </dependency>
  </dependencies>

  <repositories>
    <repository>
      <id>security-repo</id>
      <url>http://mb0935dap.it.mb.it:8500/mavenRepo</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>central</id>
      <url>http://hammer.mb.it:5201/runtimeRepo</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>xtools-hufs</id>
      <url>http://hammer.mb.it:5201/hufsRepo</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>security-repo</id>
      <url>http://mbit0935dap.ldn.mb.it:8500/mavenRepo</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </pluginRepository>
    <pluginRepository>
      <id>central</id>
      <name>xtools-plugins</name>
      <url>http://hammer.mb.it:5201/runtimeRepo</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
    <pluginRepository>
      <id>xtools-hufs</id>
      <url>http://hammer.mb.it:5201/hufsRepo</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.1.3</version>
        <configuration>
          <forkMode>once</forkMode>
          <childDelegation>false</childDelegation>
          <argLine>-Xmx512M</argLine>
          <includes>
            <include>**/*Test.java</include>
          </includes>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-clover-plugin</artifactId>
        <!-- jar file with colver-teamedition.licence -->
        <dependencies>
          <dependency>
            <groupId>com.mb.pkgs.SPP</groupId>
            <artifactId>build-tools</artifactId>
            <version>1.0-SNAPSHOT</version>
          </dependency>
        </dependencies>
        <configuration>
          <licenseLocation>clover-teamedition.licence</licenseLocation>
          <jdk>1.5</jdk>
          <generateXml>true</generateXml>
        </configuration>
        <executions>
          <execution>
            <phase>pre-site</phase>
            <goals>
              <goal>instrument</goal>
              <goal>aggregate</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-deploy-plugin</artifactId>
        <configuration>
          <url>file:///home/sppdev/webserver/htdocs/mavenRepo</url>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <distributionManagement>

  <distributionManagement>
    <!--For continuous integration, deployment of SNAPSHOT jars to remote repository-->
    <repository>
      <id>security-ci-repo</id>
      <name>Security Continuous Integration Repository</name>
      <url>file:///home/sppdev/webserver/htdocs/mavenRepo</url>
    </repository>
    <!--For nightly build website containing documentation and test coverage reports-->
    <site>
      <id>website</id>
      <url>file:///home/sppdev/webserver/htdocs/Sentinel</url>
    </site>
  </distributionManagement>

  <properties>
  </properties>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.mb.security.sentinel</groupId>
    <artifactId>Sentinel</artifactId>
    <version>1.4-SNAPSHOT</version>
  </parent>

  <artifactId>sentinel-admin-dto</artifactId>
  <name>Admin DTO</name>
  <packaging>jar</packaging>
  <url>http://mbit0164570.develop.mb.net:8085/display/security/home</url>
  <description>
    This project includes the DTOs (POJOs) used by the Sentinel architecture.
    They represent the object graphs used in the admin services exposed by the system itself.
  </description>

  <dependencies>
    <dependency>
      <groupId>com.mb.pd.jakarta-commons</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <executions>
          <execution>
            <id>Build test-jar</id>
            <goals>
              <goal>test-jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.mb.security.sentinel</groupId>
    <artifactId>sentinel</artifactId>
    <version>1.4-SNAPSHOT</version>
  </parent>

  <!-- component specific details -->
  <artifactId>sentinel-server</artifactId>
  <name>Sentinel Server</name>
  <packaging>jar</packaging>
  <version>1.4-SNAPSHOT</version>
  <url>http://mbit0164570.develop.mb.net:8085/display/security/home</url>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <executions>
          <execution>
            <id>Build test-jar</id>
            <goals>
              <goal>test-jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
    <resources>
      <resource>
        <directory>src/main/spring-config</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/hibernate</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/script</directory>
        <includes>
          <include>**/*.sql</include>
        </includes>
      </resource>
    </resources>
  </build>

  <dependencies>
    <dependency>
      <groupId>com.mb.tp.JavaMail</groupId>
      <artifactId>mail</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.mx4j.lib</groupId>
      <artifactId>mx4j</artifactId>
      <version>3.0.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.mx4j.lib</groupId>
      <artifactId>mx4j-impl</artifactId>
      <version>3.0.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.mx4j.lib</groupId>
      <artifactId>mx4j-jmx</artifactId>
      <version>3.0.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.mx4j.lib</groupId>
      <artifactId>mx4j-tools</artifactId>
      <version>3.0.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.springframework</groupId>
      <artifactId>spring</artifactId>
      <version>1.2.6</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.springframework</groupId>
      <artifactId>spring-mock</artifactId>
      <version>1.2.6</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.hibernate</groupId>
      <artifactId>hibernate3</artifactId>
      <version>3.1.3</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.hibernate</groupId>
      <artifactId>hibernate-tools</artifactId>
      <version>3.2.0.beta6</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.jakarta-commons</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.0.4</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.jakarta-commons</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.2.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.jakarta-commons</groupId>
      <artifactId>commons-pool</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.jakarta-commons</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.7.0</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.jakarta-commons</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.hibernate.lib</groupId>
      <artifactId>jta</artifactId>
      <version>3.1.3</version>
    </dependency>
    <dependency>
      <groupId>com.b.pd.hibernate.lib</groupId>
      <artifactId>antlr</artifactId>
      <version>2.7.6rc1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.hibernate.lib</groupId>
      <artifactId>asm</artifactId>
      <version>3.1.3</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.hibernate.lib</groupId>
      <artifactId>cglib</artifactId>
      <version>2.1.3</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.hibernate.lib</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.hibernate.lib</groupId>
      <artifactId>ehcache</artifactId>
      <version>1.1</version>
    </dependency>
    <dependency>
      <groupId>com.mb.pd.easymock</groupId>
      <artifactId>easymock</artifactId>
      <version>2.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.mb.tp.oracle</groupId>
      <artifactId>ojdbc14</artifactId>
      <version>10.2.0.2.0-32bit</version>
    </dependency>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>sentinel-constraint-lib</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>sentinel-security-dto</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>sentinel-admin-dto</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>security-infrastructure</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>
</project>