Las dependencias en los distintos proyectos ------------------------------------------- A la hora de identificar un *artefacto* en maven, lo normal es que que intervengan al menos tres componentes, sin los cuales no es posible identificar al *artefacto*. Estos serian: - Grupo, **groupId**. Normalmente hace referencia al nombre de nuestra organización. Por ejemplo en gvSIG utilizamos *"org.gvsig"*, por otras organizaciones o empresas pueden utilizar uno propio. - Identificador, **artefactId**. Deber ser un identificador del proyecto único dentro del grupo. - Versión, **version**. En el proceso de desarrollo iremos generando distintas revisiones o versiones de nuestros productos o *artefactos*. Para identificarlos no solo deberemos indicar su nombre, si no también la versión a la que nos referimos. Todo proyecto maven deberá identificarse por estos tres datos. Así en el *pom.xml* del raíz de nuestro proyecto encontraremos algo como: .. code-block:: xml org.gvsig org.gvsig.landregistryviewer 1.0.0-SNAPSHOT Donde se declaran esos valores. Además en el *pom* de nuestro proyecto raíz también encontraremos: - Una declaración de quien es el padre o de quien extiende nuestro proyecto, sección **parent**: .. code-block:: xml org.gvsig org.gvsig.desktop 2.0.157 Aquí observaremos que, normalmente, en un proyecto gvSIG, extenderemos o heredaremos del proyecto *org.gvsig:org.gvsig.desktop*. Este proyecto tiene la configuración necesaria para compilar y desplegar proyectos gvSIG, normalmente plugins para la aplicacion *gvSIG desktop* y las librerias que estos precisen. Además de la configuración básica, también tiene declarada la versión de todos los componentes que forman el núcleo de gvSIG, de forma que no tengamos que declararla cada vez que indiquemos una dependencia con un subproyecto del núcleo. - Una sección donde declararemos las versiones de los subproyectos que conforman nuestro proyecto. En maven esto lo realizaremos en la sección **dependencyManagement**. Normalmente aquí especificaremos: - Todos los subproyectos de nuestro proyecto. - Las dependencias con los proyecto o artefactos que no formen parte del núcleo de gvSIG, como otras librerías que podamos necesitar. Hay que tener en cuenta que en esta sección, **dependencyManagement**, indicamos que versiones de que artefactos queremos usar cuando especifiquemos una dependencia con estos en la sección **dependencies**. Que aparezca una depedencia en **dependencyManagement** no le esta indicando a *maven* que exista una dependencia real con ese artefacto, esto solo sucederá con las que se incluyan en la sección **dependencies**. Para nuestro caso tendríamos algo como: .. code-block:: xml org.gvsig org.gvsig.landregistryviewer.lib.api 1.0.0-SNAPSHOT org.gvsig org.gvsig.landregistryviewer.lib.api 1.0.0-SNAPSHOT test-jar org.gvsig org.gvsig.landregistryviewer.lib.impl 1.0.0-SNAPSHOT org.gvsig org.gvsig.landregistryviewer.swing.api 1.0.0-SNAPSHOT org.gvsig org.gvsig.landregistryviewer.swing.api 1.0.0-SNAPSHOT test-jar org.gvsig org.gvsig.landregistryviewer.swing.impl 1.0.0-SNAPSHOT org.gvsig org.gvsig.landregistryviewer.app.mainplugin 1.0.0-SNAPSHOT Muy importante que las versiones de los subproyectos aquí indicadas coincidan siempre con la versión del proyecto raíz. La finalidad principal sera centralizar en este *pom* la declaración de las versiones de las dependencias de nuestro proyecto de cara a facilitar su mantenimiento. Si dependediesemos de algún otro proyecto de gvSIG, normalmente lo que haremos seria importar las dependencias que este tuviese declaradas en su *dependencyManagement* en lugar de ir declarando una a una las que precisemos. Esto reduce la posibilidad de confusión al declarar las dependencias de estos. Así por ejemplo si quisiésemos declarar las versiones de los subproyectos base de raster pondríamos algo como: .. code-block:: xml org.gvsig org.gvsig.raster ${org.gvsig.raster.version} pom import org.gvsig org.gvsig.landregistryviewer.lib.api 1.0.0-SNAPSHOT ... Y declararíamos la propiedad *"org.gvsig.raster.version"* en la sección *properties*: .. code-block:: xml 2.2.52 Podemos o no usar un *property* para indicar la versión del proyecto del cual importamos las dependencias. La ventaja de usar un *property* es que podemos actualizar nuestro proyecto fácilmente a la ultima revisión de gvSIG con:: mvn versions:update-parent versions:update-properties Pero antes de ejecutar esto es conveniente informarse de si se ha generado ya alguna versión mas nueva que con la que estamos trabajando, en nuestro caso 2.3.1-2501. Una cuestión mas a tener en cuenta relacionada con las versiones de los artefactos que podemos encontrar en el *"pom"* es que estas no se corresponden con las versiones de la aplicación "gvSIG desktop". La aplicación de usuario lleva su linea de versiones y cada uno de los artefactos de gvSIG la suya. Siendo así... ¿ Como podemos saber que versión de artefacto debemos usar ? Para saber la versión de *org.gvsig.desktop* que debemos usar, deberemos decidir contra que versión de la aplicación *gvSIG desktop* deberemos trabajar, y disponer de una versión de esta instalada. Miraremos la versión del jar:: org.gvsig.andami-*.jar de dentro de la carpeta *"lib"* de la instalación de gvSIG. La versión de ese jar nos dirá la versión que debemos usar como versión de *"org.gvsig.desktop"*. Para *"gvSIG desktop 2.3.1-2501"* es **2.0.157**. En el caso de la librería base de raster, org.gvsig.raster, en la carpeta *lib* del plugin *org.gvsig.raster.mainplugin*, podemos encontrar:: org.gvsig.raster.lib.api-*.jar del que podemos obtener la versión de esta. O si queremos enlazar con el plugin de *"mapas"*, consultaríamos en el plugin *org.gvsig.app.document.layout2.app.mainplugin*, en la carpeta *lib* la versión de:: org.gvsig.app.document.layout2.app.mainplugin-*.jar Las versiones de las dependencias mas comunes a usar podemos encontrarlas en: .. list-table:: Proyectos mas comunes :header-rows: 1 * - Proyecto - jar * - org.gvsig.desktop - lib/org.gvsig.andami-...jar * - org.gvsig.raster - gvSIG/extensiones/org.gvsig.raster.mainplugin/lib/org.gvsig.raster.lib.api-...jar * - org.gvsig.geoprocess - gvSIG/extensiones/org.gvsig.geoprocess.app.mainplugin/lib/org.gvsig.geoprocess.app.mainplugin-...jar * - org.gvsig.hyperlink.app - gvSIG/extensiones/org.gvsig.hyperlink.app.extension/lib/org.gvsig.hyperlink.app.extension-...jar * - org.gvsig.mapsheets.app - gvSIG/extensiones/org.gvsig.mapsheets.app.mainplugin/lib/org.gvsig.mapsheets.app.mainplugin-...jar * - org.gvsig.vectorediting - gvSIG/extensiones/org.gvsig.vectorediting.app.mainplugin/lib/org.gvsig.vectorediting.app.mainplugin-...jar * - org.gvsig.tools - lib/org.gvsig.tools.lib-...jar Además de la sección **parent** y **dependencyManagement**, en el *pom* podemos encontrarnos una sección **dependencies**. Esta sección es donde se declaran las dependencias reales de nuestro proyecto, a partir de las que se construirá el *classpath* de compilación y ejecución. Sin embargo recomendamos que en proyectos de tipo *pom*, como es el raíz, no incluyamos ninguna dependencia, incluyéndolas únicamente en los proyectos *hoja*, de tipo *jar*, ya que en un momento dado puede desvirtuarnos los informes de dependencias de nuestros proyectos. Por ultimo, relacionado con el *pom* del proyecto raíz, es importante la sección **modules**, que indica cuales son los subproyectos de este. Es importante tener en cuenta que una carpeta dentro del proyecto raíz no es un subproyecto o modulo de este si no se declara aquí. Vamos a comentar ahora sobre los demás *poms* que encontraremos en los distintos subproyectos. Primero, sobre los *poms* de los subproyectos o módulos de tipo *pom*, que no son subproyectos *hoja*. En estos lo mas importante es tener en cuenta que: - Deberemos indicar siempre una sección **parent** en la que referenciaremos al pom padre de este, utilizando su **groupId**, **artifactId** y **version**. - Incluiremos solo **artifactId**, ya que la *version* y *groupId* lo heredara del padre. - No incluiremos sección **dependencies**. - Incluiremos la sección **modules** con los subproyectos de este. Ahora pasemos a ver que tendremos en los *poms* de los proyectos *hoja*, de tipo *jar*. Estos proyectos son los que generan *artefactos*, normalmente *jars* con nuestro código y los que precisan que especifiquemos dependencias de cara a su correcta compilación. Asi que sera en estos donde deberemos incluir la sección **dependencies**. A la hora de especificar una dependencia tendremos que tener en cuenta que: - Siempre especificaremos su **groupId** y **ArtefactId**. - No especificaremos nunca su **version**, esta deberemos haberla incluido en el **dependenciesManagement** de nuestro proyecto raíz o vendrá heredada del proyecto *org.gvsig.desktop*. - Deberemos especificar siempre el *scope* de la dependencia. Aunque maven no lo requiere siendo *compile* si no se especifica, desde el proyecto gvSIG recomendamos que se incluya siempre de cara a evitar confusiones. Normalmente el **scope** sera: - compile - runtime Aunque hay algunos mas. Este nos indicara si esa dependencia debe incluirse en el *classpath* de compilación o de ejecución. Vamos a comentar ahora algunas consideraciones sobre las dependencias entre los distintos subproyectos. En gvSIG tendemos a separar *conceptos*, API/implementacion por un lado y logica/GUI/plugin, influyendo esto directamente en la estructura de proyectos, ya que como vimos anteriormente disponemos de un proyectos para la lógica (...lib) con su API e implementación, otro proyecto para el interface de usuario (...swing), también con su API e implementación, y otro para los plugins de gvSIG (...app). Ahora bien... ¿ Que dependencias podemos encontrar en cada uno de ellos ? Normalmente tendremos en cuenta una serie de reglas: - La definición de APIs solo dependerá de proyectos que definan APIs. Normalmente en los proyectos que definen APIs su *artifactId* termina en *".api"*. - Nadie tendrá dependencias con proyectos que contengan la implementación de un API, dependiendo estos exclusivamente de APIs. - En general, una librería, de API o implementación, nunca dependerá de una implementación, un plugin de gvSIG a el framework de runtime de la aplicación gvSIG (andami). - Las librerías que contienen el interface de usuario, tanto su API como su implementación, no deberán depender de la librería que implementa la lógica de ese interface de usuario, solo de su API. - Solo los proyectos de tipo plugin de gvSIG podrán tener dependencias con otros plugins o el framework de ejecución de gvSIG. Con esto en mente podemos echar un vistazo a las dependencias de los distintos *poms* de nuestros proyectos. - **org.gvsig.landregistryviewer.lib.api**: .. code-block:: xml org.gvsig org.gvsig.tools.lib compile org.gvsig org.gvsig.tools.lib test-jar test org.gvsig org.gvsig.fmap.geometry.api compile org.gvsig org.gvsig.fmap.dal.api compile Depende de la librería *org.gvsig.tools.lib*, que contiene todas las utilidades básicas para separación de API e implementación, con lo que prácticamente todos nuestros proyectos dependerán de ella, y del API de las librerías de acceso a datos, *org.gvsig.fmap.dal.api* y de manejo de geometrías, *org.gvsig.fmap.geometry.api*. Como se aprecia, solo depende de APIs. - **org.gvsig.landregistryviewer.lib.impl**, básicamente mantiene las mismas dependencias que el API, pero además tiene dependencias de compilación con este. - **org.gvsig.landregistryviewer.swing.api**: .. code-block:: xml org.gvsig org.gvsig.tools.lib compile org.gvsig org.gvsig.tools.lib test-jar test org.gvsig org.gvsig.tools.swing.api compile org.gvsig org.gvsig.landregistryviewer.lib.api compile Dependerá del API de la parte de lógica, *org.gvsig.landregistryviewer.lib.api*, y además del API de la parte de *swing* de la libreria org.gvsig.tools, *org.gvsig.tools.swing.api*. - **org.gvsig.landregistryviewer.swing.impl**, dependerá básicamente de su API. - **org.gvsig.landregistryviewer.app.mainplugin**, la parte del plugin para gvSIG desktop, dependerá de: .. code-block:: xml org.gvsig org.gvsig.landregistryviewer.lib.api compile org.gvsig org.gvsig.landregistryviewer.swing.api compile org.gvsig org.gvsig.tools.lib compile org.gvsig org.gvsig.tools.swing.api compile org.gvsig org.gvsig.andami compile org.gvsig org.gvsig.app.mainplugin compile org.gvsig org.gvsig.fmap.control compile org.gvsig org.gvsig.fmap.mapcontext.api compile org.gvsig org.gvsig.fmap.geometry.api compile org.gvsig org.gvsig.fmap.dal.api compile org.gvsig org.gvsig.projection.api compile org.gvsig org.gvsig.landregistryviewer.lib.impl runtime org.gvsig org.gvsig.landregistryviewer.swing.impl runtime Como se trata del plugin para gvSIG, este depende específicamente del framework de la aplicación gvSIG desktop, *org.gvsig.andami*, y del plugin principal de la aplicación, *org.gvsig.app.mainplugin*. Además depende de algunas otras librerías de gvSIG, como: - org.gvsig.fmap.control, componente gráfico para visualizar un mapa. - org.gvsig.fmap.mapcontext.api, la parte de lógica del componente del mapa. - org.gvsig.fmap.geometry.api, la librería de geometrías. - org.gvsig.fmap.dal.api, la librería de acceso a datos. - org.gvsig.projection.api, la librería de proyecciones. - org.gvsig.tools.lib. - org.gvsig.tools.swing.api. Además de depender para compilación de los APIs de las librerías del proyecto: - org.gvsig.landregistryviewer.lib.api - org.gvsig.landregistryviewer.swing.api Y lo mas importante, deberá depender de las implementaciones de las librería del proyecto en modo runtime. - org.gvsig.landregistryviewer.lib.impl - org.gvsig.landregistryviewer.swing.impl Es importante esto por dos razones. Por un lado deben ser solo de runtime, si no significaría que no hemos definido correctamente el API de nuestro proyecto, y por otro, es preciso que se incluya la dependencia como de runtime ya que necesitaremos desplegarlas en nuestro plugin y para ello es obligatorio que nuestro plugin dependa de ellas, como veremos mas adelante cuando comentemos el código del plugin.