Exemplo de creación dunha aplicación Java que usa CRNP

O seguinte exemplo mostra como desenvolver un Java Aplicación chamada crnpclient que usa CRNP. A aplicación rexistra recordar eventos co servidor CRNP do clúster, escoita eventos e procesa estes eventos imprimindo o seu contido. Antes de finalizar, a aplicación cancela o rexistro da súa solicitude de recordos de eventos.

Nota os seguintes puntos ao examinar este exemplo:

  • O exemplo de aplicación xera e Analiza XML con JAXP (Java API para procesamento XML). Este exemplo non mostra como usar JAXP. Esta ferramenta descríbese con máis detalle en http://java.sun.com/xml/jaxp/index.html.

  • Este exemplo presenta partes dunha aplicación, que se describe completa no apéndice G, aplicación crnpclient.java. Para explicar conceptos de forma máis efectiva, o exemplo deste capítulo varía lixeiramente da aplicación completa presentada na aplicación Apéndice G, CRNPClient.Java.

  • para ser máis conciso, non código de exemplo Incluíronse delimitadores neste capítulo. Para velos, consulte a aplicación completa na aplicación Apéndice G, CRNPClient.Java.

  • A aplicación que aparece neste exemplo xestiona a maioría das condicións de erro simplemente pechando a aplicación. A aplicación real debe tratar os erros máis firmemente.

Como configurar o ambiente

Pasos
  1. Descarga e instala JAXP e a versión correcta do compilador Java e a máquina virtual de Java.

    Pode atopar instrucións en http://java.sun.com/xml/jaxp/index.html.

    Nota –

    Este exemplo require polo menos Java 1.3.1.

  2. No directorio onde se atopa o ficheiro fonte, escriba o seguinte:

    Onde Jaxp-root é a ruta absoluta ou relativa ao directorio onde os ficheiros JAXP e fonte de ficheiro residen son o nome do ficheiro Java de orixe.

    Se ClassPath está incluído na liña de comandos de compilación, asegurarase de que o compilador poida atopar clases de JAXP.

  3. Executar a aplicación, especificar a ruta de clase en ClassPath para que o A aplicación pode executar os ficheiros de clase JAXP correctos (manteña en cuente A que a primeira ruta de clase apunta ao directorio actual):

    Agora que o ambiente foi configurado pode desenvolver a aplicación .

Como comezar a desenvolver a aplicación

Nesta parte do exemplo, debes crear unha clase básica chamada crnpclient cun método principal que analiza Os argumentos da liña de comandos e construír un obxecto CRNPClient. Este obxecto pasa os argumentos da liña de comandos á clase, agarde que o usuario finalice a aplicación, chame a apagado na clase CRNPClient e a venda.

O CRNPClient Class Builder debe executar as seguintes tarefas:

  • Configure os obxectos do proceso XML.

  • Crear un subproceso que recibe reducións de eventos.

  • Póñase en contacto co servidor CRNP e rexistrar REDIARS de eventos.

Paso

    Crea o código Java que aplica a lóxica anterior.

    O seguinte exemplo mostra o código da estrutura básica da clase CRNPClient. As implementacións dos métodos auxiliares a que se refiren os métodos de peche e o constructor móstranse a continuación neste capítulo, ten en conta que o código que importa todos os paquetes necesarios móstranse.

    import javax.xml.parsers.*;import javax.xml.transform.*;import javax.xml.transform.dom.*;import javax.xml.transform.stream.*;import org.xml.sax.*;import org.xml.sax.helpers.*;import org.w3c.dom.*;import java.net.*;import java.io.*;import java.util.*;class CrnpClient{ public static void main(String args) { InetAddress regIp = null; int regPort = 0, localPort = 0; try { regIp = InetAddress.getByName(args); regPort = (new Integer(args)).intValue(); localPort = (new Integer(args)).intValue(); } catch (UnknownHostException e) { System.out.println(e); System.exit(1); } CrnpClient client = new CrnpClient(regIp, regPort, localPort, args); System.out.println("Hit return to terminate demo..."); try { System.in.read(); } catch (IOException e) { System.out.println(e.toString()); } client.shutdown(); System.exit(0); } public CrnpClient(InetAddress regIpIn, int regPortIn, int localPortIn, String clArgs) { try { regIp = regIpIn; regPort = regPortIn; localPort = localPortIn; regs = clArgs; setupXmlProcessing(); createEvtRecepThr(); registerCallbacks(); } catch (Exception e) { System.out.println(e.toString()); System.exit(1); } } public void shutdown() { try { unregister(); } catch (Exception e) { System.out.println(e); System.exit(1); } } private InetAddress regIp; private int regPort; private EventReceptionThread evtThr; private String regs; public int localPort; public DocumentBuilderFactory dbf;}

    As variables membros descríbense máis tarde neste capítulo.

Como analizar os argumentos da liña de comandos

Paso

    Para analizar os argumentos da liña de comandos, consulte o código incluído na aplicación Apéndice G, CRNPClient.Java.

Como definir o subproceso de recepción do evento

No código, ten que verificar que a recepción de eventos realízase nun fío separado para que a aplicación poida continuar a realizar o outro traballo, mentres que o subproceso do evento está bloqueado e reforma de eventos esperados.

Nota –

A configuración XML descríbese máis tarde neste capítulo.

Pasos
  1. No código, define A subclase do fío chamou eventrecepción, que crea un socket, servidores e espera que a recepción dos eventos no socket.

    Nesta parte do código de mostra, os eventos non saben que len ou son procesados. A lectura eo tratamento de eventos descríbense máis tarde neste capítulo.EventReceptionThread crea un soquete, ServersCocket, nun enderezo de protocolo intendenction con caracteres especiais. EventReceptionThread tamén mantén unha referencia ao obxecto CRNPClient para que EventReceptionThread pode enviar eventos para o obxecto CRNPClient para procesamento.

    class EventReceptionThread extends Thread{ public EventReceptionThread(CrnpClient clientIn) throws IOException { client = clientIn; listeningSock = new ServerSocket(client.localPort, 50, InetAddress.getLocalHost()); } public void run() { try { DocumentBuilder db = client.dbf.newDocumentBuilder(); db.setErrorHandler(new DefaultHandler()); while(true) { Socket sock = listeningSock.accept(); // Construct event from the sock stream and process it sock.close(); } // UNREACHABLE } catch (Exception e) { System.out.println(e); System.exit(1); } } /* private member variables */ private ServerSocket listeningSock; private CrnpClient client;}
  2. Construír un obxecto createevtrecu.

    private void createEvtRecepThr() throws Exception{ evtThr = new EventReceptionThread(this); evtThr.start();}

Como rexistrarse reducido ou cancelar o rexistro

O proceso de rexistro implica as seguintes accións:

  • Abrir unha socket TCP básica para o porto e rexistro Protocolo enterrado

  • Crea a mensaxe de rexistro XML

  • Enviar a mensaxe de rexistro XML no socket

  • Ler a mensaxe de resposta XML fóra de socket

  • Pechar o socket

Pasos
  1. Crea o código Java que aplica a lóxica anterior.

    O seguinte código de mostra mostra a implementación do método de rexistro de RegisterClacks da clase CRNPClient (chamada polo constructor CRNPClient). Chamadas a CreeAcEegistrationString () e ReadRegistrationReply () descríbense máis detalladas máis tarde neste capítulo.

    Regip and Regort son obxectos membros configurados polo constructor.

    private void registerCallbacks() throws Exception{ Socket sock = new Socket(regIp, regPort); String xmlStr = createRegistrationString(); PrintStream ps = new PrintStream(sock.getOutputStream()); ps.print(xmlStr); readRegistrationReply(sock.getInputStream(); sock.close();}
  2. Aplicar o método de non rexión.

    O método de apagado de CRNPClient chama este método. A implementación de CreateunegistrationString descríbese máis detallada máis tarde neste capítulo.

Como xerar XML

Agora que a estrutura da aplicación foi configurada e Escribiuse todo o código de rede, debe escribirse o código que xera e análises XML debe escribirse. En primeiro lugar, escriba o código que xera a mensaxe de rexistro XML SC_COLLBACK_REG.

Unha mensaxe SC_CALLBACK_REG está formada por un tipo de rexistro (ADD_CLIENT, RIVE_CLIENT, ADD_EVENTS ou DELEMINE_EVENTS), un porto de remarca e unha lista de eventos de interese .. Cada evento consta dunha clase e unha subclase, seguida dunha lista de nomes de nomes e valores.

Nesta parte do exemplo, unha clase de CallBackreg está escrita que salva o tipo de rexistro, o porto de Redial e a lista de eventos de rexistro. Esta clase tamén pode ser serializada para unha mensaxe XML SC_Callback_Reg.

Un método interesante desta clase é converttoxml, que crea unha cadea de mensaxes XML SC_Callback_reg dos membros da clase. A documentación de Jaxp situada en http://java.sun.com/xml/jaxp/index.html describe máis detallado o código deste método máis detallado.

A implementación da clase de eventos amósase no seguinte código de mostra. Teña en conta que a clase de CallBackreg usa unha clase de eventos, que permite almacenar un evento e convertelo nun elemento, elemento, xml.

Pasos
  1. Crear O código Java que aplica a lóxica anterior.

    class CallbackReg{ public static final int ADD_CLIENT = 0; public static final int ADD_EVENTS = 1; public static final int REMOVE_EVENTS = 2; public static final int REMOVE_CLIENT = 3; public CallbackReg() { port = null; regType = null; regEvents = new Vector(); } public void setPort(String portIn) { port = portIn; } public void setRegType(int regTypeIn) { switch (regTypeIn) { case ADD_CLIENT: regType = "ADD_CLIENT"; break; case ADD_EVENTS: regType = "ADD_EVENTS"; break; case REMOVE_CLIENT: regType = "REMOVE_CLIENT"; break; case REMOVE_EVENTS: regType = "REMOVE_EVENTS"; break; default: System.out.println("Error, invalid regType " + regTypeIn); regType = "ADD_CLIENT"; break; } } public void addRegEvent(Event regEvent) { regEvents.add(regEvent); } public String convertToXml() { Document document = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.newDocument(); } catch (ParserConfigurationException pce) { // Parser with specified options can't be built pce.printStackTrace(); System.exit(1); } // Create the root element Element root = (Element) document.createElement("SC_CALLBACK_REG"); // Add the attributes root.setAttribute("VERSION", "1.0"); root.setAttribute("PORT", port); root.setAttribute("regType", regType); // Add the events for (int i = 0; i < regEvents.size(); i++) { Event tempEvent = (Event) (regEvents.elementAt(i)); root.appendChild(tempEvent.createXmlElement(document)); } document.appendChild(root); // Convert the whole thing to a string DOMSource domSource = new DOMSource(document); StringWriter strWrite = new StringWriter(); StreamResult streamResult = new StreamResult(strWrite); TransformerFactory tf = TransformerFactory.newInstance(); try { Transformer transformer = tf.newTransformer(); transformer.transform(domSource, streamResult); } catch (TransformerException e) { System.out.println(e.toString()); return (""); } return (strWrite.toString()); } private String port; private String regType; private Vector regEvents;}
  2. Implementar os eventos e as clases de NVPAIR.

    Teña en conta que a clase de CallBackreg usa evento que en Turn usa unha clase NVPAIR.

    class Event{ public Event() { regClass = regSubclass = null; nvpairs = new Vector(); } public void setClass(String classIn) { regClass = classIn; } public void setSubclass(String subclassIn) { regSubclass = subclassIn; } public void addNvpair(NVPair nvpair) { nvpairs.add(nvpair); } public Element createXmlElement(Document doc) { Element event = (Element) doc.createElement("SC_EVENT_REG"); event.setAttribute("CLASS", regClass); if (regSubclass != null) { event.setAttribute("SUBCLASS", regSubclass); } for (int i = 0; i < nvpairs.size(); i++) { NVPair tempNv = (NVPair) (nvpairs.elementAt(i)); event.appendChild(tempNv.createXmlElement(doc)); } return (event); } private String regClass, regSubclass; private Vector nvpairs;}class NVPair{ public NVPair() { name = value = null; } public void setName(String nameIn) { name = nameIn; } public void setValue(String valueIn) { value = valueIn; } public Element createXmlElement(Document doc) { Element nvpair = (Element) doc.createElement("NVPAIR"); Element eName = doc.createElement("NAME"); Node nameData = doc.createCDATASection(name); eName.appendChild(nameData); nvpair.appendChild(eName); Element eValue = doc.createElement("VALUE"); Node valueData = doc.createCDATASection(value); eValue.appendChild(valueData); nvpair.appendChild(eValue); return (nvpair); } private String name, value;}

Como crear mensaxes de rexistro e mensaxes de cancelación

Unha vez creados as clases a partir do auxiliar Xerando mensaxes XML, pode escribir a implementación do CreeAcEegistrationTring Method. Os rexistros de rexistro chama este método; Este proceso descríbese como rexistrarse reducido ou cancelar o rexistro.

CreeAcEegistrationString constrúe un obxecto de CallBackreg e establece o seu porto e tipo de rexistro. A continuación, CreeAcEegistrationSting constrúe varios eventos a través dos métodos do creatallevento auxiliar, createmembershipevent, creación e creeAcrevent. Cada evento engádese ao obxecto callbackreg despois de crealo. Finalmente, CreeAreAcExistrationString invoca o método de converttoxml no obxecto de CallBackreg para recuperar a mensaxe XML no formulario de cadea.

Teña en conta que a variable de membro regs almacena os argumentos da liña de comandos proporcionada polo usuario para a aplicación. O quinto argumento e despois especifica os eventos para os que a solicitude debe ser gravada. O cuarto argumento especifica o tipo de rexistro, pero é ignorado neste exemplo. O código completo incluído no Apéndice G, CRNPClient.Java Aplicación mostra como usar este cuarto argumento.

Pasos
  1. Crea o código Java que aplica a lóxica anterior ..

    private String createRegistrationString() throws Exception{ CallbackReg cbReg = new CallbackReg(); cbReg.setPort("" + localPort); cbReg.setRegType(CallbackReg.ADD_CLIENT); // add the events for (int i = 4; i < regs.length; i++) { if (regs.equals("M")) { cbReg.addRegEvent(createMembershipEvent()); } else if (regs.equals("A")) { cbReg.addRegEvent(createAllEvent()); } else if (regs.substring(0,2).equals("RG")) { cbReg.addRegEvent(createRgEvent(regs.substring(3))); } else if (regs.substring(0,1).equals("R")) { cbReg.addRegEvent(createREvent(regs.substring(2))); } } String xmlStr = cbReg.convertToXml(); return (xmlStr);}private Event createAllEvent(){ Event allEvent = new Event(); allEvent.setClass("EC_Cluster"); return (allEvent);}private Event createMembershipEvent(){ Event membershipEvent = new Event(); membershipEvent.setClass("EC_Cluster"); membershipEvent.setSubclass("ESC_cluster_membership"); return (membershipEvent);}private Event createRgEvent(String rgname){ Event rgStateEvent = new Event(); rgStateEvent.setClass("EC_Cluster"); rgStateEvent.setSubclass("ESC_cluster_rg_state"); NVPair rgNvpair = new NVPair(); rgNvpair.setName("rg_name"); rgNvpair.setValue(rgname); rgStateEvent.addNvpair(rgNvpair); return (rgStateEvent);}private Event createREvent(String rname){ Event rStateEvent = new Event(); rStateEvent.setClass("EC_Cluster"); rStateEvent.setSubclass("ESC_cluster_r_state"); NVPair rNvpair = new NVPair(); rNvpair.setName("r_name"); rNvpair.setValue(rname); rStateEvent.addNvpair(rNvpair); return (rStateEvent);}
  2. Crea a cadea de cancelación de rexistro.

    Creación A cadea de cancelación de rexistro é un proceso máis sinxelo que o Creación da cadea de rexistro, xa que non é necesario adaptar eventos.

    private String createUnregistrationString() throws Exception{ CallbackReg cbReg = new CallbackReg(); cbReg.setPort("" + localPort); cbReg.setRegType(CallbackReg.REMOVE_CLIENT); String xmlStr = cbReg.convertToXml(); return (xmlStr);}

Como configurar o analizador XML

Unha vez que o código de xeración XML e desde a rede para a aplicación , o creador CRNPClient chama o método setupxmlprocesing, que crea un obxecto de documento e establece varias propiedades de análise nese obxecto. A documentación de Jaxp describe este método máis detallado. Vexa http://java.sun.com/xml/jaxp/index.html.

Paso

    Crea o código Java que aplica a lóxica anterior.

    private void setupXmlProcessing() throws Exception{ dbf = DocumentBuilderFactory.newInstance(); // We don't need to bother validating dbf.setValidating(false); dbf.setExpandEntityReferences(false); // We want to ignore comments and whitespace dbf.setIgnoringComments(true); dbf.setIgnoringElementContentWhitespace(true); // Coalesce CDATA sections into TEXT nodes. dbf.setCoalescing(true);}

Como analizar a mensaxe de resposta de rexistro

Para escanear a mensaxe XML SC_Reply que CRNP envía a resposta a un Rexistro ou mensaxe de cancelación, é necesario ter unha clase auxiliar, que pode ser construída a partir dun documento XML. Esta clase ofrece accesorios para o código de estado e a mensaxe de estado. Para analizar a secuencia XML do servidor, é necesario crear un novo documento XML e usar o seu método de análise. Documentación de JAXP situada en http://java.sun.com/xml/jaxp/index.html describe este método máis detallado.

Pasos
  1. Crea o código Java que aplica o Lóxica anterior.

    Teña en conta que o método ReadRegistreReply usa a nova clase de lamento.

    private void readRegistrationReply(InputStream stream) throws Exception{ // Create the document builder DocumentBuilder db = dbf.newDocumentBuilder(); db.setErrorHandler(new DefaultHandler()); //parse the input file Document doc = db.parse(stream); RegReply reply = new RegReply(doc); reply.print(System.out);}
  2. implementar a clase de lamento.

    Teña en conta que o método de recuperaciónValues execútase a través da árbore DOM do documento XML e extrae o código e a mensaxe de estado. A documentación de JAXP situada en http://java.sun.com/xml/jaxp/index.html contén máis información.

    class RegReply{ public RegReply(Document doc) { retrieveValues(doc); } public String getStatusCode() { return (statusCode); } public String getStatusMsg() { return (statusMsg); } public void print(PrintStream out) { out.println(statusCode + ": " + (statusMsg != null ? statusMsg : "")); } private void retrieveValues(Document doc) { Node n; NodeList nl; String nodeName; // Find the SC_REPLY element. nl = doc.getElementsByTagName("SC_REPLY"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "SC_REPLY node."); return; } n = nl.item(0); // Retrieve the value of the statusCode attribute statusCode = ((Element)n).getAttribute("STATUS_CODE"); // Find the SC_STATUS_MSG element nl = ((Element)n).getElementsByTagName("SC_STATUS_MSG"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "SC_STATUS_MSG node."); return; } // Get the TEXT section, if there is one. n = nl.item(0).getFirstChild(); if (n == null || n.getNodeType() != Node.TEXT_NODE) { // Not an error if there isn't one, so we just silently return. return; } // Retrieve the value statusMsg = n.getNodeValue(); } private String statusCode; private String statusMsg;}

Como analizar os eventos de remarcar

O paso final é analizar e procesar os eventos Reales de Redial. Para axudarche nesta tarefa, debes modificar a clase de eventos creada sobre como xerar XML para que esta clase poida construír un evento, evento, desde un documento XML e crear un elemento, elemento, XML: este cambio require un constructor adicional ( que inclúe un documento XML), un método de recuperación, engadindo dúas variables membros (provedor e editor), métodos de acceso para todos os campos e, finalmente, un método de impresión.

Pasos
  1. Crea o código Java que aplica a lóxica anterior.

    Ten en conta que este código é similar ao da clase de grao, que se describe sobre como analizar a mensaxe de resposta de rexistro.

    public Event(Document doc) { nvpairs = new Vector(); retrieveValues(doc); } public void print(PrintStream out) { out.println("\tCLASS=" + regClass); out.println("\tSUBCLASS=" + regSubclass); out.println("\tVENDOR=" + vendor); out.println("\tPUBLISHER=" + publisher); for (int i = 0; i < nvpairs.size(); i++) { NVPair tempNv = (NVPair) (nvpairs.elementAt(i)); out.print("\t\t"); tempNv.print(out); } } private void retrieveValues(Document doc) { Node n; NodeList nl; String nodeName; // Find the SC_EVENT element. nl = doc.getElementsByTagName("SC_EVENT"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "SC_EVENT node."); return; } n = nl.item(0); // // Retrieve the values of the CLASS, SUBCLASS, // VENDOR and PUBLISHER attributes. // regClass = ((Element)n).getAttribute("CLASS"); regSubclass = ((Element)n).getAttribute("SUBCLASS"); publisher = ((Element)n).getAttribute("PUBLISHER"); vendor = ((Element)n).getAttribute("VENDOR"); // Retrieve all the nv pairs for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) { nvpairs.add(new NVPair((Element)child)); } } public String getRegClass() { return (regClass); } public String getSubclass() { return (regSubclass); } public String getVendor() { return (vendor); } public String getPublisher() { return (publisher); } public Vector getNvpairs() { return (nvpairs); } private String vendor, publisher;
  2. Implementar fabricantes e métodos adicionais da clase NVPAIR compatible con análise XML.

    Os cambios feitos no evento mostrado no paso 1 tamén deben realizarse na clase NVPAIR.

    public NVPair(Element elem) { retrieveValues(elem); } public void print(PrintStream out) { out.println("NAME=" + name + " VALUE=" + value); } private void retrieveValues(Element elem) { Node n; NodeList nl; String nodeName; // Find the NAME element nl = elem.getElementsByTagName("NAME"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "NAME node."); return; } // Get the TEXT section n = nl.item(0).getFirstChild(); if (n == null || n.getNodeType() != Node.TEXT_NODE) { System.out.println("Error in parsing: can't find " + "TEXT section."); return; } // Retrieve the value name = n.getNodeValue(); // Now get the value element nl = elem.getElementsByTagName("VALUE"); if (nl.getLength() != 1) { System.out.println("Error in parsing: can't find " + "VALUE node."); return; } // Get the TEXT section n = nl.item(0).getFirstChild(); if (n == null || n.getNodeType() != Node.TEXT_NODE) { System.out.println("Error in parsing: can't find " + "TEXT section."); return; } // Retrieve the value value = n.getNodeValue(); } public String getName() { return (name); } public String getValue() { return (value); }}
  3. Implementar o ciclo de tempo en eventrececepciónThread, que agarda as lembranzas dos eventos.

    EventreceptionThread descríbese sobre como definir o subproceso de recepción do evento.

    while(true) { Socket sock = listeningSock.accept(); Document doc = db.parse(sock.getInputStream()); Event event = new Event(doc); client.processEvent(event); sock.close(); }

Como executar a aplicación

Pasos
  1. Tornouse un superusuario ou asume unha función similar.

  2. Executar a aplicación.

    # java CrnpClient crnpHost crnpPort localPort ...

    O código completo da aplicación CRNPClient aparece no apéndice G, aplicación crnpclient.java.

Deixa unha resposta

O teu enderezo electrónico non se publicará Os campos obrigatorios están marcados con *