miércoles, 13 de octubre de 2010

JSF - ajaxSingle

'ajaxSingle' es un atributo de algunos componentes JSF de A4J (AJAX for JSF) de RichFaces que indica si el componente para que se aplica debe (true) o no (false) ser incluido en la lista de componentes que será procesada en el ciclo de vida de JSF.

Con este atributo se evitan fallos en la fase de validación de aquellos componentes que no nos interesa procesar en una petición AJAX. Así pues, sólo se procesan los componentes con 'ajaxSingle = true'.

JSF - a4j:region

es una etiqueta JSF de la librería A4J (AJAX for JSF) de RichFaces que sirve para especificar la parte del árbol de componentes JSF que debe ser procesada en el servidor.

Por defecto, si no se define ninguna región (es decir, si no se emplea ) se procesará toda la vista en el servidor. Así pues, es importante usar esta etiqueta si no se desea que se procese toda la página.

Por otra parte, si hay algún componente que no toma el valor introducido tras realizar una petición AJAX, deberemos incluirlo en la región que ha realizado la petición.

Java - Creación de cachés

La siguiente clase define la estructura de una caché de elementos de tipo genérico. Puede resultar muy útil cuando, por ejemplo, debemos mostrar una lista de valores obtenida de un sistema externo: base de datos, servicio web, etc.

La primera vez que se llame al método 'getItems()' para obtener el listado de elementos se realizará una llamada al método 'getNewItems()' que será el encargado de obtenerlos. Este método es abstracto para mayor libertad, ya que permite que el desarrollador realice tantas implementaciones del método como sistemas y/o mecanismos de recogida de datos desee utilizar.

Como se menciona en el javadoc del método 'getItems()', la lista de elementos de la caché se actualizará si dicha lista está vacía o si ha transcurrido más de un día desde la última actualización.


/**
* Generic cache is updated dayly. If there's any problem while trying to
* update the cache, the stored data is kept in the cache and the last modification
* time is updated.
*
* @param Type of the stored element
**/
public abstract class GenericCache {

private Calendar
lastModification;
private List itemList;

/**
* Constructor
**/
protected GenericCache() {
lastModification = new GregorianCalendar();
itemList = new ArrayList();
}

/**
* Checks if cache is empty
* @return true, if cache is empty; false, otherwise
**/
private boolean isEmpty() {
return (itemList == null || (itemList.size() == 0));
}

/**
* Gets the items to be inserted in cache.
*
* @return item list
* @throws Exception if the operation fails when getting items
**/
protected abstract List getNewItems() throws Exception;


/**
* Gets the latest item list from cache. If the cache is empty or if it's
* one day old, there will be an attempt to update it.
*
* @return item list from cache
**/
public List getItems() {
Calendar currentDate = new GregorianCalendar();
try {
if (isEmpty() ||
(lastModification.get(Calendar.DATY_OF_YEAR) != currentDate.get(Calendar.DAY_OF_YEAR))) {
List items = getNewItems();
if ((items != null) && (items.size() > 0)) {
itemList = items;
lastModification = currentDate;
}
}
} catch (Exception e) {
lastModification = currentDate;
}
return itemList;
}



Una posible implementación de esta caché abstracta sería la que se muestra a continuación:

public final class CompanyNamesCache extends GenericCache {

private static CompanyNames c
ompanyNames;
private LocalService localService;

/**
* Constructor
**/
private CompanyNamesCache() {
super();
try {
localService = (LocalService) ServiceLocator.getInstance().getLocalService("java:comp/env/ejb/LocalService");
} catch (NamingException ne) {
localService = null;
}
}

/**
* Gets an instance of the company names cache
*
* @return cache instance
**/
public static synchronized CompanyNamesCache getInstance() {
if (
companyNames == null) {
companyNames = new CompanyNamesCache();
}
return companyNames;
}

/**
* Gets new company names
*
* @return new company names list
* @throw Exception if an error occurs when getting company names
**/
@Override
protected List getNewItems() throws Exception {
List localService.getCompanyNames();
}

}

SQL - Consulta para obtener la información de una tabla

La tabla 'user_tab_columns' describe las columnas de las tablas, vistas y clusters del usuario actual.

Con la siguiente consulta podemos ver la información básica de los campos de una tabla del esquema al que estamos conectados:

SELECT usc.column_id, usc.column_name, usc.data_type, usc.data_length, usc.nullable
FROM user_tab_columns usc
WHERE usc.table_name = 'NOMBRE_TABLA'
ORDER BY usc.column_id;

SQL - Obtener ID de registros cuyo campo XXX esté repetido

Esta consulta devuelve los identificadores (ID) de los registros cuyo campo XXX aparezca en más de una ocasión en la tabla:

SELECT DISTINCT(T1.ID) FROM TABLA T1
WHERE
(SELECT COUNT(*) FROM TABLA T2 WHERE T1.XXX = T2.XXX) > 1


Obviamente, podemos obtener toda la información que nos interese de esos registros e incluir condiciones adicionales en la búsqueda.

Al incluir DISTINCT estamos especificando que la consulta devuelva los identificadores que satisfacen la condición una sola vez, es decir, que no haya IDs repetidos en la salida.