Tutorial Castor XML (y IV): Integración con Spring

 Si  utilizamos Castor XML en un proyecto en el que se esté usando el contenedor de Spring, podemos delegar en éste la gestión de las instancias de Marshaller y Unmarshaller que necesitemos. La  integración se consigue a través del uso de la librería spring-xml proporcionada por Castor XML. Sin embargo, hay que tener que en cuenta que el desarrollo de esta librería ha sido abandonado y en su lugar se recomienda utilizar el módulo Spring OXM , integrado en Spring 3, tal y como veremos un poco más adelante en este mismo artículo. No obstante, el mecanismo de integración que se presenta a continuación sigue funcionando correctamente con Spring 3 por lo que no necesitamos utilizar Spring OXM si no lo deseamos (aunque su adopción es más que recomendable).

Vamos a hacer una prueba de concepto integrando con Spring el segundo proyecto de ejemplo del capítulo anterior. El nuevo proyecto se llamará  pruebasCastor-41  y en el pom añadiremos dos nuevas dependencias :

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.danielme.blog.castorxml</groupId>
	<artifactId>pruebasCastor-41</artifactId>
	<version>1.0</version>
	<name>pruebasCastor-41</name>

	<description>Pruebas de marshalling/unmarshalling con Castor XML. Integración con Spring.</description>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.build.mainClass>com.danielme.blog.castorxml.pruebas41.Main</project.build.mainClass>
	</properties>

	<licenses>
		<license>
			<name>El presente proyecto Maven es el código de ejemplo utilizado en el tutorial    "Introducción a Castor XML", publicado con licencia Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0  Unported en la web 	
      "http://danielme.com"</name>
		</license>
	</licenses>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-jar-plugin</artifactId>
					<version>2.3.2</version>
					<configuration>
						<archive>
							<manifest>
								<addClasspath>true</addClasspath>
								<mainClass>${project.build.mainClass}</mainClass>
							</manifest>
						</archive>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.3.2</version>
					<configuration>
						<source>1.5</source>
						<target>1.5</target>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.codehaus.mojo</groupId>
					<artifactId>exec-maven-plugin</artifactId>
					<version>1.2.1</version>
					<executions>
						<execution>
							<goals>
								<goal>java</goal>
							</goals>
						</execution>
					</executions>
					<configuration>
						<mainClass>${project.build.mainClass}</mainClass>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.codehaus.castor</groupId>
			<artifactId>castor-xml</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.castor</groupId>
			<artifactId>spring-xml</artifactId>
			<version>1.2.1</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-beans</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>

	</dependencies>

</project>

En este pom se incluye como dependencia la última versión de spring-context (no necesitamos más para nuestro ejemplo) y de spring-xml. Esta última librería depende a su vez de la versión 2.5.4 de spring-beans, por lo que para evitar conflictos al utilizar otra versión de Spring se ha excluído.

Como novedad con respecto a los ejemplos anteriores, hay que crear el correspondiente XML con la definición en Spring de los beans necesarios para utilizar Castor XML. Un posible patrón a seguir es el siguiente:

  1. Se define un bean de tipo org.castor.spring.xml.XMLContextFactoryBean que tendrá como propiedad una lista de los ficheros de mapeos a utilizar.
  2. Se crea el Marshaller(org.castor.spring.xml.CastorMarshallerFactoryBean) y Unmarshaller (org.castor.spring.xml.CastorUnmarshallerFactoryBean) que utilizará el bean definido en primer lugar.
  3. Para abstraer aún más el código, se puede utilizar org.castor.spring.xml.DataBindingTemplate para encapsular el Marshaller y Unmarshaller.

El fichero, que ubicaremos en /src/main/resources/springcontext.xml, quedará tal que así:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="xmlContext" class="org.castor.spring.xml.XMLContextFactoryBean">
		<property name="mappingLocations">
			<list>
				<value>mappings/mapping.xml</value>
			</list>
		</property>
	</bean>

	<bean id="marshaller" class="org.castor.spring.xml.CastorMarshallerFactoryBean">
		<property name="xmlContext" ref="xmlContext" />
	</bean>

	<bean id="unmarshaller" class="org.castor.spring.xml.CastorUnmarshallerFactoryBean">
		<property name="xmlContext" ref="xmlContext" />
	</bean>

	<bean id="castorXmlTemplate" class="org.castor.spring.xml.DataBindingTemplate">
		<property name="marshaller" ref="marshaller" />
		<property name="unmarshaller" ref="unmarshaller" />
	</bean>


</beans>

Para usar Castor XMl, ahora sólo necesitamos inyectar o recuperar el bean castorXmlTemplate. El método main que utilizamos para las pruebas con este cambio es el siguiente:

public static void main(String[] args) 
{
	String fichero = "exportacionEquipo.xml";
	SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

	//Se inicia programáticamente el contenedor de Spring y se obtiene el bean
  	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/springcontext.xml");
  	DataBindingTemplate castorXmltemplate = (DataBindingTemplate) applicationContext.getBean("castorXmlTemplate");
		
	Equipo equipo = equipoDePrueba();
	try
	{
		FileWriter writer = new FileWriter(fichero);

		//llamada al marshaller
  		castorXmltemplate.marshal(equipo, writer);	
			
		FileReader fileReader = new FileReader(fichero);

		//llamada al unmarshaller
  		Equipo unmarshal = (Equipo) castorXmltemplate.unmarshal(fileReader, Equipo.class);

		System.out.println("EQUIPO : " + unmarshal.getNombre());
		System.out.println("entrenador: " + unmarshal.getEntrenador().getNombre() + " "
					+ unmarshal.getEntrenador().getApellidos());
		System.out.println("jugadores  ");

		for (Jugador jugador: unmarshal.getJugadores())
		{
			StringBuffer sb = new StringBuffer("            " + jugador.getDorsal() + ": " + jugador.getNombre() + " " + jugador.getApellidos());
		if (jugador.getFechaNacimiento() != null)
			{
				sb.append(" ( " + sdf.format(jugador.getFechaNacimiento().getTime()) + " ) ");
			}
			System.out.println(sb);
		}
	}
	catch (IOException e1)
	{
		e1.printStackTrace();
	}
}

El resultado final será el mismo que en el capítulo anterior.

SPRING OXM

Una de las grandes novedades de  Spring 3 fue la creación del módulo spring-oxm con las funcionalidades de marshalling/unmarshalling de XML que hasta ese momento estaban incluídas dentro de Spring Web Services.

Spring OXM (Object/XML Mapping)  es una capa de abstracción que facilita la utilización de frameworks de marshalling/unmarshalling (Castor XML, XML  Beans, JiBX y XStream), unificando su uso bajo el mismo conjunto de interfaces. Esto permite, por ejemplo, utilizar en un mismo proyecto más de uno de estos frameworks de forma no intrusiva, o cambiar de implementación minimizando el impacto.

springoxm

Vamos a volver a adaptar el proyecto de ejemplo del capítulo anterior para realizar la integración con Spring mediante spring-oxm y no con la libreria propia (y ya discontinuada) de Castor XML. Por ello, en el pom ahora tendremos como dependencia spring-oxm y no el spring-xml de Castor.

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.danielme.blog.castorxml</groupId>
	<artifactId>pruebasCastor-42</artifactId>
	<version>1.0</version>
	<name>pruebasCastor-42</name>

	<description>Pruebas de marshalling/unmarshalling con Castor XML. Integración con Spring OXM.</description>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.build.mainClass>com.danielme.blog.castorxml.pruebas42.Main</project.build.mainClass>
	</properties>

	<licenses>
		<license>
			<name>El presente proyecto Maven es el código de ejemplo utilizado en el tutorial    "Introducción a Castor XML", publicado con licencia Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0  Unported en la web 	
      "http://danielme.com"</name>
		</license>
	</licenses>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-jar-plugin</artifactId>
					<version>2.3.2</version>
					<configuration>
						<archive>
							<manifest>
								<addClasspath>true</addClasspath>
								<mainClass>${project.build.mainClass}</mainClass>
							</manifest>
						</archive>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.3.2</version>
					<configuration>
						<source>1.5</source>
						<target>1.5</target>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.codehaus.mojo</groupId>
					<artifactId>exec-maven-plugin</artifactId>
					<version>1.2.1</version>
					<executions>
						<execution>
							<goals>
								<goal>java</goal>
							</goals>
						</execution>
					</executions>
					<configuration>
						<mainClass>${project.build.mainClass}</mainClass>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.codehaus.castor</groupId>
			<artifactId>castor-xml</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-oxm</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>

	</dependencies>

</project>

En esta ocasión, gracias  Spring OXM, el  springcontext.xml no puede ser más sencillo, ya que tan sólo hay que definir un bean:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema beans/spring-beans.xsd">	
	
    <bean id="castorXML" class="org.springframework.oxm.castor.CastorMarshaller" >
        <property name="mappingLocation" value="classpath:mappings/mapping.xml" />
    </bean>

</beans>

Este bean es una clase hija de org.springframework.oxm.support.AbstractMarshaller que a su vez implementa las interfaces org.springframework.oxm.Marshaller y org.springframework.oxm.Unmarshaller . Puesto que en la clase Main se va a realizar tanto el marshalling como el unmarshalling, utilizaremos por comodidad AbstractMarshaller:

public static void main(String[] args) 
{
	String fichero = "exportacionEquipo.xml";
	SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

	//Se inicia programáticamente el contenedor de Spring y se obtiene el bean
  	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/springcontext.xml");
  	AbstractMarshaller springOXM = (AbstractMarshaller) applicationContext.getBean("castorXML");
		
	Equipo equipo = equipoDePrueba();
	try
	{
		FileWriter writer = new FileWriter(fichero);

		//llamada al marshaller
  		springOXM.marshal(equipo, new StreamResult(writer));	
			
		FileReader fileReader = new FileReader(fichero);

		//llamada al unmarshaller
  		Equipo unmarshal = (Equipo) springOXM.unmarshal(new StreamSource(fileReader));

		System.out.println("EQUIPO : " + unmarshal.getNombre());
		System.out.println("entrenador: " + unmarshal.getEntrenador().getNombre() + " "
					+ unmarshal.getEntrenador().getApellidos());
		System.out.println("jugadores  ");

		for (Jugador jugador: unmarshal.getJugadores())
		{
			StringBuffer sb = new StringBuffer("            " + jugador.getDorsal() + ": " + jugador.getNombre() + " " + jugador.getApellidos());
			if (jugador.getFechaNacimiento() != null)
			{
				sb.append(" ( " + sdf.format(jugador.getFechaNacimiento().getTime()) + " ) ");
			}
			System.out.println(sb);
		}
	}
	catch (IOException e1)
	{
		e1.printStackTrace();
	}	

}

Obsérvese que en nuestro código no hay referencia alguna a Castor XML, y que la configuración del mismo (o de cualquier otro mapeador de los soportados), se realiza integramente en Spring.

Conclusiones

A lo largo de estos cuatro artículos he tratado de exponer de forma práctica las posibilidades que Castor XML nos brinda para trabajar con XML en nuestro código Java, y espero que mi trabajo haya servido para que el lector pueda empezar a utilizar  este framework. No obstante, aprovecho para recordar que los frameworks mapeadores de XML tienen un coste en lo que respecta al rendimiento, por lo que en entornos donde se requiera un uso intensivo de XML es necesario evaluar seriamente si nos podemos «permitir el lujo» de utilizarlos o bien tendremos que implementar directamente lo que necesitemos con JDOM o SAX.

 

Código de ejemplo

Descargar desde WordPress.comWordPress: debido a las limitaciones del servicio ofrecido por WordPress.com, el código de ejemplo está comprimido en formato zip pero con la extensión «.odt», por lo que hay que cambiar la extensión a «.zip» del fichero descargado o abrirlo directamente con el software adecuado.

Un comentario sobre “Tutorial Castor XML (y IV): Integración con Spring

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.