viernes, 15 de diciembre de 2017

Creación de un nodo de entrada en Java

Un nodo de entrada se utiliza para recibir un mensaje en un flujo de mensajes, normalmente de un origen no soportado por los nodos de entrada incorporados.
Creación de un proyecto Java
Para poder crear nodos Java en el IBM® Integration Toolkit, antes debe crear un proyecto Java:
  1. Pulse Archivo > Nuevo > Proyecto, seleccione Proyecto Java y luego pulse Siguiente.
  2. Asigne un nombre al proyecto y luego pulse Siguiente.
  3. En el panel Valores de Java, seleccione el separador Bibliotecas y pulse Añadir archivos JAR externos.
  4. Seleccione dir_instalación\classes\jplugin2.jar, donde dir_instalación es el directorio inicial de la instalación de IBM Integration Bus.
  5. Siga las solicitudes de los demás separadores para definir otros valores de creación.
  6. Pulse Finalizar.
Ahora puede desarrollar el origen del nodo Java en este proyecto.

Declaración de la clase de nodo de entrada

Cada clase que implemente MbInputNodeInterface y esté contenida en la vía de acceso de LIL del intermediario se registra en el intermediario como un nodo de entrada. Cuando implemente MbInputNodeInterface, también debe implementar un método runpara esta clase. El método run representa el inicio del flujo de mensajes, contiene los datos que formulan el mensaje y los propaga por el flujo. El intermediario invoca el método run cuando quedan hebras disponibles de acuerdo con el modelo de trabajo con hebras especificado.
El nombre de clase debe terminar por la palabra "Node". Por ejemplo, si el nombre es BasicInput en el IBM Integration Toolkit, el nombre de clase debe ser BasicInputNode.
Por ejemplo, para declarar la clase de nodo de entrada:
package com.ibm.jplugins;

import com.ibm.broker.plugin.*;

public class BasicInputNode extends MbInputNode implements MbInputNodeInterface
{
...

Siga estos pasos para completar esta acción en IBM Integration Toolkit:
  1. Pulse Archivo > Nuevo > Otros, seleccione Clase y luego pulse Siguiente.
  2. Establezca los campos de nombre de paquete y clase en los valores apropiados.
  3. Suprima el texto en el campo de texto Superclase y pulse el botón Examinar.
  4. Seleccione MbInputNode.
  5. Pulse el botón Añadir junto al campo de texto de interfaces y seleccione MbInputNodeInterface.
  6. Pulse Finalizar.

Definición del constructor de nodos

Cuando se crea una instancia del nodo, se llama al constructor de la clase de nodo. Esta clase es donde se crean los terminales del nodo y se inicializan los valores predeterminados para los atributos.
Un nodo de entrada tiene asociados varios terminales de salida pero normalmente no tiene ningún terminal de entrada. Utilice el método createOutputTerminal para añadir terminales de salida a un nodo cuando se crea una instancia del nodo. Por ejemplo, para crear un nodo con tres terminales de salida:
public BasicInputNode() throws MbException
{
 createOutputTerminal ("out");
 createOutputTerminal ("failure");
 createOutputTerminal ("catch");
 setAttribute ("firstParserClassName","myParser");
 attributeVariable = "none"; 
}

Recepción de datos externos en un almacenamiento intermedio

Un nodo de entrada puede recibir datos de cualquier tipo de origen externo, como un sistema de archivos, una cola o una base de datos, del mismo modo que todos los demás programas de Java, si la salida del nodo está en el formato correcto.
Proporcione un almacenamiento intermedio de entrada (o corriente de bits) para incluir los datos de entrada y asócielo con un objeto de mensaje. Cree un mensaje a partir de una matriz de bytes, utilizando el método createMessage de la clase MbInputNode, y luego genere un conjunto de mensajes válido desde este mensaje. Por ejemplo, para leer los datos de entrada de un archivo:
  1. Cree una corriente de datos de entrada para leerla en el archivo:
    FileInputStream inputStream = new FileInputStream("myfile.msg");

  2. Cree una matriz de bytes del tamaño del archivo de entrada:
    byte[] buffer = new byte[inputStream.available()];

  3. Lea del archivo en la matriz de bytes:
    inputStream.read(buffer);

  4. Cierre la corriente de datos de entrada:
    inputStream.close();

  5. Cree un mensaje para ponerlo en la cola:
    MbMessage msg = createMessage(buffer);

  6. Cree un conjunto de mensajes para que contenga este mensaje:
    msg.finalizeMessage(MbMessage.FINALIZE_VALIDATE);
    MbMessageAssembly newAssembly =
         new MbMessageAssembly(assembly, msg);

Propagación del mensaje

Cuando haya creado un conjunto de mensajes, puede propagarlo a uno de los terminales de salida definidos en el nodo.
Por ejemplo, para propagar el conjunto de mensajes al terminal denominado out:
MbOutputTerminal out = getOutputTerminal("out");
out.propagate(newAssembly);

Para suprimir el mensaje:
msg.clearMessage();
Para borrar la memoria que está asignada para el árbol de mensaje, llame a la función clearMessage() del bloque try/catch final.

Control del trabajo con hebras y transacciones

La infraestructura de intermediario maneja las cuestiones de transacción, tales como el control de la confirmación de una unidad de trabajo de WebSphere MQ o de base de datos, cuando se ha completado el proceso de mensajes. Sin embargo, los recursos modificados desde dentro de un nodo definido por el usuario no están necesariamente bajo el control transaccional del intermediario.
Cada hebra de flujo de mensajes se asigna desde una agrupación de hebras mantenidas para cada flujo de mensajes y se inicia en el método run.
El nodo definido por el usuario utiliza valores de retorno para indicar si una transacción es satisfactoria, para controlar si las transacciones se confirman o se retrotraen y para controlar cuándo se devuelve la hebra a la agrupación. La infraestructura de intermediario detecta todas las excepciones no manejadas y retrotrae la transacción.
Determine el comportamiento de las transacciones y las hebras utilizando el valor de retorno adecuado:
MbInputNode.SUCCESS_CONTINUE
La transacción se confirma y el intermediario invoca el método run otra vez utilizando la misma hebra.
MbInputNode.SUCCESS_RETURN
La transacción se confirma y se devuelve la hebra a la agrupación de hebras, suponiendo que no sea la única hebra para este flujo de mensajes.
MbInputNode.FAILURE_CONTINUE
La transacción se retrotrae y el intermediario invoca el método run otra vez utilizando la misma hebra.
MbInputNode.FAILURE_RETURN
La transacción se restituye y se devuelve la hebra a la agrupación de hebras, suponiendo que no sea la única hebra para este flujo de mensajes.
MbInputNode.TIMEOUT
El método run no debe bloquearse de forma indefinida mientras espera a que lleguen datos de entrada. Mientras el flujo está bloqueado por el código de usuario, no puede concluir ni reconfigurar el intermediario. El método run debe ceder el control al intermediario periódicamente volviendo del método run. Si no se reciben datos de entrada después de un determinado periodo de tiempo (por ejemplo 5 segundos), el método debe volver con el código de retorno TIMEOUT. Suponiendo que no sea necesario reconfigurar o concluir el intermediario, se vuelve a llamar inmediatamente al métodorun del nodo de entrada.
Para crear flujos de mensajes de varias hebras, invoque el método dispatchThread después de que se haya creado un mensaje pero antes de que se propague el mensaje a un terminal de salida. Esta acción asegura que sólo una hebra esté esperando datos mientras otras hebras están procesando el mensaje. Se obtienen hebras nuevas de la agrupación de hebras hasta el límite máximo especificado por la propiedad Instancias adicionales del flujo de mensajes. Por ejemplo:
public int run( MbMessageAssembly assembly ) throws MbException
{
  byte[] data = getDataWithTimeout();  // el método proporcionado por el usuario
                                       // devuelve nulo si se excede el tiempo de espera
  if( data == null )
    return TIMEOUT;

  MbMessage msg = createMessage( data );
  msg.finalizeMessage( MbMessage.FINALIZE_VALIDATE );
  MbMessageAssembly newAssembly =
       new MbMessageAssembly( assembly, msg );

  dispatchThread();

  getOutputTerminal( "out" ).propagate( newAssembly );

  return SUCCESS_RETURN;
}

Declaración del nombre de nodo

Debe declarar el nombre del nodo para que IBM Integration Toolkit pueda utilizarlo e identificarlo. Todos los nombres de nodo deben terminar con los caracteres "Node". Declare el nombre utilizando el método siguiente:
public static String getNodeName()
{
   return "BasicInputNode";
}

Si no se declara este método, la infraestructura de API Java crea un nombre de nodo predeterminado utilizando las normas siguientes:
  • El nombre de clase se añade el nombre de paquete.
  • Los puntos se eliminan y la primera letra de cada parte del nombre de paquete y clase se escribe en mayúsculas.
Por ejemplo, por omisión se asigna a la clase siguiente el nombre de nodo "ComIbmPluginsamplesBasicInputNode":
package com.ibm.pluginsamples;
public class BasicInputNode extends MbInputNode implements MbInputNodeInterface
{
   ...

Declaración de atributos

Declare atributos de nodo utilizando el mismo método que utiliza para las propiedades de bean de Java. Usted es responsable de escribir métodos get y set para los atributos; la infraestructura de API deduce los nombres de atributo utilizando las normas de introspección de bean Java. Por ejemplo, si declara los dos métodos siguientes:
private String attributeVariable;

public String getFirstAttribute()
{
  return attributeVariable;
}

public void setFirstAttribute(String value)
{
  attributeVariable = value;
}
El intermediario deduce que este nodo tiene un atributo denominado firstAttribute. Este nombre se deriva de los nombres de los métodos get o set, no de los nombres de variable de los miembros de clase internos. Dado que los atributos sólo se pueden exponer como series de caracteres, convierta los tipos numéricos a y desde series de caracteres en los métodos get o set. Por ejemplo, el método siguiente define un atributo denominado timeInSeconds:
int seconds;

public String getTimeInSeconds()
{
  return Integer.toString(seconds);
}

public void setTimeInSeconds(String value)
{
  seconds = Integer.parseInt(value);
}

Implementación de la funcionalidad de nodo

Como ya se ha descrito, el intermediario invoca el método run para crear el mensaje de entrada. Este método debe proporcionar toda la función de proceso para el nodo de entrada.

Alteración temporal de los atributos de analizador de mensajes predeterminados (opcional)

Normalmente una implementación de nodo de entrada determina qué analizador de mensajes analiza inicialmente un mensaje de entrada. Por ejemplo, el nodo MQInput incorporado indica que se necesita un analizador MQMD para analizar la cabecera MQMD. Un nodo de entrada definido por el usuario puede seleccionar un analizador de mensajes o cabeceras apropiado y la modalidad en la que se controla el análisis, utilizando los atributos predeterminados siguientes que se incluyen, que se pueden alterar temporalmente:
rootParserClassName
Define el nombre del analizador raíz que analiza los formatos de mensaje soportados por el nodo de entrada definido por el usuario. Toma por omisión GenericRoot, un analizador raíz proporcionado que hace que el intermediario asigne y encadene analizadores. Es poco probable que un nodo tenga que modificar este valor de atributo.
firstParserClassName
Define el nombre del primer analizador, de lo que puede ser una cadena de analizadores responsables de analizar la corriente de bits. Toma por omisión XML.
messageDomainProperty
Atributo opcional que define el nombre del analizador de mensajes necesario para analizar el mensaje de entrada. Los valores soportados son los mismos que los valores soportados por el nodo MQInput.
messageSetProperty
Atributo opcional que define el identificador de conjunto de mensajes o el nombre de conjunto de mensajes, en el campo Conjunto de mensajes, sólo si el atributo messageDomainProperty especificaba el analizador MRM.
messageTypeProperty
Atributo opcional que define el identificador del mensaje en el campo Tipo de mensaje, sólo si el atributomessageDomainProperty especificaba el analizador MRM.
messageFormatProperty
Atributo opcional que define el formato del mensaje en el campo Formato del mensaje, sólo si el atributomessageDomainProperty especificaba el analizador MRM.

Supresión de una instancia del nodo

Se suprime una instancia del nodo cuando se realiza una de las acciones siguientes:
  • Se concluye el intermediario.
  • Se elimina el nodo o el flujo de mensajes que contiene el nodo y se vuelve a desplegar la configuración.
Cuando el nodo se suprime, puede realizar operaciones de limpieza, tales como cerrar sockets, si implementa el método onDeleteopcional. El intermediario llama a este método, si existe, justo antes de que se suprima el nodo.
Implemente el método onDelete del modo siguiente:
public void onDelete()
{
  // realizar limpieza de nodo si es necesario
}

jueves, 14 de diciembre de 2017

Listas Enlazadas Circulares Dobles

Listas Enlazadas Circulares Dobles

La lista circular doble es una especie de lista enlazada  “doblemente enlazada”, pero que posee una característica adicional para el desplazamiento dentro de la lista, “ésta no tiene fin”  y tiene 2 apuntadores a si misma.

Para que la lista sea sin fin, el puntero siguiente del último elemento apuntará hacia el 1er elemento y  el puntero anterior del primer elemento apuntara hacia el ultimo elemento de la lista en lugar de apuntar al valor NULL, como hemos visto en el caso de listas enlazadas simples o doblemente enlazadas.
En las listas circulares dobles, nunca se llega a una posición en la que ya no sea posible desplazarse.
Cuando se llegue al último elemento, el desplazamiento volverá a comenzar desde el primer elemento.


Los operaciones básicas de una lista circular doble   son:
·    Insertar: inserta un nodo con dato x en la lista, pudiendo realizarse esta inserción al principio o final de la lista o bien en orden.
·    Eliminar: elimina un nodo de la lista, puede ser según la posición o por el dato.
·    Buscar: busca un elemento en la lista.
·    Localizar: obtiene la posición del nodo en la lista.
·    Imprimir: imprime los elementos de la lista.

Nodo principal
public class Nodo {
       private Integer dato;
       private Nodo anterior;
       private Nodo siguiente;
   
}

Método Insertar al inicio
public void insertarInicio(Integer d){
         Nodo nuevo=new Nodo(d);
         if(inicio==null)
                   inicio=nuevo;
         else{
                   Nodo aux=inicio;
                   while(aux.getSiguiente()!=inicio)
                            aux=aux.getSiguiente();
                   aux.setSiguiente(nuevo);
                   nuevo.setAnterior(aux);
                   nuevo.setSiguiente(inicio);
                   inicio.setAnterior(nuevo);
                   inicio=nuevo;
                  
         }
       }
 Método insertar al final
      
public void insertarFinal(Integer d){
         Nodo nuevo=new Nodo(d);
         if(inicio==null)
                   inicio=nuevo;
         else{
                   Nodo aux=inicio;
                   while(aux.getSiguiente()!=inicio)
                            aux=aux.getSiguiente();
                   aux.setSiguiente(nuevo);
                   nuevo.setAnterior(aux);
                   nuevo.setSiguiente(inicio);
                   inicio.setAnterior(nuevo);
         }
       }
      


Método insertar ordenadamente


public void agregarOrdenados(Integer d){
         Nodo nuevo=new Nodo(d);
         if(inicio==null)
                   inicio=nuevo;
         else{
                   Nodo aux=inicio;
                   while((aux.getSiguiente()!=inicio) && (aux.getDato()<d)){
                            aux=aux.getSiguiente();
                   }
                   if((aux.getSiguiente()==inicio) && (aux.getDato()<d)){
                            aux.setSiguiente(nuevo);
                            nuevo.setAnterior(aux);
                            nuevo.setSiguiente(inicio);
                            inicio.setAnterior(nuevo);
                   }else{
                            Nodo ant=aux.getAnterior();
                            nuevo.setAnterior(ant);
                            ant.setSiguiente(nuevo);
                            nuevo.setSiguiente(aux);
                            aux.setAnterior(nuevo);
                            if((aux==inicio) && (inicio.getDato()>d))
                                     inicio=nuevo;
                   }
         }
       }






Método imprimir

       public void imprimir(){
         if(inicio==null)
                   System.out.println("<-->NULL<-->");
         else{
                   Nodo aux=inicio;
                   System.out.print("<--> Inicio");
                   do{
                            System.out.print(" <--> "+aux.getDato());
                            aux=aux.getSiguiente();
                   }while(aux!=inicio);
                   System.out.println(" <-->NULL<-->");
         }
       }

Método buscar elemento

       public boolean buscar(Integer d){
         Nodo aux=inicio;
         while((aux.getSiguiente()!=inicio) && (!(aux.getDato().equals(d))))
                   aux=aux.getSiguiente();
         return aux.getDato().equals(d);
       }
      

Creación de un nodo de entrada en Java

Un nodo de entrada se utiliza para recibir un mensaje en un flujo de mensajes, normalmente de un origen no soportado por los nodos de entr...