La soledad humana no es más que temor a la vida
Calavera, de Las macabras aventuras de Billy y Mandy

Spring, Struts 1.3.8, JDBC y MySQL

Vaya combinación, ya se va complicando el tema. Ahora que ya tenemos un servidor de base de datos MySQL disponible, queremos utilizarlo en nuestros proyectos web. Para ello partiremos del proyecto que ya hemos desarrollado integrando Spring con Struts 1.3.8, al que añadiremos una capa de persistencia utilizando JDBC (Java DataBase Connectivity).

Diseño

A la hora del diseño, vamos a desarrollar varias capas de persistencia y a la hora de desplegar nuestro proyecto utlizaremos la que más nos convenga.

  • Una primera capa de cartón piedra (es más profesional utilizar los términos mock o fake), es decir con los datos a fuego, que es como estaba en el ejemplo. Se utliza profesionalmente más de lo que parece porque resulta frecuente empezar el desarrollo sin disponer de una base de datos (por problemas de conectividad, licencias…) o desarrollando en paralelo con otro equipo que se encargue de la base de datos.
  • En este ejemplo utlizaremos una para MySQL con JDBC.
  • Más adelante utlizaremos para MySQL el framework iBATIS.
  • Y más adelante aún utlizaremos para MySQL el framework Hibernate.

Creamos los nuevos paquetes :

  • es > lycka > holamundo > persistencia > impl > cartonpiedra
  • es > lycka > holamundo > persistencia > impl > mysql > jdbc
  • es > lycka > holamundo > persistencia > impl > mysql > ibatis
  • es > lycka > holamundo > persistencia > impl > mysql > hibernate

Movemos las clases que ya teníamos (BaseDAOImpl y IdentificarDAOImpl) al paquete cartonpiedra. Creamos dos nuevas clases en el paquete jdbc, BaseDAOImpl y IdentificarDAOImpl (que extienda del nuevo BaseDAOImpl e implemente el interfaz IdentificarDAO). A la izquierda se ve la estructura que quedaría.

Conector MySQL

Descargamos el conector MySQL de la página de sun aquí, e importamos el jar (mysql-connector-java.jar) en nuestro proyecto.

Obtener una conexión

Creamos un nuevo método en nuestro nuevo BaseDAOImpl, establecerConexion.

protected Connection establecerConexion (String URL, String usuario, String contrasenna) throws Exception {

Connection conn = null;

try {

Class.forName(“com.mysql.jdbc.Driver”);

conn = DriverManager.getConnection (URL, usuario, contrasenna);

log.info(“establecerConexion – INFO – Conexión Establecida con\n -> URL = “ + URL + “\n -> USUARIO = “ + usuario);

} catch (Exception e) {

log.error(“establecerConexion – ERROR – Conexión no Establecida con “ + URL);

throw e;

}

return conn;

}

Cerrar una conexión

Creamos un nuevo método también en el nuevo BaseDAOImpl, cerrarConexión.

protected void cerrarConexión (Connection conn, String URL) {

try {

if (conn != null) {

conn.close();

log.info(“cerrarConexión – INFO – Conexión cerrada con “ + URL);

}

} catch (Exception e) {

log.error(“cerrarConexión – WARNING – No se puede cerrar la conexión con “ + URL);

e.printStackTrace();

}

}

Utilizar la conexión

En este ejemplo simple crearemos una conexión en cada petición, ejecutaremos la consulta y cerraremos la conexión. Profesionalmente se debería de utilizar un pool de conexiones, lo dejaré para otra entrada.

package es.lycka.holamundo.persistencia.impl.mysql.jdbc;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import es.lycka.holamundo.model.Usuario;

import es.lycka.holamundo.persistencia.IdentificarDAO;

public class IdentificarDAOImpl extends BaseDAOImpl implements IdentificarDAO {

public Usuario consultarUsuario (Usuario usuario) throws Exception {

String URLBBDD = “jdbc:mysql://localhost/holamundo”;

String usuarioBBDD = “root”;

String contrasennaBBDD = “superfeo”;

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

String query = “SELECT IDENTIFICADOR, CONTRASENNA “ +

“FROM USUARIO “ +

“WHERE IDENTIFICADOR = ? AND CONTRASENNA = ?”;

Usuario resultado = null;

try {

conn = establecerConexion (URLBBDD, usuarioBBDD, contrasennaBBDD);

ps = conn.prepareStatement(query);

ps.setString ( 1, usuario.getIdentificador());

ps.setString ( 2, usuario.getContrasenna());

rs = ps.executeQuery();

while ( rs.next() ) {

resultado = new Usuario ();

resultado.setIdentificador(rs.getString(“IDENTIFICADOR”));

resultado.setContrasenna(rs.getString(“CONTRASENNA”));

}

rs.close();

} catch (Exception e) {

throw e;

} finally {

cerrarConexión(conn, URLBBDD);

}

return resultado;

}

}

Acoplar la nueva implementación

Configuramos el fichero para inyectar los nuevos beans applicationContext-persistencia.xml:

<beans>

<bean id=“dao” class=“es.lycka.holamundo.persistencia.impl.mysql.jdbc.BaseDAOImpl” abstract=“true” />

<bean id=“identificarDAO” class=“es.lycka.holamundo.persistencia.impl.mysql.jdbc.IdentificarDAOImpl” parent=“dao”/>

</beans>

Para saber más

Integrar Struts con Spring – holamundoStruts138Spring

Integrar Struts con Spring - holamundoStruts138SpringVamos al turrón, vamos a implementar lo que hemos visto a nivel teórico.

Creamos un nuevo proyecto web dinámico, holamundoStruts138Spring. Copiamos todo lo que tenemos en holamundoStruts138 sobre este nuevo proyecto para no partir de cero.

Básicamente sobreescribermos el controlador de Struts y utilizaremos la configuración de Spring para inyectar las dependencias a nuestros objetos.

LyckaRequestProcessor

package es.lycka.holamundoStruts138.action;

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.action.RequestProcessor;

import org.apache.struts.config.ModuleConfig;

import org.apache.struts.util.RequestUtils;

import org.springframework.web.context.WebApplicationContext;

import org.springframework.web.struts.DelegatingActionUtils;

public class LyckaRequestProcessor extends RequestProcessor{

      private WebApplicationContext webApplicationContext;

      public void init(ActionServlet actionServlet, ModuleConfig moduleConfig) throws ServletException {

            super.init(actionServlet, moduleConfig);

            if (actionServlet != null) {

                  this.webApplicationContext = initWebApplicationContext(actionServlet, moduleConfig);

            }

      }

      protected WebApplicationContext initWebApplicationContext(

                  ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {

            return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig);

      }

      protected final WebApplicationContext getWebApplicationContext() {

            return webApplicationContext;

      }

      /**

       * Método que sobreescribimos para utilizar beans de Spring.

       */

      protected Action processActionCreate(HttpServletRequest request,

                  HttpServletResponse response, ActionMapping mapping)

                  throws IOException {

            // Acquire the Action instance we will be using (if there is one)

            String className = mapping.getType();

            if (log.isDebugEnabled()) {

                  log.debug(" Looking for Action instance for class " + className);

            }

            // If there were a mapping property indicating whether

            // an Action were a singleton or not ([true]),

            // could we just instantiate and return a new instance here?

            Action instance;

            //Acceso sincronizado al HasMaps de actions

            synchronized (actions) {

                  // Return any existing Action instance of this class

                  instance = (Action) actions.get(className);

                  if (instance != null) {

                        if (log.isTraceEnabled()) {

                             log.trace("  Returning existing Action instance");

                        }

                        return (instance);

                  }

                  // Create and return a new Action instance

                  if (log.isTraceEnabled()) {

                        log.trace("  Creating new Action instance");

                  }

                  try {

                        //String beanName = determineActionBeanName(mapping);

                        String beanName = mapping.getType();

                        if (getWebApplicationContext().containsBean(beanName))

                             instance = (Action)getWebApplicationContext().getBean(beanName, Action.class);                           

                        else

                             instance = (Action) RequestUtils.applicationInstance(className);

                        // Maybe we should propagate this exception

                        // instead of returning null.

                  } catch (Exception e) {

                        log.error(getInternal().getMessage("actionCreate",

                                   mapping.getPath()), e);

                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,

                                   getInternal().getMessage("actionCreate", mapping.getPath()));

                        return (null);

                  }

                  actions.put(className, instance);

            }

            if (instance.getServlet() == null) {

                  instance.setServlet(this.servlet);

            }

            return (instance);

      }

}

Para que funcione correctamente además de las librerías de Struts que ya tenemos importadas, debemos utilizar spring.jar y spring-struts.jar.

Bases, Interfaces e Implementaciones

Ya aprovechamos que vamos a utilizar Spring para desdoblar nuestras clases en una clase Base por cada capa, y para cada clase utilizaremos un interfaz y una implementación.

Para no poner todas las implementaciones, que ya bastante larga va a quedar la entrada, sólo transcribo la implementación de IdentificarBOImpl. Sólo sería necesario el set del bean identificarDAO, pero por comodidad dejo ambas. Las demás implementaciones serían similares.

package es.lycka.holamundoStruts138Spring.negocio.impl;

import es.lycka.holamundoStruts138Spring.model.Usuario;

import es.lycka.holamundoStruts138Spring.negocio.IdentificarBO;

import es.lycka.holamundoStruts138Spring.persistencia.IdentificarDAO;

public class IdentificarBOImpl extends BaseBOImpl implements IdentificarBO  {

      private IdentificarDAO identificarDAO;

      public boolean esUsuarioAutorizado (Usuario usuario) throws Exception {

            boolean esAutorizado               = false;

            try {

                  if (identificarDAO.consultarUsuario (usuario) != null ) {

                        esAutorizado = true;

                  }

            } catch (Exception e) {

                  throw e;

            }

            return esAutorizado;

      }

      public IdentificarDAO getIdentificarDAO() {

            return identificarDAO;

      }

      public void setIdentificarDAO(IdentificarDAO identificarDAO) {

            this.identificarDAO = identificarDAO;

      }

}

web.xml

Vale, ahora debemos modificar el web.xml para utilizar también Spring.

<context-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>

            /WEB-INF/spring/applicationContext-*.xml

      </param-value>

</context-param>

<listener>

      <listener-class>

            org.springframework.web.context.ContextLoaderListener

      </listener-class>

</listener> 

Así, podemos crear varios archivos XML para configurar nuestra aplicación:

  • applicationContext-struts.xml, que contendrá los beans que representan a nuestras Acciones de Struts.
  • applicationContext-negocio.xml, que contendrá los beans que representan a nuestros objetos de la capa de negocio.
  • applicationContext-persistencia.xml, que contendrá los beans que representan a nuestros objetos de la capa de persistencia. Meteremos iBATIS en otro ejemplo.

applicationContext-struts.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

      "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

      <bean name="parentAction" class="es.lycka.holamundoStruts138Spring.control.action.AppBaseAction" abstract="true" />

      <bean name="es.lycka.holamundoStruts138Spring.control.action.IdentificarAction" class="es.lycka.holamundoStruts138Spring.control.action.IdentificarAction" singleton="false" parent="parentAction">

            <property name="identificarBO"><ref bean="identificarBO" /></property>

      </bean>

</beans>

applicationContext-negocio.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

      "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

      <bean name="baseBO" class="es.lycka.holamundoStruts138Spring.negocio.impl.BaseBOImpl" abstract="true"/>

      <bean id="identificarBO" class="es.lycka.holamundoStruts138Spring.negocio.impl.IdentificarBOImpl"  parent="baseBO">

            <property name="identificarDAO" ref="identificarDAO" />

      </bean>

</beans>

applicationContext-persistencia.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

      "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

      <bean id="dao" class="es.lycka.holamundoStruts138Spring.persistencia.impl.BaseDAOImpl" abstract="true" />

      <bean id="identificarDAO" class="es.lycka.holamundoStruts138Spring.persistencia.impl.IdentificarDAOImpl" parent="dao"/>

</beans>

struts-config.xml

Debemos declarar como controlador nuestra nueva clase es.lycka.holamundoStruts138Spring.action.LyckaRequestProcessor

<controller>

      <set-property property="processorClass"

      value="es.lycka.holamundoStruts138Spring.action.LyckaRequestProcessor" />

</controller>

Probamos y … bene !

Integrar Struts con Spring – Teoría

Bueno, ya tenemos un proyecto con Spring – MVC (holamundo) y otro con Struts (holamundoStruts138). Cuál utilizaremos para desarrollar ? Eso lo dejo para otra discusión.

Aquí quiero señalar que existe otra solución, y es integrar Struts con Spring, es decir, utilizar Struts aprovechando sus puntos fuertes como MVC (madurez, documentación, podemos extender el framework con Struts-Validator y Tiles…) y Spring aprovechando también sus puntos fuertes (como AOP, IoC, DI…).

El framework de Struts realiza una serie de operaciones transparentes para el desarrollador para facilitarle la vida. Entre ellas mantiene un HashMap que contiene referencias a objetos Action ya instanciados. Ante cada petición mira primero este HashMap para ver si contiene la clase Action solicitada. Si es así recupera el objeto a partir de la referencia almacenada en el HashMap; y si no instancia e inicializa la clase Action y guarda su referencia en el HashMap.

Al manejar una única instancia de cada Action se ahorra bastante tiempo y el rendimiento de la aplicación mejora notablemente, pero este mecanismo podría ser más eficiente, ya que cada Action invoca a uno o varios objetos de negocio que con Struts se deben instanciar e inicializar en cada llamada.

La integración con Spring perfecciona este mecanismo aprovechando IoC y DI. Las clases Action de Struts pasan a ser beans gestionados en el contexto de Spring, y permitiendo que Spring aplique IoC y DI también a los Action de Struts conseguimos que las instancias de estas clases Action ya tengan inyectadas (instanciados e inicializados) los objetos de negocio, mejorando considerablemente el rendimiento de nuestra aplicación: al levantar la aplicación será un poco lenta pero después irá como un tiro.

Pues manos a la obra. Debemos declarar un bean en el contexto de Spring que represente nuestro Action para que sea Spring quien le instancie y le inyecte sus dependencias (los objetos de negocio).

Donde gestiona Struts la creación de sus clases Action ? En el método

processActionCreate de su controlador,

RequestProcessor.

Vale, pues sobre escribamos esta clase con nuestro propio controlador,

AppRequestProcessor, para que pida la instancia del bean al contexto de Spring (la rama true del if). Si existe la instancia será la que manejemos; sino existe la crearemos como se hacía con Struts (la rama del else). Lo que está en negrita es la clave, sólo un if.

Si queremos utilizar Tiles debemos extender de

TilesRequestProcessor.

public class AppRequestProcessor extends RequestProcessor {

. . .

protected Action processActionCreate(HttpServletRequest request,

HttpServletResponse response, ActionMapping mapping)

throws IOException {

// Acquire the Action instance we will be using (if there is one)

String className = mapping.getType();

if (log.isDebugEnabled()) {

log.debug(” Looking for Action instance for class “ + className);

}

// If there were a mapping property indicating whether

// an Action were a singleton or not ([true]),

// could we just instantiate and return a new instance here?

Action instance;

//Acceso sincronizado al HasMaps de actions

synchronized (actions) {

// Return any existing Action instance of this class

instance = (Action) actions.get(className);

if (instance != null) {

if (log.isTraceEnabled()) {

log.trace( Returning existing Action instance”);

}

return (instance);

}

// Create and return a new Action instance

if (log.isTraceEnabled()) {

log.trace( Creating new Action instance”);

}

try {

//String beanName = determineActionBeanName(mapping);

String beanName = mapping.getType();

if (getWebApplicationContext().containsBean(beanName))

instance = (Action)getWebApplicationContext().getBean(beanName, Action.class);

else

instance = (Action) RequestUtils.applicationInstance(className);

// Maybe we should propagate this exception

// instead of returning null.

} catch (Exception e) {

log.error(getInternal().getMessage(“actionCreate”,

mapping.getPath()), e);

response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,

getInternal().getMessage(“actionCreate”, mapping.getPath()));

return (null);

}

actions.put(className, instance);

}

if (instance.getServlet() == null) {

instance.setServlet(this.servlet);

}

return (instance);

}

. . .

}

Es decir, buscamos si el nombre del bean (beanName) existe en el contexto de Spring, y si es así lo obtenemos de ahí. Para que funcione debemos utilizar como nombre del bean que representa la clase Action en el contexto de Spring un nombre que Struts pueda obtener, por ejemplo:

  • El nombre lo podemos obtener de la ruta (path) mediante determineActionBeanName(mapping), el método que está comentado en este ejemplo.
  • O bien lo podemos obtener como se muestra en el ejemplo del “type” del mapping, es decir el nombre de la clase Action.

En el contexto de Spring debemos declarar nuestros actions, utilizando como nomenclatura para sus nombres una de las dos opciones anteriormente propuestas. En el primer caso el nombre del bean será la ruta introducida en el navegador : “/editarDatos” y “/guardarDatos”. Ojo, porque en este caso que todos los beans del mismo action deben declarar los mismos BO’s porque la instancia que se almacenará será la que se instancia primero, es decir por la primera ruta a la que se acceda, por lo cual hay que tener ojo al utilizar wildcards.

<bean name=“parentAction” class=“es.xxx.xxx.control.action.base.AppBaseAction” abstract=“true” />

<bean name=/editarDatosclass=“es.xxx.xxx.control.action.DatosAction” singleton=“false” parent=“parentAction”>

<property name=“datosBO”><ref bean=“datosBO” /></property>

</bean>

<bean name=/guardarDatosclass=“es.xxx.xxx.control.action.DatosAction” singleton=“false” parent=“parentAction”>

<property name=“datosBO”><ref bean=“datosBO” /></property>

</bean>

<bean name=“/validarDatos” class=“es.xxx.xxx.control.action.DatosAction” singleton=“false” parent=“parentAction”>

<property name=“datosBO”><ref bean=“datosBO” /></property>

</bean>

En el segundo caso el nombre del bean debe ser el “tipo” del action, es decir “es.xxx.xxx.control.action.DatosAction”.

<bean name=“parentAction” class=“es.xxx.xxx.control.action.base.AppBaseAction” abstract=“true” />

<bean name=“es.xxx.xxx.control.action.DatosAction” class=“es.xxx.xxx.control.action.DatosAction” singleton=“false” parent=“parentAction”>

<property name=“datosBO”><ref bean=“datosBO” /></property>

</bean>

En ambos casos se apoyarían sobre un bean de negocio

<bean name=“baseBO” class=“es.xxx.xxx.negocio.base.BaseBOImpl” abstract=“true”/>

<bean id=“datosBO” class=“es.xxx.xxx.negocio.impl.DatosBOImpl” parent=“baseBO”>

<property name=“datosDAO” ref=“datosDAO” />

</bean>

que se apoya sobre otro de persistencia

<!– SqlMap setup for iBATIS Database Layer –>

<bean id=“sqlMapClient” class=“org.springframework.orm.ibatis.SqlMapClientFactoryBean”>

<property name=“configLocation”>

<value>classpath:/es/xxx/xxx/persistencia/impl/xml/sql-map-config.xml</value>

</property>

<property name=“dataSource” ref=“dataSource”/>

</bean>

<!– Generic Dao – can be used when doing standard CRUD –>

<bean id=“dao” class=“es.xxx.xxx.persistencia.base.BaseDaoImpl” abstract=“true”>

<property name=“sqlMapClient” ref=“sqlMapClient”/>

</bean>

<bean id=“datosDAO” class=“es.xxx.xxx.persistencia.impl.DatosProyectoDAOImpl” parent=“dao”/>

Qué fácil, una vez que se sabe ! :)

Spring AOP : Primeros pasos

La Programación Orientada a Aspectos (POA en español, AOP en inglés) es un concepto relativamente antiguo, y que ha tenido un éxito relativamente discreto.

Proyecto holamundoAOPBásicamente consiste en implementar por un lado un aspecto, que es un trozo de código común a ejecutar en varios métodos / clases. Por otro lado configuraremos los puntos de cruce, que son los lugares en los que el aspecto cruza con el código, es decir, cuando serán ejecutados. Para que funcione debemos interponer un Proxy entre la clase y el aspecto. De esta forma podemos acoplar / desacoplar aspectos comunes sin tocar código.

Existen varias implementaciones como AspectJ (AspectJ Programming Guide) o Spring AOP (Aspect Oriented Programming in Java with Spring Framework), y desgraciadamente no he encontrado mucha documentación fiable y moderna al respecto, además de que la terminología ha evolucionado estos últimos años.

En esta entrada construiremos un aspecto muy sencillo para aplicarlo a todos los objetos de negocio. El aspecto auditará el tiempo que tarda en ejecutarse cualquier método de la capa de negocio.

holamundoAOP

Partiremos del anterior proyecto, holamundoBO. Creamos un nuevo proyecto web dinámico, holamundoAOP, e introducimos las librerías de Spring, la configuración en el web.xml, los jsps, las clases que hemos definido y configuramos holamundoAOP-servlet.xml. Comprobamos que funciona todo correctamente.

Implementación del aspecto

Ahora podemos implementar un aspecto, en nuestro ejemplo utilizaremos una clase es.lycka.holamundoAOP.aspectos.AuditoriaInterceptor.

package es.lycka.holamundoAOP.aspectos;

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

public class AuditoriaInterceptor implements MethodInterceptor {

      public Object invoke(MethodInvocation method) throws Throwable {

            long start = System.currentTimeMillis();

            try {

                  Object result = method.proceed();

                  return result;

            }finally {

                  long end = System.currentTimeMillis();

                  long timeMs = end – start;

                  System.out.println("Method: " + method.toString() + " took: " + timeMs +"ms.");

            }

      }

}

Configuración de AOP

Primeros declaramos el bean que identifica al aspecto:

<bean name="auditoriaInterceptor" class="es.lycka.holamundoAOP.aspectos.AuditoriaInterceptor" />

Y ahora declaramos el proxy y lo configuramos para interceptar las llamadas a los métodos de negocio, que serán atendidas por nuestro aspecto.

<bean id="autoProxyCreator"         class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

      <property name="interceptorNames">

            <value>auditoriaInterceptor</value>

      </property>

      <property name="beanNames">

            <value>*BO</value>

      </property>

</bean>

Reiniciamos, et voilá, ya lo tenemos. Volvemos a introducir el path "holamundoAOP/holamundo.lycka" y ahora el método es interceptado y el aspecto ejecutado. Simple y bello.

Spring – MVC : Capa de negocio

Avancemos un poco más en nuestros conocimientos básicos de Spring – MVC. Vamos a extraer el negocio de nuestras clases controlers y vamos a llevarlos a nuevas clases de la capa de negocio.

holamundoBO

Proyecto holamundoBOBueno, repasemos los primeros pasos de Spring – MVC. Si necesitas ayuda mira la chuleta de la entrada anterior, sobre el proyecto holamundo con Spring – MVC.

Creemos un nuevo proyecto web dinámico, holamundoBO. Importamos las librerías necesarias, configuramos el web.xml para que utilice Spring al recibir extensiones ".lycka". Creemos nuestra clase controller, es.lycka.holamundoBO.control.HolaMundoController y la implementamos como hicimos en el tutorial anterior. Nos resta configurar el fichero xml de configuración de la servlet de spring, holamundoBO-servlet.xml para que mapee el path /holamundo.lycka al controlador que acabamos de crear.

Podemos utilizar las mismas jsp's que en el proyecto de holamundo, index.jsp y jsp/holamundo.jsp.

Desplegamos la aplicación en el servidor y comprobamos que se ven correctamente la ruta /holamundo.lycka.

Extraer el negocio

En nuestro caso el negocio es muy simple, es únicamente una sentencia. Habitualmente sabemos que no es así.

(new Date()).toString()

Para ello crearemos un interfaz, es.lycka.holamundoBO.negocio.HolaMundoBO, y lo implementaremos en la clase es.lycka.holamundo.negocio.impl.HolaMundoBOImpl.

package es.lycka.holamundoBO.negocio;

public interface HolaMundoBO {

      public String getHoraActual ();

} 

y

package es.lycka.holamundoBO.negocio.impl;

import java.util.Date;

import es.lycka.holamundo.negocio.HolaMundoBO;

public class HolaMundoBOImpl implements HolaMundoBO {

      public String getHoraActual () {

            return (new Date()).toString();

      }

}

Configurar Spring

Vale, ahora vamos a sacar uso de la Inyección de Dependencias de Spring.

Creamos una variable privada en el controller del tipo HolaMundoBO, y un método set para esta variable. Utilizamos el método de negocio de esta variable, getHoraActual ().

private HolaMundoBO holaMundoBO;

public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

      throws ServletException, IOException {

      String ahora = holaMundoBO.getHoraActual();

      logger.info("Se dirige a la vista holamundo con ahora = " + ahora);

      return new ModelAndView("holamundo", "ahora", ahora);

}

public void setHolaMundoBO(HolaMundoBO holaMundoBO) {

      this.holaMundoBO = holaMundoBO;

}

Ahora declaramos el bean en el archivo de configuración de Spring, holamundoBO-servlet.xml.

<bean id="HolaMundoBO" class="es.lycka.holamundoBO.negocio.impl.HolaMundoBOImpl" />

Y ahora le inyectamos el bean de negocio al controlador… cómo ? declaramos una nueva propiedad en el bean del controller para inyectarle este método de negocio.

<bean name="/holamundo.lycka" class="es.lycka.holamundoBO.control.HolaMundoController" >

      <property name="holaMundoBO"       ref="HolaMundoBO" />

</bean> 

Probamos el códgio, et voilá, funciona ! Ya tenemos nuestra capa de negocio en un proyecto de Spring.

Comenta