O próximo exemplo mostra como desenvolver um Java Aplicativo chamado CRNPClient que o CRNP usa. Os registros de aplicativos recordam de eventos com o servidor CRNP do cluster, ouve eventos e processa esses eventos imprimindo seu conteúdo. Antes de finalizar, o aplicativo cancela o registro de sua solicitação de recalls de eventos.
Observe os seguintes pontos ao examinar este exemplo:
-
O exemplo do aplicativo gera e Analisa XML com JAXP (Java API para processamento XML). Este exemplo não mostra como usar o JAXP. Esta ferramenta é descrita em mais detalhes em http://java.sun.com/xml/jaxp/index.html.
-
Este exemplo apresenta partes de um aplicativo, que é descrito na íntegra no apêndice G, aplicativo crnpclient.java. Para explicar mais efetivamente certos conceitos, o exemplo deste capítulo varia ligeiramente a partir do aplicativo completo apresentado no aplicativo do Apêndice G, CRNPCLIENT.JAVA.
-
Para ser mais conciso, não o código de exemplo Delimitadores foram incluídos neste capítulo. Para vê-los, consulte o aplicativo completo no aplicativo do Apêndice G, CRNPCLIENT.JAVA.
-
O aplicativo que aparece neste exemplo gerencia a maioria das condições de erro simplesmente fechando o aplicativo. A aplicação real deve tratar erros com mais firmeza.
como configurar o ambiente
etapas
-
Baixe e instale o JAXP e a versão correta do compilador Java e Java Virtual Machine.
Você pode encontrar instruções sobre http://java.sun.com/xml/jaxp/index.html.
Nota –
Este exemplo requer pelo menos Java 1.3.1.
-
no diretório em que o arquivo de origem está localizado, digite o seguinte:
% 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
Onde Jaxp-raiz é a rota absoluta ou relativa para o diretório onde os arquivos JAXP e Filename-Filename residem é o nome do arquivo java de origem.
Se o ClassPath estiver incluído na linha de comando de compilação, ele garantirá que o compilador possa encontrar aulas JAXP.
-
Execute o aplicativo, especifique o caminho da classe em classpath para que o Aplicativo pode executar os arquivos corretos de classe JAXP (segure em Cuent Para o qual a primeira rota de classe aponta para o diretório atual):
Agora que o ambiente foi configurado Você pode desenvolver o aplicativo .
Como começar a desenvolver o aplicativo
Nesta parte do exemplo, você deve criar uma classe básica chamada CRNPClient com um método principal que analisa os argumentos da linha de comando e construir um objeto crnpclient. Este objeto passa os argumentos da linha de comando para a classe, aguarde o usuário terminar o aplicativo, chamar o desligamento na classe CRNPClient.
O construtor de classe CRNPClient deve executar as seguintes tarefas:
-
Configure os objetos do processo XML.
-
Crie um subprocesso que recebe reduções de eventos.
-
Entre em contato com o servidor CRNP e registre rediscamentos de eventos.
step
Crie o código Java que aplica a lógica anterior.
O exemplo a seguir mostra o código da estrutura básica da classe CRNPClient. As implementações dos métodos auxiliares referidos nos métodos de fechamento e o construtor são mostrados abaixo neste capítulo, lembre-se de que o código que importa todos os pacotes necessários é mostrado.
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 variáveis de membro são descritas posteriormente neste capítulo.
Como analisar os argumentos da linha de comandos
etapa
- analisar os argumentos da linha de comando, consulte o código incluído no aplicativo Apêndice G, CRNPCLIENT.JAVA.
Como definir o subprocesso de recebimento do evento
no código, você precisa verificar se a recepção de eventos é executada em um encadeamento separado para que o aplicativo possa continuar executando o outro trabalho, enquanto o subprocesso do evento é bloqueado e rediscamentos de eventos esperados.
Nota –
A configuração XML é descrita posteriormente neste capítulo.
etapas
-
no código, definir A subclasse do thread chamado EventRecepthThread que cria um soquete, ServiceCocket e espera a recepção dos eventos no soquete.
Nesta parte do código de exemplo, os eventos não sabem lidos ou são processados. A leitura e o processamento de eventos são descritos mais adiante neste capítulo.EventReceXThread cria um soquete, ServiceCocket, em um endereço de protocolo intendenction com curingas. EventReceXThread também mantém uma referência ao objeto CRNPCLIENTE para que EventRecepthread possa enviar eventos para o objeto CRNPClient para processamento.
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;}
-
Construa um objeto CreateEvtrecepth.
private void createEvtRecepThr() throws Exception{ evtThr = new EventReceptionThread(this); evtThr.start();}
Como registrar reduzido ou cancelar o registro
O processo de registro envolve as seguintes ações:
-
Abra um soquete TCP básico para o protocolo de interredição de porta e registro
-
Criar a mensagem de log XML
-
Enviar a mensagem de log XML no soquete
-
Leia a mensagem de resposta XML fora do soquete
-
Fechar o soquete
etapas
-
Crie o código Java que aplica a lógica anterior.
O seguinte código de amostra mostra a implementação do método RegisterCallbacks da classe CRNPClient (chamado pelo construtor CRNPClient). As chamadas para creatersegrationstring () e readregistrationReply () são descritos mais detalhados posteriormente neste capítulo.
regip e regip são objetos membros configurados pelo construtor.
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();}
-
Aplique o método de não registrador.
O método de desligamento de CRNPClient chama este método. A implementação do CreateUregRationString é descrita mais detalhada posteriormente neste capítulo.
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();}
Como gerar XML
Agora que a estrutura do aplicativo foi configurada e foi escrito todo o código de rede, o código que gera e analisa xml deve ser escrito. Primeiro, escreva o código que gera a mensagem do Registro XML SC_Callback_reg.
Uma mensagem SC_Callback_reg é formada por um tipo de registro (add_client, remove_client, add_events ou remove_events), uma porta de rediscagem e uma lista de eventos de interesse . Cada evento consiste em uma classe e uma subclasse, seguida de uma lista de nomes de nomes e valores.
Nesta parte do exemplo, uma classe CallbackReg é escrita que salva o tipo de registro, a porta rediscagem e a lista de eventos de registro. Esta classe também pode ser serializada para uma mensagem XML SC_Callback_reg.
Um método interessante dessa classe é convertidoxml, que cria uma string de mensagem XML SC_Callback_reg de classe de classe. A documentação do JAXP localizada em http://java.sun.com/xml/jaxp/index.html descreve mais detalhado o código desse método mais detalhado.
A implementação da classe de evento é exibida no seguinte código de amostra. Observe que a classe CallBackReg usa uma classe de evento, que permite armazenar um evento e convertê-lo em um elemento, elemento, xml.
etapas
-
criar O código Java que aplica a lógica 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;}
-
Implemente o evento e as aulas NVPair.
Observe que a classe CallbackReg usa o evento, que em O turno usa uma classe 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 criar mensagens de registro e mensagens de cancelamento
Uma vez que as classes forem criadas a partir do auxiliar Gerando mensagens XML, você pode escrever a implementação do método creatersegrationstring. RegisterCallbacks chama esse método; Esse processo é descrito em como registrar reduzido ou cancelar o registro.
CreateGistRationString constrói um objeto CallbackReg e define sua porta e tipo de registro. Em seguida, o creatersegrationstring constrói vários eventos através dos métodos do Createallevent auxiliar, CreatemembershipEvent, CreedEvent e CreateEvent. Cada evento é adicionado ao objeto CallLlBackReg depois de criá-lo. Finalmente, o CreateGistRationstring invoca o método ConverttoxML no objeto CallbackReg para recuperar a mensagem XML no formulário de string.
Observe que a variável de membro regs armazena os argumentos da linha de comando fornecida pelo usuário para o aplicativo. O quinto argumento e a seguir especificar os eventos para os quais o aplicativo deve ser registrado. O quarto argumento especifica o tipo de registro, mas é ignorado neste exemplo. O código completo incluído no aplicativo Apêndice G, CRNPCLIENT.JAVA mostra como usar este quarto argumento.
etapas
-
Criar o código Java que aplica a lógica 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);}
-
Crie a cadeia de cancelamento de registro.
Criação A cadeia de cancelamento de registro é um processo mais simples do que o Criação da cadeia de registro, uma vez que não é necessário adaptar os 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 analisador XML
Uma vez o código de geração XML e da rede para o aplicativo , o construtor CRNPClient chama o método SetupXMLProcessing, que cria um objeto DocumentBuilderFactory e estabelece várias propriedades de análise nesse objeto. A documentação do JAXP descreve esse método mais detalhado. Consulte http://java.sun.com/xml/jaxp/index.html.
etapa
-
Crie o código Java que aplica o lógica anterior.
Observe que o método ReadRegistrationReply usa a nova classe reavaliação.
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);}
-
implemente a classe regressiva.
Observe que o método RecolhaValues é executado através da árvore DOM do documento XML e extrai o código e a mensagem de status. A documentação do JAXP localizada em http://java.sun.com/xml/jaxp/index.html contém mais informações.
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;}
-
Crie o código Java que aplica a lógica anterior.
Por favor, note que este código é semelhante ao da classe regressiva, que é descrito em como analisar a mensagem de resposta de registro.
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;
-
Implementar fabricantes adicionais e métodos da classe NVPair compatível com a análise XML.
As alterações feitas no evento mostradas na etapa 1 também devem ser realizadas na classe 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); }}
-
Implementar o loop while while em eventrecepthread, que aguarda as recordações de eventos.
eventrecepthread é descrito sobre como definir o subprocesso de recebimento de eventos.
while(true) { Socket sock = listeningSock.accept(); Document doc = db.parse(sock.getInputStream()); Event event = new Event(doc); client.processEvent(event); sock.close(); }
-
Torne-se um superusuário ou assuma uma função semelhante.
-
execute o aplicativo.
# java CrnpClient crnpHost crnpPort localPort ...
O código completo do aplicativo CRNPClient é exibido no Apêndice G, aplicativo CRNPClient.java.
Crie o código Java que aplica a lógica 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 analisar a mensagem de resposta de registro
para digitalizar a mensagem XML SC_REPLY que a CRNP envia em resposta em um Mensagem de registro ou cancelamento, é necessário ter uma reavaliação de classe auxiliar, que pode ser construída a partir de um documento XML. Esta classe fornece acessadores para o código de status e a mensagem de status. Para analisar a seqüência XML do servidor, é necessário criar um novo documento XML e usar seu método de análise. Documentação jaxp localizada em http://java.sun.com/xml/jaxp/index.html descreve este método mais detalhado.
etapas
Como analisar os eventos rediscais
O passo final é analisar e processar os eventos Reais de rediscagem. Para ajudá-lo nesta tarefa, você deve modificar a classe de evento criada sobre como gerar XML para que esta classe possa criar um evento, evento, de um documento XML e criar um elemento, elemento, XML: Essa alteração requer um construtor adicional ( Isso inclui um documento XML), um método de recuperação, adicionando duas variáveis de membro (fornecedor e editor), métodos de acesso para todos os campos e, finalmente, um método de impressão.