martes, 30 de julio de 2013

En la Ciudad de México 6to Simposio Internacional de SOA, Tecnología de Nube + Servicio.

clip_image002

En los días 5 y 6 de noviembre del 2013 se desarrollará en la Ciudad de México la Conferencia más Grande del Mundo Dedicada a SOA, Computación en Nube y Tecnologías Modernas de Servicio. El evento de este año atrae a oradores, conferencistas, autores y expertos de la industria de alrededor del mundo para promover el compartir de conocimientos y la experiencia en los campos cada vez más amplios de tecnología de servicio. Los temas incluirán Arquitectura Orientada al Servicio (SOA-Service Oriented Architecture), Computación en Nube, Datos Grandes, Virtualización Contemporánea, Planeación de Capacidad, Web Semántico, y muchos más

Los temas que se estarán abordando son los siguientes:

  • Patrones y arquitecturas para la Computación en la Nube.
  • Herramientas y buenas prácticas para Big Data.
  • Tecnologías emergentes e innovadoras para servicios.
  • Arquitecturas para aplicaciones móviles.
  • Arquitectura y diseño de Apis.
  • Modelos y prácticas para SOA y la Orientación a Servicios.
  • Seguridad de datos en aplicaciones hosteadas en la Nube.
  • Virtualización e Infraestructura de Servicios.
  • Arquitectura Empresarial basada en la Nube.
  • Casos de estudio reales.
  • Frameworks de gobierno para proyectos SOA y de Computación en la Nube.

Más información en http://www.servicetechsymposium.com/es/

{ Leer Más }


lunes, 29 de julio de 2013

Título: Introducción al diseño e implementación de un proceso con la herramienta BPMS Bonita. V

clip_image002

En la primera entrada  de esta serie con el BPMS Bonita habíamos visto como modelar el proceso de la figura anterior.

En la segunda entrada  vimos cómo crear tanto variables globales como locales para actividades en particular.

En la tercera entrada  vimos cómo definir condiciones y transiciones que nos permitían dar un mejor sentido a las posibles variantes que el proceso puede seguir en función de las decisiones que se tomen.

En la cuarta entrada  vimos cómo definir los roles participantes en el proyecto y ejecutar el proyecto visualizándolo desde una aplicación web ofrecida por Bonita.

En la cuarta entrada vimos como las interfaces de usuario estaban bastante pobres, sin ningún diseño ni usabilidad. Por este motivo en esta entrada estaremos viendo cómo mejorar este asunto.

Comencemos.!!!!

Lo primer es ir al formulario que inicia el proceso. Para eso damos clic en el pool del proceso, seleccionamos la pestaña de “Aplicación”, y luego seleccionamos “Pageflow de captura” tal y como se muestra en la siguiente imagen.

clip_image004

Ahora damos clic en el botón “Agregar” y veremos lo siguiente:

clip_image005

Como se puede apreciar se muestran las variables que se deben llenar al inicio del proceso y el tipo de componente que se usa para visualizarlas. Las dejamos todas seleccionadas y damos clic en “Finalizar”.

Ahora se nos muestra un nuevo elemento, es el formulario que acabamos de crear pero esta vez nos deja manipular la forma en que se visualizará y los componentes que contiene. Verán una paleta de componentes y podemos realizar mejoras a la interfaz gráfica.

clip_image007

Cada componente está dentro de un Widget y es fácilmente configurable su posición. Si quieren ver todo el formulario minimicen las otras pestañas.

Los signos de + y – si se paran encima de ellos les indican las acciones que realizan. En mi caso hice las siguientes:

1. Agregué una fila arriba.

2. Arrastre el Widget de nombre de cliente a esa fila.

3. Cree una fila encima de email y arrastré para ella el Widget de numerotelefono.

4. El Widget de productos que se visualizaba como botones de radio, lo cambié a “seleccionar” modificando el tipo de campo como se puede apreciar en la siguiente imagen.

clip_image008

Luego de estos cambios como me interesa ver qué tal va quedando, le doy a la pestaña “preview” y selecciono el navegador que quiero usar para ver el formulario. Y va quedando así:

clip_image010

Pruebo de nuevo con los productos como botones de radio a ver qué tal, y se ve así:

clip_image012

Como se puede observar en las imágenes se está mostrando el nombre de las variables, así que ahora mostraremos unos nombres más amigables. Para eso seleccionamos el Widget y vamos a la pestaña general, donde podemos modificar la etiqueta, tal y como se observa en la siguiente imagen.

clip_image014

Hacemos lo mismo para el resto de los campos.

Volvemos a ver el preview y ya ha mejorado algo.

clip_image016

Luego de estos cambios podemos trabajar sobre algunas validaciones. Les mostraré como validar el Widget que contiene el número de teléfono. Para eso debe seleccionar el Widget y dar clic en “Validadores”, dar clic en el botón “Agregar”, y seleccionar el tipo de validador “Phone Number” y poner algo como lo siguiente:

clip_image018

Otra cosa que podemos hacer es seleccionar “Opciones” y marcar cada Widget como requerido para forzar al usuario a que introduzca información en los campos.

Ahora podemos instanciar nuevamente el proceso ejecutándolo para ver los cambios realizados. Está claro que usaré valores no válidos para probar las cosas que se han hecho, veamos como se ve:

clip_image019

Podemos ver que donde no hemos introducido un valor nos dice que es “mandatory” o sea obligado, y cuando se ha puesto un valor que no se corresponde con un número telefónico nos alerta al respecto.

Luego de esta prueba haré otros cambios más:

1. Pondré un validador Email al Widget del correo electrónico,

2. cambiaré los productos ofertados a un seleccionar.

3. Cambiamos el nombre del botón.

Volvemos a probar ejecutando el proceso.

clip_image021

Y como se puede ver ya se valida el campo del correo electrónico y los productos se muestran en un seleccionar.

Como se ha podido apreciar, con Bonita es muy fácil mejorar las interfaces de usuario y agregar validadores a los cambios así como organizarlos mejor para el usuario final. En la siguiente entrada seguiremos trabajando con las otras interfaces de usuario viendo casos en particular que nos interesa explicar


{ Leer Más }


viernes, 26 de julio de 2013

Desplazamiento – Scrolling- en Tablet usando el Framework ZK.

clip_image002

Visualmente, la diferencia más notable entre dispositivos de escritorio y los táctiles es que no existen barras de desplazamiento en los dispositivos táctiles [1]. También los usuarios finales no son capaces de desplazarse usando los periféricos, como un ratón o un teclado, el movimiento en sentido vertical se hace mediante una acción de movimiento con el dedo.

ZK 6,5 se centra en esta característica y se han hecho muchas mejoras para hacer que todo funcione bien y sin problemas en los tablets. Este artículo tiene el objetivo de introducirlo en las funcionalidades de movimiento en sentido vertical en los tablets, en cómo los componentes de ZK admiten estas funciones y un ejemplo al final para expresar algunos consejos para la migración de aplicaciones de escritorio hacia los tablets.

Principio

clip_image004

El principio de la barra de desplazamiento es simple, si la altura del contenedor es menor que su contenido, barra de desplazamiento será visible para el desplazamiento, lo que significa que el valor de la altura del recipiente y el contenido decidirá el comportamiento de la barra de desplazamiento.

En el escritorio, la barra de desplazamiento es manejada por el navegador. En la tableta, la barra de desplazamiento está a cargo de ZK, ZK calculará la altura de los componentes, construyendo una barra de desplazamiento personalizada y transformando la acción para que sea fácil realizar el desplazamiento con el dedo.

Soporte de componentes ZK

Los componentes de ZK actúan indistintamente en la PC de escritorio y en el Tablet, con respecto a si una aplicaciones es desplazable o no. Si un componente se puede recorrer en una PC de escritorio, es desplazable en una tableta también. Del mismo modo, si un componente no admite el desplazamiento en una PC escritorio, no sería desplazable en una tableta. Los desarrolladores deben ser conscientes de este problema al migrar un proyecto de PC escritorio para tableta.

En ZK, algunos componentes permite desplazarse de forma predeterminada, algunos desactivan el desplazamiento por defecto. Esta sección le mostrará cómo puede cambiar sus valores por defecto para satisfacer diferentes necesidades.

Lo mismo para la PC escritorio y el Tablet, estos componentes se pueden desplazar de forma predeterminada:

  • Grid
  • Listbox
  • Tree

Para desactivar el desplazamiento, debe establecer el atributo data-scrollable de la siguiente forma:

<listbox xmlns:ca="client/attribute" ca:data-scrollable="false" />

Los siguientes componentes no se pueden desplazar de forma predeterminada para PC o tablet. Para habilitar el desplazamiento, debe establecer los atributos de la siguiente manera:


  • (Borderlayout) Center, East, West, North, South

  • autoScroll="true"

  • Groupbox, Window

  • contentStyle="overflow:auto"

  • PanelChildren, Tabpanel

  • style="overflow:auto"

ZK 6.5 también introduce un componente contenedor ScrollView. El se puede conectar a cualquier componente y proporciona la capacidad de desplazamiento.

Otras cuestiones

En los casos en que el padre y el hijo son componentes desplazables la acción de deslizar será manejada únicamente por el hijo y bloqueando los padres de desplazamiento. Al igual que el ejemplo de abajo, "pie de página" es invisible a los usuarios finales por lo que no sería capaz de desplazarlo.

<borderlayout height="100px">

<center autoscroll="true">

<div vflex="min">

<listbox height="100px">

<listitem forEach="1,2,3,4,5">

<listcell label="${each}"></listcell>

</listitem>

</listbox>

<label>footer</label>

</div>

</center>

</borderlayout>


clip_image005

Tenga en cuenta que componentes que no son desplazable a veces podrán tener desplazamiento porque navegador también proporciona un comportamiento de desplazamiento (antes de iOS 5, debe utilizar dos dedos para desplazarse). En el siguiente ejemplo, aunque <div> es no-desplazable, los usuarios finales pueden todavía desplazarse y ver "pie de página" porque navegador soporta esta funcionalidad.

<zk>

<div style="background-color:green" width="100%" height="2000px" />

<label>footer</label>

</zk>


clip_image006

Ejemplo

Ahora, vamos a analizar un ejemplo y reescribirla para que pueda entender el comportamiento del desplazamiento componente ZK con más detalle y cómo transformar el código existente para trabajar con dispositivos de tableta de manera eficiente.

Primero, lea este código:

<window id="root">

<tabbox width="100%">

<tabs>

<tab label="Demo"/>

</tabs>

<tabpanels><tabpanel>

<window id="inner">

<listbox id="lbx" />

<zscript><![CDATA[

//generate data for listbox

String[] data = new String[50];

for (int i = 0; i < data.length; i++) {

data[i] = "item " + i;

}

org.zkoss.zul.ListModel strset = new org.zkoss.zul.SimpleListModel(data);

lbx.setModel(strset);

]]></zscript>

</window>

</tabpanel></tabpanels>

</tabbox>

</window>


Parece ser normal, que el navegador haba que la barra de desplazamiento y el desplazamiento funcionen bien. Pero puede no funcionar en la tableta. ¿Por qué?

El cuadro de lista en el ejemplo anterior no hace que su propia barra de desplazamiento porque no nos limitamos a la altura del cuadro de lista, por lo que su tamaño se extiende a tantos elementos como sea necesario que en este caso es de 50 artículos. Esto da como resultado el contenido y el recipiente de ser del mismo tamaño y que el navegador sólo hace que la barra de desplazamiento para toda la página, esta página se convierte en un-desplazables porque los usuarios bloques listbox de deslizar toda la página.

clip_image007

Para aclarar la situación, si establece Listbox con width = "50%", el listbox todavía no es desplazables pero el espacio vacío de la derecha que no está cubierto por el listbox desplazable y vuelve cuando deslizar esa área, toda la página se desplaza .

Por supuesto, la asignación de una altura fija al cuadro de lista puede resolver este problema, pero, como modificar el código para que funcionara correctamente en la tableta con diseño flexible?

Solución

En primer lugar, debemos establecer un límite de alturas definida para los componentes de los padres por lo tanto para la ventana y Tabbox fijamos "height =" 100%". Entonces, nos pusimos Listbox VFLEX =" 1 "y dejamos ZK para calcular la altura del Listbox.

<window id="root" height="100%">

<tabbox width="100%" height="100%">

<tabs>

<tab label="Demo"/>

</tabs>

<tabpanels><tabpanel>

<window id="inner" height="100%">

<listbox id="lbx" vflex="1" />

<zscript><![CDATA[

String[] data = new String[50];

for (int i = 0; i < data.length; i++) {

data[i] = "item " + i;

}

org.zkoss.zul.ListModel strset = new org.zkoss.zul.SimpleListModel(data);

lbx.setModel(strset);

]]></zscript>

</window>

</tabpanel></tabpanels>

</tabbox>

</window>

clip_image008

La otra forma equivalente visual es dejar ventanas cuyo id es "interno" para manejar el desplazamiento. Para ello, retire VFLEX del Listbox para darle a tamaño completo y desactivar el desplazamiento de manera que la ventana puede recibir el evento de desplazamiento:

<window id="root" height="100%">

<tabbox width="100%" height="100%">

<tabs>

<tab label="Demo"/>

</tabs>

<tabpanels><tabpanel>

<window id="inner" height="100%" contentStyle="overflow:auto">

<listbox id="lbx" xmlns:ca="client/attribute" ca:data-scrollable="false" />

<zscript><![CDATA[

String[] data = new String[50];

for (int i = 0; i < data.length; i++) {

data[i] = "item " + i;

}

org.zkoss.zul.ListModel strset = new org.zkoss.zul.SimpleListModel(data);

lbx.setModel(strset);

]]></zscript>

</window>

</tabpanel></tabpanels>

</tabbox>

</window>


clip_image009

Conclusión

El mecanismo de desplazamiento es casi la misma cosa entre la PC de escritorio y la tableta. En el pasado, escribiendo la disposición incorrectamente no se producían errores serios de funcionamiento en la PC de escritorio, pero estos malos usos afectaban el funcionamiento de la aplicación en la tableta. Si los desarrolladores siguen los consejos en este artículo al escribir una aplicación, van a disminuir sustancialmente el costo de la migración de PC escritorio hacia tableta.

{ Leer Más }


jueves, 25 de julio de 2013

Introducción al diseño e implementación de un proceso con la herramienta BPMS Bonita. IV

clip_image002

En la primera entrada de esta serie con el BPMS Bonita habíamos visto como modelar el proceso de la figura anterior.

En la segunda entrada vimos cómo crear tanto variables globales como locales para actividades en particular.

En la tercera entrada vimos cómo definir condiciones y transiciones que nos permitían dar un mejor sentido a las posibles variantes que el proceso puede seguir en función de las decisiones que se tomen.

Y en esta entrada veremos cómo definir los actores y ejecutar el proceso.

Empecemos.!!!

Los actores, son aquellas personas que interactúan con el proceso a través de las actividades humanas, introduciendo o modificando de alguna forma la información. En los BPMS los actores son seleccionados dinámicamente en base a determinados criterios. En nuestro caso introducimos la restricción de crear una lista estática de los mismos para facilitar la comprensión inicial del funcionamiento de la herramienta Bonita, ya más adelante mostraremos como eliminar esta restricción.

En este proceso se requieren 2 tipos de actores:

  • El iniciador del proceso.
  • Los empleados de ventas.

Así que debemos:

1. Definir ambos grupos al nivel del proceso.

2. Ir a cada actividad que lo requiera y asignarles el grupo según se necesite.

Para realizar el primer paso damos clic en cualquier parte del pool y seleccionamos General y luego Actores. Veremos lo siguiente:

clip_image004

Por defecto la herramienta nos ha creado un actor y lo ha definido como iniciador, informándonos de que en caso de que no se defina uno, pues el proceso solo se puede iniciar desde el código.

En versiones anteriores como la 5.1 desde aquí mismo se podían crear grupos y dentro de cada grupo los actores. Ahora Bonita incluye desde hace algunas versiones el concepto de Organización entro de la cual se pueden crear los grupos, roles y usuarios de una organización.

Para este ejemplo lo primero que deben hacer es ir a menú superior y dar clic en la opción Organización y luego dan clic en Administrar.

Les saldrá una pestaña con una organización por defecto “Acme” pero para crear la de esta aplicación BPM pueden dar clic en “Añadir” e introducir los datos, tal y como se muestra a continuación.

clip_image006

Como ven solo le he puesto un nombre y una descripción, si quieren que aparezca como activa, es necesario que la publiquen en el portal, ya veremos cómo.

Una vez que marquen la organización que acaban de crear podrán dar clic en el botón “Siguiente” y entonces se debe crear el grupo o los grupos que contendrá nuestra organización. A fines de este ejemplo solo he creado un grupo.

clip_image008

Pero como pueden ver se pueden crear múltiples grupo e incluso subgrupos, eso queda a consideración de los analistas del proyecto.

Luego dan clic en “Siguiente” y creamos dentro del grupo anterior los roles necesarios para nuestra aplicación. Nos quedaría algo como lo siguiente:

clip_image010

Damos clic en “Siguiente” y pasamos a crear los usuarios. Importante que se fijen como un usuario se vincula con un grupo y a su vez con un rol dentro de dicho grupo.

clip_image012

Y hasta aquí esta primera parte, dan clic en Finalizar y listo.

Si vuelven a dar clic en el menú “Organización” pueden seleccionar la opción “Publicar”.

clip_image013

Seleccionan la organización que acaban de crear y si quieren le dan clic a “Siguiente” y de esta manera definen que usuario será usado automáticamente para acceder desde el portal a esta organización.

Para finalizar le dan clic al botón “Publicar”. Y ya está publicada la organización en el portal.

clip_image015

Llegado este momento si le dan clic al botón que dice “Ejecutar”.

clip_image016

Lo más seguro es que les dé un error pues falta algunos pasos por configurar. Veámoslos.

Deben dar clic en el botón que dice “Configurar” y entonces verán un mensaje que dice que el actor no está asignado a ningún grupo o rol, deben dar clic en “Grupos” y seleccionar el grupo correspondiente. Esto para cada usuario que no esté asociado a un grupo.

clip_image018

Luego deben dar clic donde dice “Autenticación” y poner el usuario y la contraseña con la que se accederá a la aplicación BPM una vez iniciada.

clip_image020

Ya pueden dar “Finalizar” y ejecutar el proceso.

Como no nos hemos dedicado aun a las interfaces gráficas pues todo está muy verde aun, pero lo importante es que está funcional. Cuando el proceso es ejecutado veremos estas pantallas:

clip_image022

El primer problema que vemos es que no se listan los artículos que están disponibles. Es algo que se arreglará después. Los datos que ven lo hemos introducido para este ejemplo.

Le damos “SUBMIT”

clip_image024

Y se nos informa que tenemos una tarea disponible.

Se nos muestra la información introducida por pepe el comprador en la página 1.

clip_image026

Y en la página 2:

clip_image028

Aparece por defecto la decisión de “Aprobar”, como ven no se nos muestran las otras opciones posibles de decisión y será otro problema a solucionar.

Le damos “SUBMIT

clip_image029

Y se nos informa que hay otra tarea disponible, le damos “Pagar”.

Se nos vuelve a mostrar la información de la venta en la página 1.

clip_image031

Y en la página 2 podemos decidir si el envío es express, poner la fecha de vencimiento y el número de la tarjeta con que se pagará.

clip_image033

Llegado este punto pueden darle al botón “SUBMIT” pero si quieren pueden darle al botón que tienen en la esquina superior derecha y que los lleva al portal de bonita, donde podrán navegar por los diferentes elementos y ver las tareas ya hechas, los comentarios, las tareas asignadas y pendientes, etc.

clip_image035

Al darle a “DO IT” se nos muestra la misma interface anterior y le podemos dar a “SUBMIT

clip_image037

Terminando así la ejecución de este proceso.

Como ven el proceso es funcional y hace lo que diseñamos pero quedan varias cuestiones de diseño que deben ser solucionadas. Esto lo veremos en próximas entradas.

Cualquier duda no dejen de dejarnos un comentario.


{ Leer Más }


miércoles, 24 de julio de 2013

Desarrollo de un cliente TCP/IP con el Framework Qt.

clip_image002

En la entrada anterior mostramos la creación de un servidor para un servicio de red simple, a través del protocolo TCP/IP usando el Framework Qt; a continuación se explicara la implementación de un cliente TCP/IP que se conectara a dicho servidor.

clip_image004

Esta aplicación de ejemplo usa un protocolo de trasferencia de datos simple basado en la clase QDataStream para solicitar una línea de texto “fortuna” desde el servidor de textos aleatorios (que ya explicamos en la entrada anterior).

El cliente solicita un texto “fortuna” a través de una conexión simple al servidor. Entonces el servidor le responde con un entero de 16-bit (quint16) que contiene la longitud del texto “fortuna”, seguido por un QString.

QTcpSocket soporta dos mecanismos generales para abordar la programación en red:

  • El mecanismo asíncrono (no-bloqueante): Las operaciones son planificadas y ejecutadas cuando el control retorna a ciclo de eventos de Qt. Cuando las operación es finalizada, QTcpSocket emite una señal. Por ejemplo, QTcpSocket::connectToHost() devuelve inmediatamente, y cuando la conexión ha sido establecida, QTcpSocket emite la señal connected().
  • El mecanismo síncrono (bloqueante): En aplicaciones que no tengan interfaz gráfica y las que son concurrentes, usted puede llamar a la función waitFor… () (por ejemplo: QTcpSocket::waitForConnected()) para suspender la llamada al hilo hasta que las operaciones se hayan completado, en vez de conectar a las señales.

En este ejemplo, le demostraremos el mecanismo asíncrono.

Nuestra clase contiene algunos datos y varios slots privados:

class Client : public QDialog
{
Q_OBJECT
public:
Client(QWidget *parent = 0);
private slots:
void requestNewFortune();
void readFortune();
void displayError(QAbstractSocket::SocketError socketError);
void enableGetFortuneButton();
private:
QLabel *hostLabel;
QLabel *portLabel;
QLineEdit *hostLineEdit;
QLineEdit *portLineEdit;
QLabel *statusLabel;
QPushButton *getFortuneButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QTcpSocket *tcpSocket;
QString currentFortune;
quint16 blockSize;
#ifdef Q_OS_SYMBIAN
bool isDefaultIapSet;
#endif
};

Además de los widgets que conforman la Interfaz Gráfica de Usuario, los miembros de clase incluyen un puntero a QTcpSocket, una copia del texto “fortuna” que se muestra actualmente, y el tamaño del paquete de datos que actualmente estamos leyendo.

El socket es inicializado en el constructor del Cliente (Client). Nosotros pasaremos el widget principal como padre, de esta forma no tendremos que preocuparnos por eliminar el socket:

Client::Client(QWidget *parent)
: QDialog(parent)
{
...
tcpSocket = new QTcpSocket(this);

Las únicas señales de QTcpSocket que necesitamos en este ejemplo son QTcpSocket::readyRead (), que representa cuando los datos han sido recibidos, y QTcpSocket::error (), el cual usaremos para capturar cualquier error de conexión:

 ...
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readFortune()));
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
...

Haciendo clic en el botón Get Fortune invocaremos el slot requestNewFortune ():

void Client::requestNewFortune()
{
getFortuneButton->setEnabled(false);
#ifdef Q_OS_SYMBIAN
if(!isDefaultIapSet) {
qt_SetDefaultIap();
isDefaultIapSet = true;
}
#endif
blockSize = 0;
tcpSocket->abort();
tcpSocket->connectToHost(hostLineEdit->text(),
portLineEdit->text().toInt());
}

En este slot, nosotros inicializamos blockSize a 0, preparando para leer un nuevo bloque de datos. Debido a que se permite al usuario hacer clic en el botón Get Fortune antes que la conexión previa haya finalizado el proceso de cierre, se pone en marcha abortando la conexión previa mediante una llamada a QTcpSocket::abort (). (En un socket desconectado, esta función no hace nada). Entonces procedemos a realizar la conexión al servidor de “Fortunas” mediante la llamada a QTcpSocket::connectToHost (), pasando como argumentos el nombre del host y el puerto, que se obtienen de la interfaz de usuario.

Como resultado de la llamada a connectToHost (), puede suceder una de estas dos acciones:

· La conexión es establecida. En ese caso, el servidor enviara un texto de “Fortuna”. QTcpSocket emitirá la señal readyRead () cada vez que reciba un bloque de datos.

· Ocurre un error. En este caso es necesario informar al usuario si la conexión fallo o fue abortada. De esta forma, QTcpSocket emitirá la llamada a error(), y la función Client::displayError () será llamada.

Revisemos primero el caso de la llamada a error ():

  void Client::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError) {
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
QMessageBox::information(this, tr("Fortune Client"),
tr("The host was not found. Please check the "
"host name and port settings."));
break;
case QAbstractSocket::ConnectionRefusedError:
QMessageBox::information(this, tr("Fortune Client"),
tr("The connection was refused by the peer. "
"Make sure the fortune server is running, "
"and check that the host name and port "
"settings are correct."));
break;
default:
QMessageBox::information(this, tr("Fortune Client"),
tr("The following error occurred: %1.")
.arg(tcpSocket->errorString()));
}
getFortuneButton->setEnabled(true);
}

Los errores se muestran al usuario en forma de dialogo usando QMessageBox::information (). QTcpSocket::RemoteHostCloseError es silenciosamente ignorado, porque el protocolo del servidor de “Fortunas” finaliza con el cierre de la conexión al servidor.

Ahora para la alternativa de readyRead(). Esta señal es conectada al método Client::readFortune():

void Client::readFortune()
{
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize == 0) {
if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> blockSize;
}
if (tcpSocket->bytesAvailable() < blockSize)
return;

El protocolo es basado en QDataStream, por lo tanto iniciamos creando un objeto flujo (stream), pasando el socket al constructor de QDataStream. Entonces se establece explícitamente la versión del protocolo para el flujo a QDataStream::Qt_4_0 para estar seguros que estamos usando la misma versión que el servidor de “Fortunas”, no importa cual versión de Qt están usando el cliente y el servidor.

Ahora, TCP es basado en el envío de flujos de datos, por lo tanto nosotros no podemos tener la expectativa de obtener el texto completo de la “fortuna” en un solo intento. Especialmente en una red lenta, los datos pueden ser recibidos en muchos fragmentos pequeños. QTcpSocket almacenara en buffers todos los datos entrantes y emitirá readyRead() para cada nuevo bloque que arribe, y es nuestro trabajo asegurarnos de que hemos recibido todos los datos que necesitamos antes de empezar el proceso de análisis. La respuesta del servidor inicia con el número de paquetes, de esta forma primero necesitamos asegurarnos de que podemos leer el tamaño, y entonces esperaremos hasta que QTcpSocket haya recibido el paquete completo.

QString nextFortune;
in >> nextFortune;
if (nextFortune == currentFortune) {
QTimer::singleShot(0, this, SLOT(requestNewFortune()));
return;
}
currentFortune = nextFortune;
statusLabel->setText(currentFortune);
getFortuneButton->setEnabled(true);
}

Se procede a usar el operador de flujo de la clase QDataStream para leer el texto “Fortuna” desde el socket hacia un QString. Una vez leído, podemos llamar al método QLabel::setText () para mostrar el texto “Fortuna”.

El código fuente de esta aplicación pueden descargarlo desde aquí.




{ Leer Más }


martes, 23 de julio de 2013

Postgresql + CodeIgniter

Ya que hemos avanzado un poco en el mundo de las consultas, ya citado en el artículo anterior vamos a introducirnos en la utilización de las mismas pero enfocados a un marco de trabajo llamado codeIgniter, framework que goza de gran prestigio en los desarrolladores y empresas que eligen php como lenguaje de programación para desarrollar sus proyectos.

¿Qué es CodeIgniter?

CodeIgniter es un Entorno de Desarrollo de una Aplicación - una herramienta de sistema - para gente que construye sitios web usando PHP. El objetivo es habilitar el desarrollo de proyectos mucho más rápido de lo que podría si escribiese código desde cero, a través de proveer un rico conjunto de librerías para tareas comúnmente necesarias, tanto como una simple interface y estructura lógica para acceder a estas librerías. CodeIgniter le permite concentrarse creativamente en su proyecto minimizando el volumen de código necesario para una tarea determinada.

¿Para quién es CodeIgniter?

CodeIgniter es correcto para usted si:

  • Quiere un entorno de trabajo con un pequeño punto de apoyo.
  • Necesita un desempeño excepcional.
  • Necesita amplia compatibilidad con cuentas de hosting estándar que corren una variedad de versiones y configuraciones de PHP.
  • Quiere un entorno de trabajo que requiere casi nula configuración.
  • Quiere un entorno de trabajo que no requiera usar línea de comando.
  • Quiere un entorno de trabajo que no requiera adherir a reglas de codificación estrictas.
  • No está interesado en monolíticas librerías de gran escala como PEAR.
  • No quiere ser forzado a aprender un lenguaje de plantillas (aunque una sintaxis de plantillas está opcionalmente disponible si lo desea).
  • Evita complejidad, favoreciendo las soluciones simples.
  • Necesita clara, exhaustiva documentación.

Ya explicado más menos sobre el framework de trabajo que vamos a usar nuestras consultas y sin desviarnos del tema central que son los gestores de base de datos y en nuestro caso particular postgres vamos a pasar a ver algunos aspectos que les resultarán muy interesantes.

CodeIgniter está basado en el patrón de desarrollo Modelo-Vista-Controlador. MVC es una aproximación al software que separa la lógica de la aplicación de la presentación. En la práctica, permite que sus páginas web contengan mínima codificación ya que la presentación es separada del código PHP.

  • El Modelo representa la estructura de datos. Típicamente sus clases de modelo contendrán funciones que lo ayudarán a recuperar, insertar y actualizar información en su base de datos.
  • La Vista es la información que es presentada al usuario. La Vista normalmente será una página web, pero en CodeIgniter, una vista también puede ser un fragmento de una página como un encabezado o un píe de página. También puede ser una página RSS, o cualquier otro tipo de "página".
  • El Controlador sirve como un intermediario entre el Modelo, la Vista y cualquier otro recurso necesario para procesar la petición HTTP y generar una página web.

CodeIgniter tiene un enfoque bastante flexible del MVC, ya que los Modelos no son requeridos. Si no necesita agregar separación, o descubre que mantener los modelos requiera más complejidad que quería, puede ignorarlos y construir su aplicación mínimamente usando Controladores y Vista. CodeIgniter también le permite incorporar sus códigos existentes, o incluso desarrollar librerías de núcleo para el sistema, habilitándolo a trabajar en una forma que hace que tenga más sentido para usted.

Hasta aquí aunque parezca que se sale un poco del tema no lo creas así porque es necesario que entiendas que terrenos pisas para pasar a la parte que nos interesa, en nuestro caso vamos a introducirnos en la capa del Modelo aquí es donde vamos a poner nuestras consultas a las base de datos.

¿Qué es un modelo?

Los modelos son clases PHP que se han diseñado para trabajar con la información en su base de datos. Por ejemplo, digamos que usted usa CodeIgniter para administrar un blog. Puede que tenga una clase de modelo que contiene funciones para insertar, actualizar y recuperar datos de su blog. Aquí está un ejemplo de lo que podría ser la clase del modelo:

Nota: Las funciones en el ejemplo anterior usan funciones de base de datos Active Record.

Y aquí es donde queríamos llegar a Active Record.

CodeIgniter usa una versión modificada del Patrón de Base de Datos Active Record. Este patrón permite obtener, insertar y actualizar información en tu base de datos con mínima codificación. En algunos casos, sólo una o dos líneas de código son necesarias para realizar una acción de base de datos. CodeIgniter no requiere que cada tabla de la base de datos sea un propio archivo de clase. Se permite una interface más simplificada

Más allá de la simplicidad, un beneficio mayor de usar la Active Record es que te permite crear una aplicación independiente de la base de datos que usa, ya que la sintaxis de consulta es generada por cada adaptador de base de datos. También permite consultas más seguras.

A continuación vamos a pasar a ilustrar algunos ejemplos de consultas usando este patrón no hay nada mejor para entender que ejemplos reales. Las siguientes funciones permiten construir una sentencia SELECT SQL.

Ejemplo # 1 Ejecuta la consulta de selección y devuelve el resultado. Puede ser usado solo, para traer todos los registros de una tabla:

$consulta = $this->db->get('mitabla');

Produce: SELECT * FROM mitabla

Ejemplo # 2 Permite escribir la porción de SELECT de tu consulta:

$this->db->select('titulo, contenido, fecha');
$consulta = $this->db->get('mitabla');

Produce: SELECT titulo, contenido, fecha FROM mitabla


Ejemplo # 3 Permite escribir una porción JOIN de la consulta:
$this->db->select('*');
$this->db->from('blogs');
$this->db->join('comentarios', 'comentarios.id = blogs.id');
$query = $this->db->get();
Produce:
SELECT * FROM blogs
JOIN comentarios ON comentarios.id = blogs.id

Con estos 3 ejemplos vamos cerrando por esta artículo esperando que siempre sea de su agrado, y sobre todo que le pueda servir a solucionar problemas, si quiere seguir abordando sobre el tema puede visitar la ayuda de CodeIgniter y recuerde seguirnos en próximos artículos no olvide visitar nuestro blog.

{ Leer Más }


lunes, 22 de julio de 2013

Construir una interfaz de usuario en ZK con un Richlet.

clip_image002

Una alternativa para no tener que escribir ficheros ZUL que se sirvan bajo petición del usuario, es desarrollar aplicaciones usando Richlet, que es un pequeño programa en Java que construye la interfaz de usuario mediante programación en Java. Cuando un usuario hace una petición mediante una URL que está enlazada en el Richlet, ZK Loader hace responsable al Richlet de la construcción de la interfaz de usuario. Esto les da a los desarrolladores todo el poder a la hora de crear los componentes [1]. La elección entre páginas ZUML y Richlets depende de su preferencia. En este artículo, demostraremos cómo usar un Richlet creando una pequeña aplicación que consistirá en un buscador. Para una explicación más detallada ver: Richlet en la ZK Developer's Reference.

Aplicación de ejemplo

La aplicación de ejemplo que vamos a construir es un simple catálogo de coches. Esta aplicación tiene 2 funciones principales:

  • Buscar coches. Escribir una palabra clave en el campo de texto, hacer clic en el botón de buscar y mostrar los resultados de la búsqueda en la lista contigua.
  • Ver los detalles de un coche. Haciendo clic en uno de los coches de la lista, el área contigua mostrará los detalles del coche seleccionado, incluyendo el modelo, precio, descripción y vista previa.

clip_image003

Implementación

Para implementar un Richlet, tu clase tiene que implementar el interfaz Richelt. A pesar de que, no es necesario implementarla tal cual. En vez de eso puedes extender GenericRichlet y solo sobrescribir el método Richlet.service(Page). Este método será el que se llame cuando se haga una petición al Richlet por parte del usuario.

clip_image004

Para tener mejor control, puedes incluso implementar los métodos Richlet.init(RichletConfig) y Richlet.destroy() para inicializar y destruir cualquier cosa que necesite el Richlet para funcionar.

Creando la Interfaz de Usuario

Una de las funciones principales de un Richlet es crear la interfaz de usuario. Es recomendable empezar leyendo los conceptos básicos sobre interfaz de usuario en ZK antes de crearla mediante Java.

  • El interfaz de usuario en ZK es un árbol de componentes, cada componente tiene un componente padre, y a su vez puede tener o no múltiples componentes hijos.
  • No todos los componentes aceptan como hijos a todos los tipos de componentes que existen, solo a aquellos que se correspondan, o incluso ninguno.

Por ejemplo, un Grid en XUL acepta columnas y Filas como hijos. Para más detalle mirar la documentación al respecto: ZK Component Reference.

clip_image005

Línea 12: Para crear un componente, simplemente lo instanciamos.
Línea 14: Cada atributo de un componente tiene su correspondiente método setter que podemos usar para asignarle el valor correspondiente.
Línea 18: Para establecer una relación Padre-Hijo entre componentes, podemos usar el método appendChild(Component). Esto enlaza el componente indicado en el método, al final de la lista de componentes hijos (que ya tuviera) del componente padre. Hay otros métodos similares para hacer esto como setParent(Component), insertBefore(Component,Component). Puedes encontrar más información al respecto en la documentación

Renderizando el modelo de datos

Después de proveer el objeto Modelo al componente ListBox, normalmente necesitamos indicar cómo mostrar los datos que contiene. Necesitamos crear un objeto Render para ello.

Un Render es una clase Java en la que se indica cómo se va a mostrar cada dato del modelo. Lo creamos implementando la interfaz de tipo Render que corresponda a cada componente, para un Listbox usaremos ListitemRenderer. En la ZK Developer's Reference están la del resto de componentes.

Item renderer de un Listbox

clip_image007

  • En el método render(), nos encargamos de crear el interfaz del usuario que queremos añadiendo los componentes hijos al componente padre Listitem.

Después de crear el Render necesitamos asignarlo al ListBox.

carListbox.setItemRenderer(new CarRenderer());

Event Listener

En nuestra aplicación de ejemplo, un usuario puede hacer click en el botón de "Search" para realizar su búsqueda, tenemos por lo tanto que escuchar el evento "onClick". Podemos resolverlo invocando al método AbstractComponent.addEventListener(String, EventListener) del componente. El primer parámetro es el nombre del evento, y el segundo es un objeto que implemente la interfaz EventListener. En un EventListener, puedes manipular los componentes para añadir tu lógica de la aplicación, como puede ser cambiar atributos de otros componentes, crear nuevos componentes, o eliminar uno existente. Puedes ver todas las características de los componentes en la ZK Component Reference, y ver qué atributos puedes necesitar usar.

clip_image009

Línea 7: Puedes crear una clase a parte que implemente EventListener. En este ejemplo usamos una clase anónima por simplificar. Pero ojo, en un clúster debes implementar la versión serializable SerializableEventListener.
Línea 10: Escribe la lógica de tu aplicación dentro del método onEvent(), cosas como leer un valor con un get, cambiar un atributo de un componente o actualizar información

Otra función del ejemplo es que cuando el usuario selecciona un coche de la lista, mostramos sus detalles en el área de información. Para manejar esto, tenemos que escuchar el evento de seleccionar del componente Listbox, y entonces leer los atributos del coche y asignar los valores a los componentes correspondientes de la vista.

clip_image011

Configuración del Richlet

Hay 2 requisitos para que el Richlet esté disponible para la aplicación cliente.

  1. Activar el soporte de Richlets (en WEB-INF/web.xml)
  2. Mapear la URL (que puede ser estática o un patrón) a la que responderá el Richlet (in WEB-INF/zk.xml)
Activar el soporte de Richlets

Por defecto, los richlets están desactivados. Para activarlos, hay que añadir la siguiente declaracíon en el fichero WEB-INF/web.xml.

<servlet-mapping>
     <servlet-name>zkLoader</servlet-name>
     <url-pattern>/zk/*</url-pattern>

</servlet-mapping>

De este ejemplo, puedes cambiar /zk/* a otro patrón (que corresponda con una URL válida) que tu quieras, como por ejemplo /do/*. Fíjate que no puedes mapear la expresión como si de una extensión de un fichero se tratase (como por ejemplo *.do) o se procesará como una página ZUML en vez de como un Richlet.

Mapear la URL a la que responderá el Richlet

Cada Richlet que implementes, debes declararlo en la configuración WEB-INF/zk.xml de la siguiente forma:

clip_image012

Línea 6: Después de definir el Richlet, puedes mapearlo bajo tantas URLs como quieras mediante el elemento de configuración richlet-mapping

Puedes visitar http://localhost:8080/PROJECT_NAME/zk/search y ver tu Richlet. La URL especificada en el parámetro url-pattern debe empezar siempre con "/".

Si la URL termina en /*, se asocia a cualquier petición con el mismo prefijo. Para recibir la URL de la petición actual puedes chequear el valor que retorna el método getRequestPath de la página en la que te encuentres.

clip_image013

Conclusiones

ZK es tan versátil que provee de múltiples opciones para que seas usted quien elija cómo construir la Interfaz de usuario, o incluso varias al mismo tiempo, dependiendo de tus preferencias o entorno. El código fuente usado en el artículo puedes descargarlo aquí.

{ Leer Más }


IconIconIcon