Comment faire un appel de service Web SOAP à partir de la classe Java?

Je suis relativement nouveau dans le monde des webservices et mes recherches semblent m'avoir confondu plus que m'éclairer, mon problème est qu'on m'a donné une bibliothèque (jar) que je dois étendre avec des fonctionnalités de webservice.

Cette bibliothèque sera partagée avec d'autres développeurs, et parmi les classes du jar, il y aura des classes qui ont une méthode qui appelle un webservice (qui définit essentiellement un attribut de la classe, fait de la logique métier, comme stocker l'objet dans une base de données, etc et envoie retour l'objet avec ces modifications). Je veux rendre l'appel à ce service aussi simple que possible, espérons-le aussi simple que possible pour que le développeur utilisant la classe n'ait qu'à le faire.

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

J'ai étudié JAX-WS à utiliser sur le serveur mais il me semble que je n'ai pas besoin de créer un wsimport dans le serveur ni le wsimport sur le client, puisque je sais que les deux ont les classes, j'ai juste besoin d'une interaction entre les classes partagées dans le serveur et le client. Comment pensez-vous fait sens de faire le webservice et l'appel dans la classe?

101
demandé sur acdcjunior 2013-04-11 07:28:41

2 réponses

Je comprends que votre problème se résume à Comment appeler un service Web SOAP (JAX-WS) à partir de Java et obtenir son objet de retour . Dans ce cas, vous avez deux approches possibles:

  1. Générez les classes Java via wsimport et utilisez-les; ou
  2. crée un client SOAP qui:
    1. sérialise les paramètres du service en XML;
    2. appelle la méthode web via une manipulation HTTP; et
    3. analysez la réponse XML de retour dans un objet.


A propos de la première approche (en utilisant wsimport):

Je vois que vous avez déjà les classes commerciales (entités ou autres) des services, et c'est un fait que wsimport génère un nouvel ensemble de classes (qui sont en quelque sorte des doublons des classes que vous avez déjà).

J'ai peur, cependant, dans ce scénario, vous ne pouvez que:

  • adaptez (modifiez) le code généré par wsimport pour qu'il utilise vos classes métier (c'est difficile et en quelque sorte pas la peine - gardez à l'esprit chaque fois que le WSDL change, vous devrez régénérer et réadapter le code); ou
  • abandonnez et utilisez les classes générées par wsimport. (Dans cette solution, vous pouvez "utiliser" les classes générées en tant que service à partir d'une autre couche architecturale.)

A propos de la deuxième approche (créez votre client SOAP personnalisé):

Afin de mettre en œuvre la deuxième approche, vous aurez à:

  1. Faire l'appel:
    • utilisez le framework SAAJ (soap with Attachments API for Java) (voir ci-dessous, il est livré avec Java SE 1.6 ou supérieur) pour effectuer les appels; ou
    • Vous pouvez également le faire à travers java.net.HttpUrlconnection (et certains java.io Manipulation).
  2. transforme les objets en XML et en arrière:
    • utilisez un cadre OXM (Object to XML Mapping) tel que JAXB pour sérialiser / désérialiser le XML depuis / vers des objets
    • ou, si nécessaire, manuellement créer / analyser le XML (cela peut être la meilleure solution si l'objet reçu n'est qu'un peu différent de l'objet envoyé).

Créer un client SOAP en utilisant classic java.net.HttpUrlConnection n'est pas si difficile (mais pas si simple non plus), et vous pouvez trouver dans ce lien un très bon code de départ.

Je vous recommande d'utiliser le framework SAAJ:

SOAP with Attachments API for Java (SAAJ) est principalement utilisé pour traiter directement avec SOAP Messages de demande / réponse qui se passe dans les coulisses de N'importe quelle API de service Web. Il permet aux développeurs d'envoyer et de recevoir directement des messages soap au lieu d'utiliser JAX-WS.

Voir ci-dessous un exemple de travail (exécutez-le!) d'un appel de service Web SOAP utilisant SAAJ. Il appelle ce service web.

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;
    }

}

À propos de L'utilisation de JAXB pour la sérialisation / désérialisation, il est très facile de trouver des informations à ce sujet. Vous pouvez commencer ici: http://www.mkyong.com/java/jaxb-hello-world-example/.

240
répondu acdcjunior 2017-08-23 11:59:01

Ou utilisez simplementWsdl2java D'Apache CXF pour générer des objets que vous pouvez utiliser.

Il est inclus dans le paquet binaire que vous pouvez télécharger à partir de leur site web. Vous pouvez simplement exécuter une commande comme ceci:

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

Il utilise le wsdl pour générer des objets, que vous pouvez utiliser comme ceci (les noms d'objets sont également saisis dans le wsdl, donc le vôtre sera un peu différent):

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

Il existe même un plug-in Maven qui génère les sources: https://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html

Remarque: Si vous générez des sources en utilisant CXF et IDEA, vous pouvez regarder ceci: https://stackoverflow.com/a/46812593/840315

2
répondu appl3r 2018-04-18 06:14:19