• 10 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 03/09/2019

Intégrez Spring dans une application Struts

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Vous connaissez sûrement le framework Spring® permettant, ente autre, de mettre en place une inversion de contrôle avec de l'injection de dépendances.

Si ce n'est pas le cas, je vous conseille vivement de suivre le cours : Simplifiez le développement d'applications Java avec Spring.

Dans ce chapitre, je vais vous montrer qu'il est possible d'intégrer Spring dans une application Struts.

L'inversion de contrôle avec Struts/Spring

Avez-vous remarqué que depuis le début de ce cours, vous n'instanciez jamais les classes d'action ? En effet, Struts le faisait pour vous à chaque requête HTTP en fonction de la configuration du mapping. Pour y parvenir, Struts utilise un mécanisme de fabrique d'objets (eh oui, le design pattern Factory ;) ).

Struts s'appuie donc sur une fabrique globale : l'ObjectFactory.

Vous devinez sûrement où je veux en venir... Étant donné que Struts s'appuie sur une fabrique d'objets, ce serait l'endroit idéal pour injecter les dépendances vers les autres composants de l'application !

Bingo, c'est là qu'on va pouvoir s'appuyer sur Spring !

Pour l'intégration de Spring, Struts fournit un plugin permettant :

  • d'utiliser Spring comme fabrique d'objets ;

  • d'injecter les dépendances dans les composants Struts avec Spring.

Mise en place de Spring

Tout d'abord, commencez par mettre en place Spring dans votre application comme dans n'importe quelle application web.

Ce qui est déjà fait dans mon application de gestion de ticket. En voici rapidement les grandes lignes :

  • Dans les POM du projet Maven, j'ai ajouté les dépendances vers le framework Spring.

    <!-- Dans le module ticket-technical -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    
    <!-- Dans le module ticket-webapp -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
  • Dans le fichier src/main/webapp/WEB-INF/web.xml, j'ai déclaré et configuré le listener Spring :

    <!-- Listener Spring -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/bootstrapContext.xml</param-value>
    </context-param>
  • J'ai configuré Spring avec le fichier src/main/resources/bootstrapContext.xml et via des annotations

Intégration de Spring avec Struts

Comme je le disais plus haut, pour l'intégration de Spring, Struts fournit un plugin permettant :

  • d'utiliser Spring comme fabrique d'objets Struts ;

  • d'injecter les dépendances dans les composants Struts avec Spring.

Ajout du plugin Spring de Struts

Le première chose à faire est d'ajouter une dépendance vers le plugin Spring de Struts dans le POM du module ticket-webapp :

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-spring-plugin</artifactId>
</dependency>

En ajoutant cette dépendance, le plugin déclare automatiquement Spring comme fabrique d'objet Struts. Pour votre information ceci est fait via les propriétés de configuration Struts dans le fichier struts-plugin.xml du jar de la dépendance, notamment la propriété struts.objectFactory.

La construction des objets et l'injection de dépendances

Maintenant que Spring est utilisé comme fabrique d'objets, il faut configurer la construction des objets et l'injection des dépendances.

Par défaut, Struts demande à Spring de créer les objets et les dépendances sont injectées par autowiring sur les noms. En d'autres termes, les objets sont instanciés par Spring et les beans Spring sont injectés dans les attributs portant le même nom que ces beans.

Par exemple, soit l'action Struts suivante :

  • struts.xml :

    <action name="demo" class="org.example.demo.ticket.webapp.action.DemoAction">
        <result>/jsp/view.jsp</result>
    </action>
  • DemoAction.java :

    public class DemoAction extends ActionSupport {
        private ManagerFactory managerFactory;
        public void setManagerFactory(ManagerFactory pManagerFactory) {
            managerFactory = pManagerFactory;
        }
        //...
    }
  • ManagerFactoryImpl.java :

    @Named("managerFactory")
    public class ManagerFactoryImpl implements ManagerFactory {
        // ...
    }

Dans cet exemple, au moment de la réception de la requête HTTP sur .../demo, la classe d'action DemoAction est instanciée par Spring et le bean Spring managerFactory est injecté dans l'attribut managerFactory de l'instance de l'action par autowiring.

Désactiver l'autowiring

Personnellement, je préfère désactiver l'autowiring par nom et spécifier les éléments à injecter via les annotations de la JSR-330. Cela me permet d'avoir un meilleur contrôle des injections.

Pour cela, je modifie la propriété Struts struts.objectFactory.spring.autoWire, dans le fichier src/main/resources/struts.properties :

# Autowiring
struts.objectFactory.spring.autoWire=no

Et dans les classes d'action, j'ajoute l'annotation @Inject sur l'attribut managerFactory :

import javax.inject.Inject;

public class DemoAction extends ActionSupport {

    @Inject
    private ManagerFactory managerFactory;

    //...
}

Laisser Spring gérér complètement les objets Struts

Jusqu'ici, Spring ne fait qu'instancier et injecter les dépendances. Mais si vous souhaitez utiliser des fonctionnalités plus avancée de ce framework comme l'AOP, il vous sera peut-être nécessaire de déléguer complètement la gestion des objets Struts à Spring comme n'importe quel autre bean Spring.

Pour cela, dans le fichier configuration du mapping Struts (struts.xml), vous ne précisez alors plus les classes des actions dans l'attribut class, mais le nom du bean Spring à la place.

  • struts.xml :

    <!-- Action listant les projets -->
    <action name="demo" class="demoAction">
        <result>/jsp/view.jsp</result>
    </action>
  • webappContext.xml (fichier de configuration de Spring) :

    <beans>
        <bean id="demoAction"
              class="org.example.demo.ticket.webapp.action.DemoAction"
              singleton="false" />
        ...
    </beans>

Enlever le surplus de colle...

Maintenant que Spring est parfaitement intégré à mon application Struts, je peux enlever la rustine que constituait la classe org.example.demo.ticket.webapp.WebappHelper. En effet, celle-ci me permettait d'accéder aux beans Spring depuis les composants gérés par Struts, notamment les Actions.

Ce n'est déormais plus nécéssaire, car les beans sont injectés !

Je supprime donc la classe org.example.demo.ticket.webapp.WebappHelper et sa configuration dans Spring (/src/main/resources/org/example/demo/ticket/webapp/webappContext.xml) :

<!-- ==== WebappHelper ===== -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetClass" value="org.example.demo.ticket.webapp.WebappHelper"/>
    <property name="targetMethod" value="setManagerFactory"/>
    <property name="arguments" ref="managerFactory"/>
</bean>

Dans les classes d'action (GestionProjetActionLoginAction...), j'ajoute un attribut managerFactory annoté avec @Inject en remplacement des appels à WebappHelper.getManagerFactory() :

@Inject
private ManagerFactory managerFactory;

public String doList() {
    //listProjet = WebappHelper.getManagerFactory().getProjetManager().getListProjet();
    listProjet = managerFactory.getProjetManager().getListProjet();
    return ActionSupport.SUCCESS;
}

Conclusion

Comme vous avez pu le constater, l'intégration de Spring dans une application Struts est très simple grâce au plugin fourni par Struts.

Vous pouvez ainsi gérer vos composants Struts, comme les Actions, de la même manière que n'importe quel autre élément de votre application (instanciation, injection des dépendances...).

Si vous voulez approfondir ce sujet, vous pouvez consulter la documentation du plugin Spring.

Dans le chapitre suivant, j'aborderai le principe de conversion des paramètres HTTP reçus en entrée (donc de type String) en d'autres types Java.

Exemple de certificat de réussite
Exemple de certificat de réussite