IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Services Web Java Discussion :

CXF : A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only endpoint.


Sujet :

Services Web Java

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Points : 159
    Points
    159
    Par défaut CXF : A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only endpoint.
    Bonjour,

    En essayant de migrer vers des versions récentes des librairies, je me retrouve avec des problèmes que je n'avais pas.

    J'utilise les versions 2.6.2 de CXF.

    dans myAppContext.xml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	<bean id="myWSFonds" class="some.package.MyFondsServiceType"
    	  factory-bean="proxyFactoryFonds" factory-method="create"/>	  
    	<jee:jndi-lookup id="adresseFondsWS" jndi-name="java:/comp/env/fondsservice"/>
    	<bean id="proxyFactoryFonds" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
    	    <property name="serviceClass" value="some.package.MyFondsServiceType"/>
    	    <property name="address" ref="adresseFondsWS"/>	    
    	    <property name="username" ref="userNameFondsWS"/>
    	    <property name="password" value="thePwd"/>
    	</bean>
    Erreur qu'on j'essaie d'appeler une fonction du WebService :
    A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only endpoint.

    A noter que j'ai aussi essayé comme on me l'a conseillé de générer les classes du WS à partir de la wsdl (avec cxf aussi) mais ça ne change rien.

    Tout ce que je trouve sur Internet c'est des solutions pour bricoler la WSDL mais j'imagine quand-même qu'il y a moyen avec une version récente de CXF d'appeler un WebService tel qu'il était auparavant sans devoir bricoler quelque chose sur celui-ci (en plus dans ma wsdl il y a déjà des références à xmlns:soap12)

    Merci.

  2. #2
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2007
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 186
    Points : 474
    Points
    474
    Par défaut
    Pas besoin de déclarer quoique ce soit dans l'app contexte, cette manière de faire est peu désuette, il suffit de générer une fois tes classes "clientes" à partir de la tache wsdl2java (via un goal du script Maven du projet par exemple).

    Dans le cas où il faut s'authentifier on peut créer une classe qui implémente SOAPHandler<SOAPMessageContext> afin de rajouter dans le header du message SOAP les credentials du webservice (login/password). Ou alors utiliser le wrapper fourni par CXF : CXFClientPasswordHandler.

    L'appel du service est trivial, on instancie le proxy du service et ensuite on utilise la factory du client webservice pour alimenter le message SOAP avant envoi ...

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Points : 159
    Points
    159
    Par défaut
    Merci pour la réponse.
    Donc avec mes classes en local je suis sur la bonne voie.

    Par contre j'ai pas bien compris ce que je dois changer dans mon code.

    J'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        <bean id="myAppService" class="som.package.service.impl.MyAppService" >
            <property name="myAppDao"        	ref="myAppDao"/>
            <property name="port"        		ref="myWSFonds"/>
        </bean>
    et donc dans le service, j'appelle le WS avec la variable port de type MyFondsServiceType

    je ne peux donc pas juste supprimer totalement la définition du bean; oeut-être alors que ça signifie que je laisse juste le minium, soit :
    <bean id="myWSFonds" class="some.package.MyFondsServiceType"/>

    Désolé, si tu peux détailler un peu ce que je dois changer car c'est un peu obscur pour moi

  4. #4
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2007
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Janvier 2007
    Messages : 186
    Points : 474
    Points
    474
    Par défaut
    Pas besoin de déclarer de bean déjà. Il suffit de générer la première fois les classes clientes à partir du WSDL (fourni l'URL du webservice directement).

    Tu déclares :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    endpointURL; // l'URL du webservice
    username; // le login
    passwd; // le password
    Tu définis le handler pour gérer l'authentification:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CXFClientPasswordHandler handler = new CXFClientPasswordHandler(username, passwd);
    Map<String, Object> outProps = new HashMap<String, Object>();
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    outProps.put(WSHandlerConstants.USER, username);
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
    WSS4JOutInterceptor interceptor = new WSS4JOutInterceptor(outProps);
    Tu instancies la factory du service:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    JaxWsProxyFactoryBean serviceFactory = new JaxWsProxyFactoryBean();
    serviceFactory.getOutInterceptors().add(interceptor);
    serviceFactory.setServiceClass(MonService.class);
    serviceFactory.setAddress(endpointURL);
    serviceFactory.setBindingId(SoapBindingFactory.SOAP_12_BINDING);
    Note: MonService.class est la classe du service généré par la première étape de génération des classes clientes

    Tu instancies le service :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MonService monServicePort= (MonService) serviceFactory.create();
    Tu crée le message SOAP mais avant pour faciliter les choses du va te servir de la factory d'objet gracieusement fournie par CXF (le XML du message est construit à partir d'objet voir en quoi consiste la techno JAXB pour plus d'explications).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ObjectFactory factory = new ObjectFactory();
    Le but ici est de renseigner le ou les arguments à passer à la méthode appelée du webservice : argumentService

    Ensuite tu invoques la méthode foo() de ton service (qui peux en comporter plusieurs au passage) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    RetourService retourService = monServicePort.foo(argumentService);
    Enfin il ne reste plus qu'a exploiter le retour de la méthode une fois exécutée.

    Par rapport à ta toute première question, je sais qu'il est possible d'intégrer CXF dans les fichiers de paramétrages Spring mais si il n'y a pas d’intérêt hormis d'alourdir un peu plus le paramétrage et favoriser la prolifération des fichiers XML ... de toute manière si le service change un jour il faut régénérer les classes cliente et cela ne coûtera pas plus de 2 min à faire.

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Points : 159
    Points
    159
    Par défaut
    Je crois que je suis pas loin d'avoir réussi:

    1°/J'ai donc créé la classe CXFClientPasswordHandler
    2°/J'ai collé tout le code que tu m'as donné dans le constructeur de mon service

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    	public MyAppService() {
    		super();
    		CXFClientPasswordHandler handler = new CXFClientPasswordHandler("theUser", "thePwd");
    		HashMap<String, Object> outProps = new HashMap<String, Object>();
    		outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    		outProps.put(WSHandlerConstants.USER, handler.getUsername());
    		outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    		outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
    		WSS4JOutInterceptor interceptor = new WSS4JOutInterceptor(outProps);
    		JaxWsProxyFactoryBean serviceFactory = new JaxWsProxyFactoryBean();
    		serviceFactory.getOutInterceptors().add(interceptor);
    		serviceFactory.setServiceClass(MyFondsServiceType.class);
    		serviceFactory.setAddress(handler.getEndpointURL());
    		serviceFactory.setBindingId(SoapBindingFactory.SOAP_12_BINDING);
    		port = (MyFondsServiceType) serviceFactory.create();
     
    	}
    Par contre à l'appel j'ai pwd == null but a password is needed.
    Pourtant dans le constructeur j'ai déjà donné le login et password.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Points : 159
    Points
    159
    Par défaut
    C'est OK; il manquait juste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	@Override
    	public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    		WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    		pc.setPassword(this.passwd);
    	}

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 20/09/2010, 17h55
  2. [Web Service][SOAP] Librairie Nusoap - Message erreur
    Par squalito dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 01/02/2007, 11h21
  3. [ORACLE 8.1.7] Message 2100 not found avec SQL LOADER
    Par ApprentiOracle dans le forum SQL*Loader
    Réponses: 3
    Dernier message: 09/08/2006, 20h03
  4. [JpGraph] Erreur : Chosen locale file for error messages does not exist
    Par nagrom dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 19/07/2006, 15h15
  5. Réponses: 4
    Dernier message: 18/01/2006, 21h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo