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

Spring Java Discussion :

Spring et autowiring [Framework]


Sujet :

Spring Java

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Spring et autowiring
    Bonjour,

    Je tente de mettre en place la gestion des transactions par Spring. Dans les exemples que j'ai pu rencontrer, la sessionFactory est parfois autowired aux DAO. Cette solution est séduisante car elle diminue drastiquement et le volume de code et la configuration Spring. Néanmoins, elle me pose de nombreux problèmes et soulèvent quelques interrogations.

    Considérons un DAO nommé EntityDAO sur lequel je fais un autowiring de sessionFactory. Pour ce faire, il est nécessaire que la sessionFactory soit déclarée en tant que bean Spring, mais également que l'EntityDAO le soit. En effet, je ne parviens pas à faire d'autowiring sur des objets instantiés via un new. Est-ce possible ?

    Si ça ne l'est pas, ne vais-je pas avoir une réaction en chaîne m'obligeant à déclarer en tant que bean tout objet faisant référence à un objet (faisant référence à un objet, etc.) cible d'un autowiring ?

    Je ne sais pas si je suis très clair. Il me manque sans doute quelques éléments pour appréhender parfaitement le mécanisme d'autowiring et son lien avec les beans. Aussi suis-je preneur de tout éclaircissement.

    Merci d'avance.

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    104
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 104
    Points : 135
    Points
    135
    Par défaut
    Salut,

    Spring ne peut faire de l'IOC que sur les beans qu'il a instanciés. Donc si ton DAO n'est pas géré par Spring c'est à toi de récupérer la SessionFactory à partir de l'ApplicationContext.
    Le plus simple est que ton DAO soit aussi un bean Spring (annotation @repository)
    Après tu peux aussi utiliser la classe HibernateTemplate pour tes DAO...

  3. #3
    Membre actif Avatar de aymen83
    Inscrit en
    Décembre 2007
    Messages
    271
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 271
    Points : 268
    Points
    268
    Par défaut
    Citation Envoyé par PomCompot Voir le message
    Bonjour,

    Je tente de mettre en place la gestion des transactions par Spring. Dans les exemples que j'ai pu rencontrer, la sessionFactory est parfois autowired aux DAO. Cette solution est séduisante car elle diminue drastiquement et le volume de code et la configuration Spring. Néanmoins, elle me pose de nombreux problèmes et soulèvent quelques interrogations.

    Considérons un DAO nommé EntityDAO sur lequel je fais un autowiring de sessionFactory. Pour ce faire, il est nécessaire que la sessionFactory soit déclarée en tant que bean Spring, mais également que l'EntityDAO le soit. En effet, je ne parviens pas à faire d'autowiring sur des objets instantiés via un new. Est-ce possible ?

    Si ça ne l'est pas, ne vais-je pas avoir une réaction en chaîne m'obligeant à déclarer en tant que bean tout objet faisant référence à un objet (faisant référence à un objet, etc.) cible d'un autowiring ?

    Je ne sais pas si je suis très clair. Il me manque sans doute quelques éléments pour appréhender parfaitement le mécanisme d'autowiring et son lien avec les beans. Aussi suis-je preneur de tout éclaircissement.

    Merci d'avance.
    La dependency injection est le mécanisme qui te permet en effet d'allouer des beans, donc pas besoin de faire un new (à la Java classique "n'est ce pas?")
    c'est pour ça d'ailleurs qu'on déclare nos beans dans des fichiers applicationContext propre à spring. Pour le AutoWiring tu délègue à spring de trouver est injecter le bean qu'on veut mais bien sûr celui ci doit se trouver dans le context(le conteneur ne va pas deviner par lui )

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Ça progresse
    Merci pour vos réponses. Je progresse sur la bonne voie. À vrai dire, je débute en Spring, j'en découvre tous les jours.

    J'ai préféré à la contrainte de déclarer chaque bean où je désire faire de l'autowire dans les fichiers de conf Spring XML, la solution plus esthétique des annotations @Repository, @Service et @Configurable comme Kirua12 me l'a proposé.

    J'ai pourtant toujours un problème. En effet, dans mon service (annoté par @Service et @Transactional), je tente l'autowire d'un DAO (annoté par @Repository et @Transactional). Hors, le mécanisme de gestion des transactions crée un proxy autour de mon DAO. Le bean alors récupéré n'est plus du bon type et plus compatible avec celui attendu par le setter du service (je me fait jeter par la méthode isTypeMatch de l'AbstractBeanFactory de Spring).

    J'ai beau chercher, je ne vois pas comment contourner le problème. Un peu de code et de log pour illustrer mon problème :
    Le 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
    18
    @Transactional
    @Service
    public class InscriptionLivraisonService implements IInscriptionLivraisonService {
    	private Logger logger = Logger.getLogger(this.getClass());
     
    	@Autowired
    	private LivraisonHome livraisonHome;
     
            []
     
    	public LivraisonHome getLivraisonHome() {
    		return livraisonHome;
    	}
     
    	public void setLivraisonHome(LivraisonHome livraisonHome) {
    		this.livraisonHome = livraisonHome;
    	}
    }
    Le DAO :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    @Transactional
    @Repository
    public class LivraisonHome extends AbstractHome {
         []
    }
    Classe attendue par le setter : 'LivraisonHome', classe réelle du bean après proxying : '$Proxy14' (JdkDynamicAopProxy apparemment).

    Message d'erreur :
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    java.lang.IllegalStateException: Failed to load ApplicationContext
        []
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inscriptionLivraisonService': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.macif.odma.dao.pojo.LivraisonHome com.macif.odma.metier.livraison.InscriptionLivraisonService.livraisonHome; nested exception is java.lang.IllegalArgumentException: Can not set com.macif.odma.dao.pojo.LivraisonHome field com.macif.odma.metier.livraison.InscriptionLivraisonService.livraisonHome to $Proxy14
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:243)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:959)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:42)
    	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:173)
    	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:197)
    	... 17 more
    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.macif.odma.dao.pojo.LivraisonHome com.macif.odma.metier.livraison.InscriptionLivraisonService.livraisonHome; nested exception is java.lang.IllegalArgumentException: Can not set com.macif.odma.dao.pojo.LivraisonHome field com.macif.odma.metier.livraison.InscriptionLivraisonService.livraisonHome to $Proxy14
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:435)
    	at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:240)
    	... 34 more
    Caused by: java.lang.IllegalArgumentException: Can not set com.macif.odma.dao.pojo.LivraisonHome field com.macif.odma.metier.livraison.InscriptionLivraisonService.livraisonHome to $Proxy14
    	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    	at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    	at java.lang.reflect.Field.set(Field.java:675)
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:431)
    	... 36 more
    Si vous avez idée de comment contourner ce problème de typage tout en conservant le mécanisme d'autoproxy de Spring pour la gestion des transactions …

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    104
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 104
    Points : 135
    Points
    135
    Par défaut
    normal, tu dois avoir des interfaces pour chacun de tes beans et c'est les interfaces que tu références et non les implémentations.
    Donc de la même façon que tu as une interface pour ton service, crées une interface pour ton DAO et ça devrait marcher

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Parfait
    Exact. J'en suis arrivé à la même conclusion tout seul en début d'après-midi. La pause porte conseil. Merci beaucoup pour votre aide.

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

Discussions similaires

  1. [Framework] [Spring annotation] @Autowired sur prop hérité
    Par obiflo dans le forum Spring
    Réponses: 2
    Dernier message: 11/03/2011, 08h41
  2. Spring probléme Autowiring
    Par kamalkane dans le forum Spring Web
    Réponses: 1
    Dernier message: 07/12/2010, 15h44
  3. [Framework] Maven+Spring : pb avec @Autowired
    Par zev dans le forum Spring
    Réponses: 2
    Dernier message: 02/10/2009, 21h43
  4. [Framework] Injection spring par autowired en cascade
    Par _Moa_ dans le forum Spring
    Réponses: 1
    Dernier message: 11/08/2009, 16h31
  5. [Integration] Spring et Jmock : injecter un mock dans un @autowired
    Par elix63 dans le forum Spring
    Réponses: 1
    Dernier message: 08/07/2009, 08h54

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