Ajax Tags
hpfloresj@gmail.com
http://hpfloresj.blogspot.com
Fecha: 14-12-2008
Introduccion
Ajax Tags es una biblioteca de etiquetas JSP que nos simplifican el uso de AJAX.
Esta biblioteca no necesita forzar al desarrollador J2EE a escribir codigo javascript para implementar una capacidad Ajax en un formulario web.
Esta libreria proporciona soporte para los siguientes casos:
- Autocomplete
- Callout
- HTML Content replace
- Select/Dropdown
- Tab Panel
- Update field
- Area y Anchor
- Ajax DisplayTag
- Editor
- Tree
- Fácil de usar.
- Puede extender funcionalidades de manera facil con funciones post y pre condiciones
- Moderadamento dificultoso extender core tags
- Soporte y actualizaciones inciertos.
Recordaremos utilizar bibliotecas de etiquetas que ya vimos también.
Integrando AjaxTags en su aplicación caso: Select/Dropdown
Requerimientos
- JDK 1.5+
- Servlet container running Servlets 2.4+ and JSP 2.0+
- AjaxTags dependencies
- Maven 2 (Si usted intenta construir desde el codigo)
- Descargar y descomprimir la ultima version de AjaxTags, nosotros trabajaremos con la version ajaxtags-1.3-beta-rc7-bin.zip que pueden descargar desde aqui, ademas de los ejemplos.
- Descargarse Prototype JavaScript framework, version 1.5.0 y copiarlos a una carpeta script de nuestro proyecto.
- Descargarse script.aculo.us scriptaculous.js v1.7.0 y copiarlos a una carpeta script de nuestro proyecto.
- Para la configuracion seguiremos los pasos vistos en item "Usando una biblioteca de etiquetas en su aplicación" del artículo Tag Libreries
Copiar el fichero ajaxtags-1.3-beta-rc7.jar al directorio WEB-INF/lib
- Copiar el fichero ajaxtags.tld al directorio WEB-INF/
- Agregar al descriptor de despliegue /WEB-INF/web.xml la siguiente entrada:
<taglib>
<uri>http://ajaxtags.org/tags/ajax</uri>
<location>/WEB-INF/ajaxtags.tld</location>
</taglib>
Esto ya no es necesario para contenedores de Servlets 2.4
Librerias jar dependientes que hay que tener en cuenta para poder hacer correr bien nuestros programas que utilicen AjaxTags:
* Librerias comunes(obligatorias)
ajaxtags-1.3-beta-rc7.jar
commons-beanutils-1.7.0.jar
commons-lang-2.3.jar
commons-logging-1.1.1.jar
// servelts
jsp-api-2.0.jar
servlet-api-2.4.jar
//taglibs
standard.jar
jstl.jar
* Librerias comunes(opcionales segun requerimeinto)
commons-collections-3.2.jar
jericho-html-2.4.jar
displaytag-1.1.jar
displaytag-export-poi-1.1.jar
displaytag-portlet-1.1.jar
itext-2.0.4.jar
poi-scratchpad-3.0-rc4-20070503.jar
poi-3.0-rc4-20070503.jar
poi-contrib-3.0-rc4-20070503.jar
ajaxtags-1.3-beta-rc7.jar
commons-beanutils-1.7.0.jar
commons-lang-2.3.jar
commons-logging-1.1.1.jar
// servelts
jsp-api-2.0.jar
servlet-api-2.4.jar
//taglibs
standard.jar
jstl.jar
* Librerias comunes(opcionales segun requerimeinto)
commons-collections-3.2.jar
jericho-html-2.4.jar
displaytag-1.1.jar
displaytag-export-poi-1.1.jar
displaytag-portlet-1.1.jar
itext-2.0.4.jar
poi-scratchpad-3.0-rc4-20070503.jar
poi-3.0-rc4-20070503.jar
poi-contrib-3.0-rc4-20070503.jar
Lo mejor para no tener problemas es copiar los ficheros jar que vienen en ajaxtags-1.3-beta-rc7-bin.zip dentro de lib.
- Es necesario tener en nuestro proyecto otros frameworks javascript que se encuentran en ajaxtags-1.3-beta-rc7-bin.zip, copiar dichos ficheros desde ajaxtags-1.3-beta-rc7\web\js a {app_name}/public/js
- Copiar desde ajaxtags-1.3-beta-rc7-bin.zip el directorio web\css a {app_name}/public/css
Creando el Servlet que devuelve una respuesta XML
AjaxTags recibe XML que tenga el siguiente formato:
<?xml version="1.0" encoding="UTF-8"?>
<ajax-response>
<response>
<item>
<name>Registro 1</name>
<value>1</value>
</item>
<item>
<name>Registro 2</name>
<value>2</value>
</item>
<item>
<name>Registro 3</name>
<value>3</value>
</item>
</response>
</ajax-response>
Esta es la respuesta del Servidor a la peticion Ajax, AjaxTags tiene la capacidad de leer este XML, además AjaxTags tambien soporta contenido HTML.Pero de donde obtenemos estos datos XML? Creando las clases y metodos necesarios desde una base de datos. Usaremos la base Recursos Humanos de PostgreSQL.
- Crearemos primero el método listEmployeesBySearchDepartment(int departmentID) de la clase Employees, metodo que lista todos los empleados segun el codigo de departamento que se le pasa. Hay que indicar que se tiene que añadir un atributo mas a esta clase del tipo Departments department, agregar los getters y setters a los constructores y al metodo find() quedando de la siguiente forma:
public Employees find( int employeeId ){
Employees objEmployees = null;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = cf.getConnection();
ps = con.prepareStatement("SELECT employee_id,first_name,last_name,email,phone_number, cast(to_char(hire_date,'DD-MM-YYYY') as character varying),job_id,salary,commission_pct,manager_id,department_id FROM employees WHERE employee_id = ?" );
ps.setInt( 1, employeeId );
rs = ps.executeQuery();
if( rs.next() ){
objEmployees = new Employees( rs.getInt(1),
rs.getString(2),
rs.getString(3),
rs.getString(4),
rs.getString(5),
rs.getString(6),
rs.getString(7),
rs.getInt(8),
rs.getDouble(9),
rs.getInt(10),
new Departments( rs.getInt(11), "" )
);
}
}catch( SQLException sqle ){
sqle.printStackTrace();
}finally{
ConnectionFactory.closeAllConnections(con, ps, rs);
}
return objEmployees;
}
Veamos como se implementa el metodo listEmployeesBySearchDepartment().
public List<Employees> listEmployeesBySearchDepartment( int departmentId ){
List<Employees> listEmployees = null;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = cf.getConnection();
ps = con.prepareStatement("select employee_id, first_name, last_name from employees where department_id = ? ");
ps.setInt( 1, departmentId );
rs = ps.executeQuery();
if( rs != null ) listEmployees = new ArrayList<Employees>();
while( rs.next() ){
listEmployees.add( new Employees( rs.getInt(1),
rs.getString(2),
rs.getString(3),
"",
"",
"",
"",
0,
0.0,
0,
null )
);
}
}catch( SQLException sqle ){
sqle.printStackTrace();
}finally{
ConnectionFactory.closeAllConnections(con, ps, rs);
}
return listEmployees;
}
- Ahora implementaremos la clase Departments, con su metodo listDepartments(),que lista todos los departamentos de la empresa.
package dominio;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import com.hpfloresj.util.Keyboard;
import com.hpfloresj.persistencia.ConnectionFactory;
import com.hpfloresj.persistencia.DAOFactory;
import com.hpfloresj.persistencia.ConfigDatabase;
import com.hpfloresj.persistencia.TypeDB;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Hugo
*/
public class Departments {
private int departmentId;
private String name;
private ConnectionFactory cf;
public Departments( ConfigDatabase conf ){
cf = DAOFactory.create( conf );
}
public Departments( int departmentId, String name ){
setDepartmentId(departmentId);
setName(name);
}
public List<Departments> listDepartments(){
List<Departments> listDepartments = null;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = cf.getConnection();
ps = con.prepareStatement("select department_id, department_name from departments");
rs = ps.executeQuery();
if( rs != null ) listDepartments = new ArrayList<Departments>();
while( rs.next() ){
listDepartments.add( new Departments( rs.getInt(1),
rs.getString(2) )
);
}
}catch( SQLException sqle ){
sqle.printStackTrace();
}finally{
ConnectionFactory.closeAllConnections(con, ps, rs);
}
return listDepartments;
}
/**
* @return the departmentId
*/
public int getDepartmentId() {
return departmentId;
}
/**
* @param departmentId the departmentId to set
*/
public void setDepartmentId(int departmentId) {
this.departmentId = departmentId;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
Bien ahora que tenemos los métodos veamos como podemos contruir nuestro Servlet, pero con AjaxTags:
package servlets;
import com.hpfloresj.persistencia.ConfigDatabase;
import com.hpfloresj.persistencia.TypeDB;
import dominio.Employees;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ajaxtags.servlets.BaseAjaxServlet;
import org.ajaxtags.xml.AjaxXmlBuilder;
/**
*
* @author Hugo
*/
public class DropSelectAjax extends BaseAjaxServlet {
public String getXmlContent( HttpServletRequest request, HttpServletResponse response )
throws Exception
{
int departmentId = 0;
ConfigDatabase conf = new ConfigDatabase("127.0.0.1", "hr",5432,
TypeDB.POSTGRE,
"postgres",
"admin");
try{
departmentId = Integer.parseInt( request.getParameter("id") );
}catch( NumberFormatException nfe ){
System.out.println( nfe.getMessage() );
}
Employees objEmployees = new Employees( conf );
List<Employees> lista = objEmployees.listEmployeesBySearchDepartment( departmentId );
AjaxXmlBuilder xml = new AjaxXmlBuilder();
for( Employees item : lista ){
xml.addItem( item.getFirstName()+ " " + item.getLastName(),String.valueOf( item.getEmployeeId() ) );
}
//xml.addItems(lista,"producto", "id");
System.out.println(xml.toString() + " -- ");
return xml.toString();
}
}
Añadimos el Servlet al descriptor de despliegue:
<servlet>
<servlet-name>DropSelectAjax</servlet-name>
<servlet-class>servlets.DropSelectAjax</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DropSelectAjax</servlet-name>
<url-pattern>/DropSelectAjax</url-pattern>
</servlet-mapping>
Si compilamos y ejecutamos el Servlet: http://localhost:8084/ajaxTags/DropSelectAjax?id=80
Vista accediendo a nuestro XML mediante AjaxTags
1. Importamos las clases que utilizaremos
2. creamos un fichero selectAjax.jsp y declaramos la biblioteca de etiquetas Ajax Tags<%@page import="dominio.*" %>
<%@page import="com.hpfloresj.persistencia.*" %>
<%@page import="java.util.List" %>
<%@ taglib uri="http://ajaxtags.org/tags/ajax" prefix="ajax"%>
3. Declaramos el TLD de la biblioteca de etiquetas JSP(JavaServer Page Stantard Tag Library)
JSTL encapsula etiquetas simples que proporcionan funcionalidad comunes a muchas aplicaciones Web. JSTL trabaja con estructura de tareas,
iteraciones y condiciones, etiquetas para manipular documentos XML, internacionalizacion de etiquetas y etiquetas SQL.
Tambien proporciona un framework para integrar etiquetas personalizadas existentes con etiquetas JSTL.
JSTL 1.2 es parte de la plataforma Java EE 5.
Referencias:
- API
- Tag Library Documentacion
- Documentacion y articulos
- JSP Standard Tag Library eases Webpage development
- Descargar jstl.jar
- Descargar standard.jar
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:set var="contextPath"><%=request.getContextPath() %></c:set>
En esta ultima linea estamos declarando una variable etiqueta JSP que almacenara el contexto de nuestra aplicacion en "contextPath"
4. Importar los CSS y Javascripts
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>JSP Page</title>
<%-- IMPORTAR LIBRERIAS JAVASCRIPT --%>
<script type="text/javascript" src="${contextPath}/public/js/prototype.js"></script>
<script type="text/javascript" src="${contextPath}/public/js/scriptaculous/scriptaculous.js"></script>
<script type="text/javascript" src="${contextPath}/public/js/ajaxtags/ajaxtags.js"></script>
<script type="text/javascript" src="${contextPath}/public/js/ajaxtags/ajaxtags_parser.js"></script>
<script type="text/javascript" src="${contextPath}/public/js/ajaxtags/ajaxtags_controls.js"></script>
<%-- IMPORTAR HOJAS DE ESTILOS(OPCIONAL PARA AUTO-COMPLETES) --%>
<!--<link type="text/css" rel="stylesheet" href="{contextPath}/public/css/ajaxtags.css" />-->
<link type="text/css" rel="stylesheet" href="${contextPath}/public/css/site.css" />
</head>
5. El resto de nuestro JSP creamos nuestra etiqueta HTML Select y las etiquetas Ajax
<body>
<form action="." class="basicForm">
<fieldset>
<legend>Escoger Departamento</legend>
<label for="id">Departamento:</label>
<select id="id">
<option value="">Selecionar</option>
<%
ConfigDatabase conf = new ConfigDatabase("127.0.0.1", "hr",5432,
TypeDB.POSTGRE,
"postgres",
"admin");
Departments dep = new Departments(conf);
List<Departments> lista = dep.listDepartments();
for( Departments item : lista){
%>
<option value="<%= item.getDepartmentId() %>"><%= item.getName() %></option>
<%
}
%>
</select>
<span id="progressMsg" style="display:none;"><img alt="Indicator" src="<%=request.getContextPath()%>/public/images/indicator.gif" /> Cargando...</span>
<label for="empleados">Empleados:</label>
<select id="listaEmpleados" disabled="disabled">
<option value="">Seleccionar Empleado</option>
</select>
</fieldset>
</form>
<div id="errorMsg" style="display:none;border:1px solid #e00;background-color:#fee;padding:2px;margin-top:8px;width:300px;font:normal 12px Arial;color:#900"></div>
<script type="text/javascript">
/*
* USER DEFINED FUNCTIONS
*/
function initProgress() {
Element.show('progressMsg');
}
function resetProgress() {
// show marker emblem
//var index = $('tipo').selectedIndex;
//var automaker = $('tipo').options[index].text;
Effect.Fade('progressMsg');
}
function reportError() {
if ($('listaEmpleados').options.length == 0) {
$('errorMsg').innerHTML = "Dropdown busted!";
}
Element.show('errorMsg');
setTimeout("Effect.DropOut('errorMsg')", 2500);
}
</script>
<ajax:select
baseUrl="${contextPath}/DropSelectAjax"
source="id"
target="listaEmpleados"
parameters="id={id}"
preFunction="initProgress"
postFunction="resetProgress"
emptyOptionName="Selecionar empleado"
errorFunction="reportError"
parser="new ResponseXmlParser()"/>
</body>
</html>
Funcionamiento
En primer lugar cargamos el select que contendra un listado de todos los departamentos que existe en nuestra "empresa"
La etiqueta más importante aqui es <ajax:select />, etiqueta hace referencia al evento de seleccionar datos que estan relacionados si.
baseURL: contiene el Servlet que procesara la petición Ajax y que devuelve una respuesta en formato XML.
source: Campo Select inicial que manda la peticion Ajax
target: Campo Select donde el valor retornado mediante Ajax se mostrara.
parameters: Lista de parametos separados por coma que se pasan al Servlet.
Notar que tiene corchetes parameters = "id={id}"
Esta sintaxis tiene la siguiente forma si no utilizariamos Ajax:
http://localhost:8084/ajaxTags/DropSelectAjax?id=80
donde {id} es el identificador HTML de la etiqueta Select
preFunction: Funcion que se ejecuta antes de usar Ajax.(Mostramos un inidicar "Cargando...")
postFunction: Funcion que se ejecuta después de finalizado Ajax.(Ocultamos el mensaje indicador)
emtyOptionName: Si no existe datos mostramos un mensaje en el segundo Select
errorFunction: Funcion que nos muestra un error si en caso el Server no puede devolvernos una respuesta.
parser : Tipo de respuesta a nuestra peticion (Por defecto: ResponseHtmlParser)
Ejecutemos nuestro ejemplo:
Bien, hemos llegado al final del articulo, espero que les sea de utilidad.
Un saludo ;).
A continuacion anexo el código fuente.
Download source code
Download database example
JAR Connection Library
1 comentario:
Hola quiero felicitarte y agradecer lo has publicado, me ha servido de mucho, pero necesito molestarte...
Me puedes indicar la forma para implementar ajax en versiones anteriores del JDK 1.3 de preferencia.
Muchas gracias!!
Saludos...
Publicar un comentario