Exemplul următor arată cum să dezvolte un Java Aplicație numită CrnpClient că CRNP utilizează. Aplicația înregistrează rechemarea evenimentelor cu serverul CRNP al clusterului, ascultă evenimente și procesează aceste evenimente prin tipărirea conținutului său. Înainte de finalizare, aplicația anulează înregistrarea cererii dvs. de rechemare a evenimentelor.
Notă Următoarele puncte Când examinați acest exemplu:
-
Exemplul de aplicație generează și Analizează XML cu Jaxp (API Java pentru procesarea XML). Acest exemplu nu arată cum să utilizați JAXP. Acest instrument este descris mai detaliat în http://java.sun.com/xml/jaxp/index.html.
-
Acest exemplu prezintă părți ale unei aplicații, care este descrisă integral în Anexa G, aplicație crnpclient.java. Pentru a explica mai eficient anumite concepte, exemplul acestui capitol variază ușor de la aplicația completă prezentată în Anexa G, Crnpclient.java aplicație.
-
Pentru a fi mai concis, nu exemplu cod delimitatoarele au fost incluse în acest capitol. Pentru a le vedea, consultați aplicația completă în aplicația Anexă G, CRNPCLINT.java.
-
Aplicația care apare în acest exemplu gestionează majoritatea condițiilor de eroare prin simpla închidere a aplicației. Aplicația reală ar trebui să trateze erorile mai ferm.
Cum se configurează mediul
pași
-
Descărcați și instalați Jaxp și versiunea corectă a compilatorului Java și a mașinii virtuale Java.
Puteți găsi instrucțiuni despre http://java.sun.com/xml/jaxp/index.html.
Notă –
Acest exemplu necesită cel puțin Java 1.3.1.
-
În cazul în care fișierul sursă este amplasat, tastați următoarele:
% javac -classpath jaxp-root/dom.jar:jaxp-rootjaxp-api. \jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \.jar:jaxp-root/xsltc.jar -sourcepath . source-filename.java
În cazul în care Jaxp-Root este traseul absolut sau relativ în directorul în care fișierele JAXP și sursă-fișiere de fișiere sunt numele fișierului de origine Java.
Dacă ClassaTh este inclus în linia de comandă de compilare, se va asigura că compilatorul poate găsi clase JAXP.
-
Rulați aplicația, specificați Calea de clasă în clasa de clasă, astfel încât Aplicația poate rula fișierele de clasă JAXP corecte (țineți-o în cuant La care primele trasee de la ClassaTh indică directorul curent):
Acum că mediul a fost configurat Puteți dezvolta aplicația .
Cum să începem dezvoltarea aplicației
În această parte a exemplului, trebuie să creați o clasă de bază numită CrNpClient cu o metodă principală care analizează argumentele liniei de comandă și construirea unui obiect crnpclient. Acest obiect trece argumentele liniei de comandă la clasă, așteptați ca utilizatorul să termine aplicația, oprirea apelului în clasa și vânzarea CrnpClient.
Builder Clasa CrnpClient trebuie să ruleze următoarele sarcini: /p>
-
Creați un subprocess care primește reduceri de evenimente.
-
Contactați serverul CRNP și registrul de evenimente.
Configurați obiectele de proces XML.
etapa
Creați codul Java care aplică logica anterioară.
Exemplul următor arată codul structurii de bază a clasei CRNPClient. Implementările metodelor auxiliare menționate în metodele de închidere și constructor sunt prezentate mai jos în acest capitol, rețineți că este prezentat codul care contează toate pachetele necesare.
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;}
Variabilele membrilor sunt descrise mai târziu în acest capitol.
Cum se analizează argumentele liniei de comenzi
etapa
Pentru a analiza argumentele liniei de comandă, consultați codul inclus în Anexa G, CRNPCLINT.java.
Cum să definiți evenimentul care primește subprocesul
în cod, trebuie să verificați dacă recepția evenimentelor se efectuează într-un fir separat, astfel încât aplicația să poată continua să efectueze cealaltă lucrare, în timp ce subprocesul evenimentului este blocat și reapelarea evenimentelor așteptate.
Notă –
Configurația XML este descrisă mai târziu în acest capitol.
pași
-
în cod, definiți Subclasa firului numită EventRecePtionTCread care creează o priză, serververchetă și se așteaptă la recepția evenimentelor în soclu.
În această parte a codului eșantionului, evenimentele nu știu citite sau sunt procesate. Citirea și prelucrarea evenimentelor sunt descrise mai târziu în acest capitol.EventRecePtionThRead creează o socket, serverversocket, într-o adresă de protocol de intenție cu metacaractere. EventReceptionThread Menține, de asemenea, o referire la obiectul CRNPClient, astfel încât EvenceReceptionTCreadCread-ul să poată trimite evenimente la obiectul CRNpClient pentru procesare.
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;}
-
Construiți un obiect Createevtrecepthr.
private void createEvtRecepThr() throws Exception{ evtThr = new EventReceptionThread(this); evtThr.start();}
Cum se înregistrează redus sau anulează înregistrarea
Procesul de înregistrare implică următoarele acțiuni:
-
Deschideți o priză de bază TCP pentru portul și înregistrarea Protocol Interred
-
Creați mesajul jurnal XML
-
Trimiteți mesajul jurnal XML pe soclu
-
Citiți mesajul de răspuns XML din soclu
-
Închideți soclul
etape
-
Creați codul Java care aplică logica anterioară.
Următorul cod de eșantionare arată implementarea metodei de registruCallbacks a clasei CRNPClient (numită de constructorul CRNPClient). Apelurile la CreareRegistrationStringStringStringStringRePly () sunt descrise mai detaliate mai detaliate în acest capitol.
regig și regort sunt obiecte de membru configurate de 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();}
-
Aplicați metoda Unregisterului.
Metoda de închidere a CRNpClient solicită această metodă. Implementarea createunegistrationString este descrisă mai detaliată mai târziu în acest capitol.
private void unregister() throws Exception{ Socket sock = new Socket(regIp, regPort); String xmlStr = createUnregistrationString(); PrintStream ps = new PrintStream(sock.getOutputStream()); ps.print(xmlStr); readRegistrationReply(sock.getInputStream()); sock.close();}
-
creare codul Java care aplică logica anterioară.
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;}
-
Implementarea evenimentului și a clasei NVPAIR.
Rețineți că clasa Callbackreg utilizează evenimentul, care în rândul său, utilizează o clasă 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;}
Cum se generează XML
acum că structura aplicației a fost configurată și ea A fost scris tot codul de rețea, codul care generează și analizează XML trebuie să fie scris. În primul rând, scrieți codul care generează mesajul de registry XML SC_CALLACK_REG.
un mesaj SC_CALLBACK_REG este format dintr-un tip de înregistrare (add_client, remove_client, add_events sau eliminare_events), un port de redial și o listă de evenimente de interes . Fiecare eveniment este alcătuit dintr-o clasă și o subclasă, urmată de o listă de nume de nume și valori.
În această parte a exemplului, este scrisă o clasă Callbogereg care economisește tipul de înregistrare, portul de redial și lista evenimentelor de înregistrare. Această clasă poate fi, de asemenea, serializată pentru un mesaj XML SC_CALLBACK_REG.
O metodă interesantă din această clasă este converttoxml, care creează un șir de mesaje XML SC_CALLACK_REG de la membrii de clasă. Documentația JAXP localizată în http://java.sun.com/xml/jaxp/index.html descrie mai detaliat codul acestei metode mai detaliat.
Implementarea clasei de evenimente este afișată în următorul cod de probă. Rețineți că clasa Callbackreg utilizează o clasă de evenimente, care vă permite să stocați un eveniment și să îl convertiți într-un element, element, XML.
pași
Cum se creează mesaje de registry și mesaje de anulare
Odată ce clasele sunt create de la auxiliarul Generarea mesajelor XML, puteți scrie implementarea metodei CreateRegistrationStringString. ÎnregistrareCallback-urile solicită această metodă; Acest proces este descris în modul de înregistrare redus sau anulează registrul.
CreareReGistrationString construiește un obiect Callbackregreg și stabilește portul și tipul de înregistrare. În continuare, CreațiReregrationString construiește diverse evenimente prin metodele de creare auxiliare, creatememberShipevent, create și create. Fiecare eveniment este adăugat la obiectul Callllbackreg după crearea acestuia. În cele din urmă, CreateReGistrationString invocă metoda Converttoxml din obiectul Callbox pentru a prelua mesajul XML în formularul de șir.
Rețineți că variabila de membru MG stochează argumentele liniei de comandă furnizate de utilizator pentru aplicație. Al cincilea argument și urmăresc specificarea evenimentelor pentru care trebuie înregistrată cererea. Al patrulea argument specifică tipul de înregistrare, dar este ignorat în acest exemplu. Codul complet inclus în aplicația Anexă G, Crnpclient.java arată cum să utilizați acest al patrulea argument.
pași
-
Creați codul Java care aplică logica anterioară .
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);}
-
Creați șirul de anulare a înregistrării
Crearea șirului de anulare a înregistrării este un proces mai simplu decât Crearea lanțului de înregistrare, deoarece nu este necesar să se adapteze evenimentele.
Cum se configurează Analizorul XML
Odată ce codul de generare XML și din rețeaua de aplicare , Builder CRNPClient solicită metoda SetupxmlProcessing, care creează un obiect DocumentBuilderFactory și stabilește mai multe proprietăți de analiză în acel obiect. Documentația JAXP descrie această metodă mai detaliată. Vedeți http://java.sun.com/xml/jaxp/index.html.
etapa
Creați codul Java care aplică logica anterioară.
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);}
Cum se analizează mesajul de răspuns în înregistrare
Pentru a scana mesajul XML SC_REPLY pe care CRNP trimite răspuns la un răspuns la o Mesaj de înregistrare sau anulare, este necesar să aveți o clasă auxiliară regreply, care poate fi construită dintr-un document XML. Această clasă oferă accesorii pentru codul de stare și mesajul de stare. Pentru a analiza secvența XML a serverului, este necesar să se creeze un nou document XML și să utilizați metoda de analiză. Jaxp Documentația situată în http://java.sun.com/xml/jaxp/index.html descrie această metodă mai detaliată.
Etape
-
Creați codul Java care aplică logica anterioară.
Rețineți că metoda ReadRegistrationRePly utilizează noua clasă regreply.
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);}
-
Implementarea clasei regreply.
Rețineți că metoda RetrieveValues rulează prin copacul DOM al documentului XML și extrage codul și mesajul de stare. Documentația Jaxp situată în http://java.sun.com/xml/jaxp/index.html Conține mai multe informații.
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;}
-
Creați codul Java care aplică logica anterioară.
Vă rugăm să rețineți că acest cod este similar cu cel al clasei regreply, care este descrisă cu privire la modul de analiză a mesajului de răspuns la înregistrare.
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;
-
Implementați producători și metode suplimentare ale clasei NVPAIR compatibile cu analiza XML.
Modificările efectuate în cazul prezentat în etapa 1 trebuie, de asemenea, efectuate în clasa 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); }}
-
Implementați în timp ce buclă în EventReceptionThread, care așteaptă rechemările evenimentelor.
EventRecePtionCreadTCAD este descrisă Cu privire la modul de definire a subprocesului de chitanță a evenimentului.
while(true) { Socket sock = listeningSock.accept(); Document doc = db.parse(sock.getInputStream()); Event event = new Event(doc); client.processEvent(event); sock.close(); }
Cum se analizează evenimentele de rediere
Pasul final este de a analiza și procesa evenimentele Reale de reapelare. Pentru a vă ajuta în această sarcină, trebuie să modificați clasa evenimentului creat cu privire la modul de generare XML, astfel încât această clasă să poată construi un eveniment, de la un document XML și să creeze un element, element, xml: această schimbare necesită un constructor suplimentar ( Aceasta include un document XML), o metodă de preluare, adăugând două variabile de membru (furnizor și editor), metode de acces pentru toate câmpurile și, în final, o metodă de imprimare.
pași
Cum se ruleze aplicația
Pași
-
Deveniți un superuser sau presupuneți o funcție similară.
-
Executarea aplicației.
# java CrnpClient crnpHost crnpPort localPort ...
Codul complet al aplicației CRNPClient este afișat în Anexa G, aplicația CRNpClient.java.