2013-04-11 19 views
97

Sono relativamente nuovo al mondo dei servizi web e la mia ricerca sembra aver mi ha confuso più che illuminarmi, il mio problema è che mi è stata data una libreria (jar) che devo estendere con alcune funzionalità di webservice.Come eseguire una chiamata al servizio Web SOAP dalla classe Java?

Questa libreria sarà condivisa con altri sviluppatori e tra le classi nel jar ci saranno le classi che hanno un metodo che chiama un webservice (che essenzialmente imposta un attributo della classe, fa qualche logica di business, come la memorizzazione dell'oggetto in un db, ecc. e rimanda l'oggetto con tali modifiche). Voglio rendere la chiamata a questo servizio il più semplice possibile, si spera così semplice che lo sviluppatore che usa la classe debba solo farlo.

Car c = new Car("Blue"); 
c.webmethod(); 

Ho studiato JAX-WS per usare sul server, ma mi sembra che non ho bisogno di creare un wsimport nel server né il wsimport sul client, in quanto so che entrambi hanno la classi, ho solo bisogno di una certa interazione tra le classi condivise sia nel server che nel client. Come pensi abbia senso fare il webservice e la chiamata in classe?

+0

la tua domanda è un po 'poco chiaro.Il metodo che vuoi creare (1) ottiene l'oggetto dal servizio web; (2) lavorare un po 'con l'oggetto; e (3) postarlo di nuovo al servizio web. È così? – acdcjunior

+0

No, l'oggetto verrà creato nel client, verrà inviato alla ws nella chiamata, ws imposterà una variabile, ad esempio currentTime, eseguirà alcune logiche di business come memorizzarlo in un db e quindi inviato tornare al client con il tempo corrente ora impostato. Spero di essermi spiegato un po 'meglio. Grazie. – jpz

risposta

222

Capisco che il problema si riduce a come chiamare un servizio Web SOAP (JAX-WS) da Java e ottenere l'oggetto restituito. In questo caso, hai due possibili approcci:

  1. Generare le classi Java tramite wsimport e utilizzarle; o
  2. creare un client SOAP che:
    1. serializza i parametri del servizio di XML;
    2. Chiama il metodo web tramite la manipolazione HTTP; e
    3. Analizzare la risposta XML di ritorno in un oggetto.


Circa il primo approccio (usando wsimport):

Vedo che già i servizi (entità o altro) le classi di business, ed è un dato di fatto che la wsimport genera un intero nuovo set di classi (che sono in qualche modo duplicati delle classi che hai già).

temo, anche se, in questo scenario, si può solo uno:

  • Adapt (modifica) il wsimport codice generato per renderlo utilizzare tuoi classi aziendali (questo è difficile e in qualche modo non ne vale la pena - ricorda ogni volta che il WSDL cambia, dovrai rigenerare e riadattare il codice); oppure
  • Abbandonare e utilizzare le classi generate wsimport. (In questa soluzione, il codice aziendale potrebbe "utilizzare" le classi generate come un servizio da un altro livello architettonico.)

Circa il secondo approccio (creare il client SOAP su ordinazione):

Al fine di attuare il secondo approccio, dovrete:

  1. effettuare la chiamata:
    • Utilizzare il framework SAAJ (SOAP con allegati API per Java) (vedere di seguito, è fornito con Java SE 1.6 o successivo) per effettuare le chiamate; oppure
    • È inoltre possibile farlo tramite java.net.HttpUrlconnection (e alcuni tipi di gestione java.io).
  2. Ruotare gli oggetti in e ritorno da XML:
    • Utilizzare un OXM (oggetto di mappatura XML) quadro, come JAXB per serializzare/deserializzare l'XML da/in oggetti
    • O, se si deve, creare/analizzare manualmente l'XML (questa può essere la soluzione migliore se l'oggetto ricevuto è solo un po 'diverso da quello inviato).

Creazione di un client SOAP utilizzando classico java.net.HttpUrlConnection non è così difficile (ma non è così semplice o), e si può trovare in this link un buon codice di partenza.

vi consiglio di utilizzare il quadro SAAJ:

SOAP con allegati API per Java (SAAJ) viene utilizzato principalmente per trattare direttamente con il sapone messaggi di richiesta/risposta che succede dietro le quinte in qualunque Servizio Web API. Permette agli sviluppatori di inviare e ricevere direttamente messaggi di sapone invece di usare JAX-WS.

Vedere di seguito un esempio funzionante (eseguirlo!) Di una chiamata di servizio Web SOAP utilizzando SAAJ. Chiama this web service.

import javax.xml.soap.*; 

public class SOAPClientSAAJ { 

    // SAAJ - SOAP Client Testing 
    public static void main(String args[]) { 
     /* 
      The example below requests from the Web Service at: 
      https://www.w3schools.com/xml/tempconvert.asmx?op=CelsiusToFahrenheit 


      To call other WS, change the parameters below, which are: 
      - the SOAP Endpoint URL (that is, where the service is responding from) 
      - the SOAP Action 

      Also change the contents of the method createSoapEnvelope() in this class. It constructs 
      the inner part of the SOAP envelope that is actually sent. 
     */ 
     String soapEndpointUrl = "https://www.w3schools.com/xml/tempconvert.asmx"; 
     String soapAction = "https://www.w3schools.com/xml/CelsiusToFahrenheit"; 

     callSoapWebService(soapEndpointUrl, soapAction); 
    } 

    private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException { 
     SOAPPart soapPart = soapMessage.getSOAPPart(); 

     String myNamespace = "myNamespace"; 
     String myNamespaceURI = "https://www.w3schools.com/xml/"; 

     // SOAP Envelope 
     SOAPEnvelope envelope = soapPart.getEnvelope(); 
     envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI); 

      /* 
      Constructed SOAP Request Message: 
      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myNamespace="https://www.w3schools.com/xml/"> 
       <SOAP-ENV:Header/> 
       <SOAP-ENV:Body> 
        <myNamespace:CelsiusToFahrenheit> 
         <myNamespace:Celsius>100</myNamespace:Celsius> 
        </myNamespace:CelsiusToFahrenheit> 
       </SOAP-ENV:Body> 
      </SOAP-ENV:Envelope> 
      */ 

     // SOAP Body 
     SOAPBody soapBody = envelope.getBody(); 
     SOAPElement soapBodyElem = soapBody.addChildElement("CelsiusToFahrenheit", myNamespace); 
     SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("Celsius", myNamespace); 
     soapBodyElem1.addTextNode("100"); 
    } 

    private static void callSoapWebService(String soapEndpointUrl, String soapAction) { 
     try { 
      // Create SOAP Connection 
      SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); 
      SOAPConnection soapConnection = soapConnectionFactory.createConnection(); 

      // Send SOAP Message to SOAP Server 
      SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), soapEndpointUrl); 

      // Print the SOAP Response 
      System.out.println("Response SOAP Message:"); 
      soapResponse.writeTo(System.out); 
      System.out.println(); 

      soapConnection.close(); 
     } catch (Exception e) { 
      System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n"); 
      e.printStackTrace(); 
     } 
    } 

    private static SOAPMessage createSOAPRequest(String soapAction) throws Exception { 
     MessageFactory messageFactory = MessageFactory.newInstance(); 
     SOAPMessage soapMessage = messageFactory.createMessage(); 

     createSoapEnvelope(soapMessage); 

     MimeHeaders headers = soapMessage.getMimeHeaders(); 
     headers.addHeader("SOAPAction", soapAction); 

     soapMessage.saveChanges(); 

     /* Print the request message, just for debugging purposes */ 
     System.out.println("Request SOAP Message:"); 
     soapMessage.writeTo(System.out); 
     System.out.println("\n"); 

     return soapMessage; 
    } 

} 

Informazioni sull'utilizzo di JAXB per la serializzazione/deserializzazione, è molto facile trovare informazioni a riguardo. Puoi iniziare qui: http://www.mkyong.com/java/jaxb-hello-world-example/.

+0

Come si imposta la versione soap con il metodo sopra menzionato? – Redone

+0

Ero in grado di usare il tuo metodo e ha funzionato quando ho usato il tuo URI ma per la mia richiesta SOAP ottengo una risposta per cui nessuno dei valori è mostrato come previsto, cioè '' ''. Come puoi vedere, l'elemento è chiuso e nessuna informazione viene generata dal WS. – santafebound

+0

'GetInfoByCity' è' 503Service non disponibile', sembra. :( –

1

O semplicemente utilizzare Apache CXF's wsdl2java per generare oggetti che è possibile utilizzare.

È incluso nel pacchetto binario che è possibile scaricare dal proprio sito Web. Si può semplicemente eseguire un comando come questo:

$ ./wsdl2java -p com.mynamespace.for.the.api.objects -autoNameResolution http://www.someurl.com/DefaultWebService?wsdl 

utilizza WSDL per generare gli oggetti, che si può usare come questo (i nomi degli oggetti vengono anche prese dal WSDL, quindi il vostro sarà diverso un po '):

DefaultWebService defaultWebService = new DefaultWebService(); 
String res = defaultWebService.getDefaultWebServiceHttpSoap11Endpoint().login("webservice","dadsadasdasd"); 
System.out.println(res); 

C'è plug-in anche un Maven che genera le fonti: https://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html