Bonjour,

Je suis face à un problème d'invocation de web services depuis un batch, un simple programme muni d'un main, lancé par appclient.bat, cet intermédiaire créé par Glassfish à cette fin.

Voici la partie cliente que je lance: serviceAuditeurs a été initialisé avec le getAuditeurServicePort() qu'il faut. Ce client n'utilise que des types générés par wsimport.

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
18
19
20
/**
 * Afficher à l'écran la liste des auditeurs connus.
 * @throws PersistanceException si un incident survient sur le serveur.
 */
public void liste() throws PersistanceException
{
   Locale locale = Locale.getDefault();

   // Ce code-ci prépare l'expédition d'un objet Locales extends ArrayList<Locale>, car Locale n'est pas compatible WS: elle a un constructeur sans argument. Un Adaptateur a été créé pour elle.
   ArrayList<StringArray> locales = new ArrayList<StringArray>();
      
   StringArray l = new StringArray();
   l.getItem().add(locale.getLanguage());
   l.getItem().add(locale.getCountry());
   l.getItem().add(locale.getVariant());
   locales.add(l);
      
   List<Auditeur> auditeurs = serviceAuditeurs.obtenirTousLesAuditeurs(locales);
   System.out.println(auditeurs);
}

Pour information: l'adaptateur pour java.util.Locale, s'il advenait qu'il soit en cause.
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
18
19
20
21
22
23
24
25
/**
 * Adaptateur pour classe Locales.
 */
public class LocaleWSAdapter extends XmlAdapter<String[], Locale>
{
   /**
    * Marshalling.
    * @param source Source à convertir en objet compatible Web Service.
    */
   public String[] marshal(Locale locale) throws Exception
   {
      String[] cible = new String[] {locale.getLanguage(), locale.getCountry(), locale.getVariant()};
      return(cible);
   }
 
   /**
    * Unmarshalling.
    * @param source Source compatible Web Service à convertir en objet cible.
    */
   public Locale unmarshal(String[] source) throws Exception
   {
      Locale cible = new Locale(source[0], source[1], source[2]);
      return cible;
   }
}
Voici mon interface SEI:

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
18
/**
 * Gestionnaire des services fournis aux auditeurs.
 */
@WebService(name = "AuditeurPortType", targetNamespace = "http://auditeurs.services/") 
public interface AuditeurWebService
{
   /**
    * Provoquer le chargement de tous les auditeurs.
    * @param locales Locales à utiliser pour l'invocation.
    * @return Liste des auditeurs.
    * @throws PersistanceException si un incident est survenu sur le support.
    * @deprecated Coûteuse en termes de performances.
    */
   @Deprecated public Auditeurs obtenirTousLesAuditeurs(
         @WebParam(name="locale", mode=IN, targetNamespace="http://localisation.utils/") @XmlJavaTypeAdapter(LocaleWSAdapter.class) Locales locales) 
               throws PersistanceException;
...
}

Et l'implémentation du Web service proprement dit, dans son Bean.

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
18
19
20
21
22
23
24
25
/**
 * Services aux auditeurs.
 */
@WebService(serviceName="GestionAuditeurs", endpointInterface="services.auditeurs.AuditeurWebService", portName="AuditeurServicePort", targetNamespace="http://auditeurs.services/") 
@LocalBean @Stateless public class AuditeurBean extends ServiceStandard implements AuditeurRemoteService, AuditeurLocalService, AuditeurWebService
{
   /**
    * Charger l'ensemble des auditeurs.
    * @return Ensemble des auditeurs.
    * @throws DonneesNonTrouveesException si aucun auditeur n'a pu être trouvé.
    * @throws PersistanceException si un incident survient sur le support.
    * @deprecated Coûteuse en termes de performances.
    */
   // @RolesAllowed("enseignant") 
   @Deprecated public Auditeurs obtenirTousLesAuditeurs(Locales locales) throws PersistanceException
   {
      // TODO: Cette méthode devrait tout simplement dégager...
      assert(locales != null) : "La liste des locales utilisées pour l'invocation ne peut pas valoir null."; //$NON-NLS-1$
 
      Auditeurs auditeurs = daoAuditeur(getGroupe().getId(), locales).loadAll();
      return(auditeurs);
   }
 
   ...
}
Lorsque je lance mon batch en debug, le client (qui tourne sous Java 7) invoque correctement le serveur Glassfish v3.1.1 que j'utilise.
La partie serveur s'exécute correctement et renvoie les données par son return(auditeurs).

Cependant, le client ne les reçoit pas, car cette exception survient:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
com.sun.xml.ws.streaming.XMLStreamReaderException: unexpected XML tag. expected: {http://auditeurs.services/}obtenirTousLesAuditeursResponse but found: {http://schemas.xmlsoap.org/soap/envelope/}Envelope
        at com.sun.xml.ws.streaming.XMLStreamReaderUtil.verifyTag(XMLStreamReaderUtil.java:218)
        at com.sun.xml.ws.streaming.XMLStreamReaderUtil.verifyTag(XMLStreamReaderUtil.java:226)
        at com.sun.xml.ws.client.sei.ResponseBuilder$DocLit.readResponse(ResponseBuilder.java:553)
        at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:125)
        at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93)
        at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:144)
        at $Proxy55.obtenirTousLesAuditeurs(Unknown Source)
        at batch.auditeurs.ListeDesAuditeurs.liste(ListeDesAuditeurs.java:58)
        at batch.auditeurs.ListeDesAuditeurs.main(ListeDesAuditeurs.java:73)
Que peut-il se passer?

En vous remerciant,

Grunt.


EDIT: J'ai peur de ce qui se passe.
L'invocation serveur s'est bien passée en effet.

Mais au retour, JAX-WS appelle les getters de mes objets, lesquels ont des protections et escomptent quelques-fois qu'un hasXXXX() soit appelé avant un getXXXX().

Bilan: au retour, j'ai cette exception côté serveur mais au moment de l'expédition du résultat. C'est à dire "trop tard.": après que JAX-WS a décidé que l'invocation était réussie, et je ne reçois pas l'exception côté client!

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
#|2012-02-12T19:58:41.228+0100|WARNING|glassfish3.1.1|javax.enterprise.webservices.org.glassfish.webservices|_ThreadID=92;_ThreadName=Thread-2;|invocation error on ejb endpoint AuditeurBean at /GestionAuditeurs/AuditeurBean : Il n'y a pas de justification associée au fait que l'auditeur 'I023895' ait le niveau d'inscription 'Déclaré' à l'UV 'X1'.
domaine.uvs.exception.NiveauInscriptionNonJustifieException: Il n'y a pas de justification associée au fait que l'auditeur 'I023895' ait le niveau d'inscription 'Déclaré' à l'UV 'X1'.
	at domaine.uvs.Inscription.getMotif(Inscription.java:53)
	at domaine.uvs.Inscription$JaxbAccessorM_getMotif_setMotif_java_lang_String.get(MethodAccessor_Ref.java:56)
	at com.sun.xml.bind.v2.runtime.reflect.Accessor.getUnadapted(Accessor.java:147)
	at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.hasValue(TransducedAccessor.java:251)
	at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:105)
	at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:356)
	at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
	at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
	at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)
	at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
	at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:356)
	at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:700)
	at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
	at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)