Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

30oct/0910

Flex Modules – TypeError: Error #1034: Echec de la contrainte de type : conversion de mx.managers::PopUpManagerImpl@18658d01 en mx.managers.IPopUpManager impossible [Résolu]

Voici un bug Flex que vous allez sûrement rencontrer si votre application comporte plusieurs modules à la fois. Ce n'est pas vraiment un bug en soi, c'est simplement un comportement du Framework Flex qu'il faut connaître pour éviter les surprises.

Le bug en question

Ce bug se produit de nombreuses manières différentes, mais toujours quand vous allez utiliser plusieurs modules dans une même application. Après des actions qui peuvent pourtant sembler banales, vous allez obtenir une RTE (RunTime Error) assez étrange du style:

TypeError: Error #1034: Echec de la contrainte de type : conversion de mx.managers::PopUpManagerImpl@18658d01 en mx.managers.IPopUpManager impossible.
 at mx.managers::PopUpManager$/get impl()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\PopUpManager.as:68]
 at mx.managers::PopUpManager$/addPopUp()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\PopUpManager.as:169]
 at mx.controls::ComboBox/getDropdown()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\ComboBox.as:1459]
 at mx.controls::ComboBox/displayDropdown()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\ComboBox.as:1552]
 at mx.controls::ComboBox/downArrowButton_buttonDownHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\ComboBox.as:1801]
 at flash.events::EventDispatcher/dispatchEventFunction()
 at flash.events::EventDispatcher/dispatchEvent()
 at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:9298]
 at mx.controls::Button/http://www.adobe.com/2006/flex/mx/internal::buttonPressed()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\Button.as:2504]
 at mx.controls::Button/mouseDownHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\Button.as:2750]
 at flash.events::EventDispatcher/dispatchEventFunction()
 at flash.events::EventDispatcher/dispatchEvent()
 at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:9298]
 at mx.controls::ComboBase/textInput_mouseEventHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\ComboBase.as:1388]

Cette erreur de conversion (Coercion) se reproduit facilement sur le PopUpManager ou sur le DragManager mais peut aussi se produire avec vos propres classes. Vous obtiendrez des messages qui pourront vous sembler étranges. Par exemple:

TypeError: Error #1034: Type Coercion failed: cannot convert MyClass@5d73ce1 to MyClass.

Une conversion de type entre un type MyClass et le même type MyClass qui ne fonctionne pas, il y a de quoi se poser des questions. Ce bug a été maintes fois reporté sur la Bug Base d'Adobe (SDK-16474, SDK-14384, ...) mais peut facilement être corrigé.

Un exemple d'application qui pose problème


J'ai monté rapidement une application qui expose ce problème. Voici le code:

L'application principale

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:ModuleLoader url="Module1.swf"/>
 <mx:ModuleLoader url="Module2.swf"/>
</mx:Application>

Le premier module (Module1)

<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Label text="Module1.swf"
 fontWeight="bold"
 fontSize="14"/>
 <mx:ComboBox>
 <mx:dataProvider>
 <mx:String>Module1-A</mx:String>
 <mx:String>Module1-B</mx:String>
 <mx:String>Module1-C</mx:String>
 <mx:String>Module1-D</mx:String>
 </mx:dataProvider>
 </mx:ComboBox>
</mx:Module>

Le second module (Module2)

<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Label text="Module2.swf"
 fontWeight="bold"
 fontSize="14"/>
 <mx:ComboBox>
 <mx:dataProvider>
 <mx:String>Module2-A</mx:String>
 <mx:String>Module2-B</mx:String>
 <mx:String>Module2-C</mx:String>
 <mx:String>Module2-D</mx:String>
 </mx:dataProvider>
 </mx:ComboBox>
</mx:Module>

Rien de bien complexe, simplement 2 modules avec une ComboBox chacun. Dans l'exemple ci-dessous, ouvrez la première ComboBox puis la deuxième. Si vous avez le Flash Player Debugger, vous obtiendrez l'erreur dont on parle dans cet article.

L'application en ligne

Flex Source Code Download: Télécharger le code source complet de l'application

This movie requires Flash Player 11

La raison du problème

Lorsqu'il se produit sur des classes internes du framework Flex (PopUpManager, DragManager, HistoryManager, ...), ce bug est du à la gestion des Singletons dans Flex. En fait,  quand les modules sont chargés, les classes contenues dans ce module sont ajoutées au domaine enfant de l'applicationDomain courant. Donc les classes qui font parties du modules seront possédées par le module et pas par l'application.

Cela crée un problème quand 2 modules essaient d'utiliser la même classe. Quand le module est chargé pour la première fois, sa définitions de classe est enregistrée et le module qui sera chargé plus tard va se rendre compte que la définition de classe qu'il contient ne correspond pas à celle qui a été enregistrée. Dans le cas des combobox, c'est la définition de IPopUpManager qui pose problème mais vous auriez le même problème de conversion avec deux modules ayant du Drag And Drop avec le DragManager.

La solution au problème

La solution est très simple mais peut pourtant nuire à la modularisation de votre application. Pour combler ce bug, il suffit de déclarer dans l'application principale, les classes qui vont être partagées par plusieurs modules. Pour être sûr de votre coup, il vous suffit de mettre ce code dans l'application principale:

import mx.managers.PopUpManager;
import mx.managers.DragManager;
import mx.managers.HistoryManager;
private var _linkage:Array = [PopUpManager, DragManager, HistoryManager];

Si vous utilisez vos propres classes, et que vous devez y accéder depuis plusieurs modules, il faut aussi les ajouter à la liste avec l'import correspondant.

Articles similaires

Commentaires (10) Trackbacks (0)
  1. Pourrais-tu poster le lien vers les sources de l'application et un court commentaire sur comment s'en servir à la suite du bug [#SDK-16474] dont tu parles, un des développeurs affirme ne pas arriver à le reproduire. Je n'ai pas osé le faire à ta place.

    Merci pour ça, pour cet article et la suite de billets sur les modules, il y a plein de choses intéressantes.

  2. Salut,
    le lien vers les sources de l'application est juste au dessus de l'exemple (View Source ne fonctionne pas à cause de ma redirection http pour WordPress). Pour le dev (Peter deHaan Adobe je présume) qui n'arrive pas à le reproduire, cela fait plus d'un an et en plus, le commentaire suivant explique comment résoudre ce bug.
    Je vais rajouter cela sur la bug base quand même

    Merci :)
    Fabien

  3. Merci bcp , excellent travail

  4. Merci Fabien pour cette solution!
    Je ne comprenais pas d'où cela venait...

  5. Merci beaucoup, votre site m'as vachement aidé.

  6. Merci, ça m'a bien aidé !

  7. Merci,
    bientôt 1h que je farfouillais mon code.
    Pb résolu!
    (je consulte ton blog depuis 2009)!

  8. Salut ben,
    content d'avoir pu aider :)

    Fabien

  9. OH MY GOD !!!!

    merciiiiiiiiiiiiiiiii j'ai passé 2h à chercher pourquoi mes le déchargement des modules provoqué cette erreur !

    P.S.: Mon problème venait du fait de chargé et décharger les même module.


Leave a comment

(required)

Aucun trackbacks pour l'instant