SlideShare a Scribd company logo
1 of 21
Workshop Spring - Session 3 
Tests & Techniques avancées 
du conteneur Spring 
Conçu en décembre 2011 
Réactualisé en novembre 2014 
# 1
Sommaire 
Tests avec pring-test , DBUnit et Mockito 3 
Injection de beans de portées différentes 8 
Support des JSR 250 et 330 11 
Usage des post-processeurs de bean 13 
Externalisation de la configuration 17 
Accès aux ressources externes 19 
2
Spring et les Tests 
Conteneur léger accessible aux tests unitaires et 
d’intégration 
Support de JUnit 4 et TestNG 
Chargement du contexte Spring 
Injection de dépendances 
Mise en cache du contexte 
Extensions JUnit par 
Runner : SpringJUnit4ClassRunner 
Annotations : @ContextConfiguration, @Rollback, @Repeat … 
Listeners : DependencyInjectionTestExecutionListener … 
Bouchons prêts à l’emploi 
MockHttpSession, MockHttpServletRequest, 
MockPortletSession ... 
3 
Les apports du module Spring Test
4 
Spring et les Tests 
Test d’intégration d’un DAO 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("applicationContext-daos.xml") 
@Transactionnal 
public class IntTestHibernateAccountDao { 
@Autowired 
private HibernateAccountDao accountDao; 
@Rollback(false) 
@Test 
public void chargerCompteParIBAN(){ 
String iban = = "FR70 3000 2005 5000 0015 7845 Z02"; 
Account account = accountDao.findAccountByIBan(iban); 
assertNotNull(account); 
assertEquals("Account 1", account.getDescription()); 
} 
}
Retour d’Expérience projet 
Fixe un cadre technique d’utilisation de frameworks pour les tests : 
JUnit, spring-test, DbUnit, H2, Logback et Mockito 
Fournit une hiérarchie de classes réutilisables pour écrire un test 
unitaire 
Selon le besoin : test simple, avec Spring, JDBC, Hibernate, JSF 
Dans le but de tester une classe : notion de systemUnderTest (SUT) 
Fournit des annotations simplifiant la configuration des tests : 
@InjectInto : injection de propriétés dans l’instance testée 
@DataSet : charge un dataset DBUnit avant l’exécution du test 
@LoggingConfiguration : spécifie le fichier de configuration logback 
Outil de génération de dataset XML DbUnit à partir d’entités 
Hibernate ou JPA 
5 
Présentation d’une extension maison
6 
Retour d’Expérience projet 
Test unitaire d’un DAO avec cette extension 
Jeu de données DbUnit : TestHibernateAccountDao-dataset.xml 
<?xml version='1.0' encoding='UTF-8'?> 
<dataset> 
<ACCOUNT ID="1" BIC="FR7030002005500000157845Z02" LABEL=“Account 1"/> 
<ACCOUNT ID="2" BIC="FR70300023455000021Z4234Y45" LABEL="Account 2"/> 
</dataset> 
+ 
@LoggingConfiguration("classpath:logback-test-dao.xml") 
public class TestHibernateAccountDao extends 
AbstractDatasetSpringContextTest<HibernateAccountDao> { 
@Test 
public void findAccountByIBan() { 
String iban = "FR70 3000 2005 5000 0015 7845 Z02"; 
Account account = systemUnderTest.findAccountByIBan(iban); 
assertNotNull(account); 
assertEquals("Account 2", account.getDescription()); 
} 
}
7 
Retour d’Expérience projet 
Test unitaire d’un service avec cette extension 
@LoggingConfiguration("classpath:logback-test-service.xml") 
public class TestPublishingService extends 
AbstractCustomSpringContextTest<IPublishingService> { 
@Mock 
@InjectInto 
private IPublishingWebService publishingWs; 
@Test(expected = UnavailablePublishingException.class) // Assertions 
public void generatePDFwithPublishingTimeout () throws 
InvalidDataException, UnavailablePublishingException { 
// Prépare les données 
financialInvestment = new FinancialInvestment(); 
// Bouchonne les services tiers 
when(publishingWs.save(any(Document.class) 
.thenThrow(new SocketTimeoutException()); 
// Exécute le scénario 
systemUnderTest.generatePDF(financialInvestment ); 
} 
}
Injection de beans de portées différentes 
• Rappels 
• Un bean de portée Singleton se doit d’être thread-safe 
• Par défaut, un singleton est créé au démarrage du conteneur 
• Un bean de portée session est créé pour chaque session web utilisateur 
• Problématique 
– Injecter par auto-wiring un bean de portée Session dans un bean 
de portée Singleton 
• Cas d’usage 
– Avoir accès dans un service métier aux informations de l’utilisateur connecté 
– Besoin : contrôle des habilitations, historisation, logs … 
• Solution 
• Proxifier le bean de portée Session 
• Le proxy est chargé d’aiguiller les appels vers le bean session approprié 
8 
Injecter un bean de portée session dans un singleton (1/2) 
@Autowired 
protected UserDetails userDetails;
9 
Injection de beans de portées différentes 
Injecter un bean de portée session dans un singleton (2/2) 
Service 
singleton 
Proxy 
Informations 
Utilisateur 
Conteneur Spring 
Contrôleur 
singleton 
James 
session 
John 
session 
+MISE EN OEUVRE 
<bean id="authenticatedUserDetails" 
scope="session" 
class="com.javaetmoi.core.security.UserDetailsFactory" 
factory-method="getUserDetails"> 
<aop:scoped-proxy /> 
</bean> 
getName() getName() 
+ILLUSTRATION 
Implémentation basée sur le 
SecurityContextHolder de Spring 
Security
Injection de beans de portées différentes 
• RAPPEL 
– Une nouvelle instance est créée à chaque fois qu’un bean prototype est 
référencé 
• Problématique 
– Avoir un nouveau bean à chaque fois qu’on y fait appel depuis un singleton 
– Cas d’usage : Utiliser le pattern commande ou une classe non thread-safe 
depuis un singleton 
• Solution : Lookup ou injection de méthode 
10 
Injecter un prototype dans un singleton 
<bean id=“contractBuilder" 
class=“ContractBuilder" 
scope=“prototype“/> 
<bean id=“publishingService" 
class=“PublishingService"> 
<lookup-method 
name="getContractBuilder" 
bean="contractBuilder"/> 
</bean> 
public abstract class PublishingService { 
public void generatePDF() { 
ContractBuilder bld = getContractBuilder(); 
bld.setNumber("CA0000019876") 
// ... 
} 
abstract ContractBuilder getContractBuilder(); 
}
Support des JSR 
• Common annotations 1.0 
• Introduites dans Java EE 5 et dans Java 6 dans le package javax.annotation 
• Leur usage permet de coller aux standards et de se découpler de Spring 
• Annotations supportées 
• @PostConstruct : méthode appelée une fois le bean instancié et ses 
dépendances injectées 
• @PreDestroy : méthode appelée avant la destruction du bean 
• @RolesAllowed : sécurise l’appel d’une méthode (équivalent à @Secured) 
• @Resource : permet d’injecter une ressource JNDI (ex: DataSource) 
• Activation des annotations 
1. Par un post processeur de beans Spring 
<bean class="org.springframework.context. 
annotation.CommonAnnotationBeanPostProcessor"/> 
2. Ou par la balise XML annotation-config : 
<context:annotation-config/> 
11 
JSR 250 - Common annotations
Support des JSR 
• API Légère dédiée à l’injection de dépendances 
o Standardisation des annotations utilisées dans Spring et Google 
Guice 
o 5 annotations et 1 interface disponibles dans le package javax.inject : 
@Inject @Named, Provider, @Qualifier, @Scope, @Singleton 
• Support 
o JSR-330 Supportée à 100% par Spring 3.x 
o L’annotation @Inject peut se subsTituer à @Autowired 
o Les annotations @Qualifier fonctionnent différemment 
o Le changement de portée par défaut des beans spring peut être 
résolu par la classe Jsr330ScopeMetadataResolver 
• Préconisations 
o A utiliser pour le développement de frameworks / OSS 
o Intéressant dans une application lorsque Spring est uniquement 
utilisé comme simple moteur d’injection de dépendances 
12 
JSR 330 - Dependency Injection for java
Usage des post-processeurs de bean 
• Caractéristiques 
o Appelé pendant le processus de création de tout bean Spring 
o Implémente 2 méthodes appelées avant et après la méthode 
d’initialisation du bean 
o Peuvent être ordonnés 
• Etapes de mise à disposition d’un bean 
1. Création du bean par constructeur ou appel de méthode statique 
2. Valorisation des propriétés du bean 
3. Résolution des références vers d’autres beans (wiring) 
4. Appel de la méthode postProcessBeforeInitialization() de chaque post-processor 
5. Appel des méthodes d’initialisation du bean 
6. Appel de la méthode postProcessAfterInitialization() de chaque post-processor 
7. Le bean est prêt à être utilisé 
13 
Fonctionnement
Usage des post-processeurs de bean 
• Par spring 
14 
Utilisation au quotidien 
Post-Processeur Description 
AutowiredAnnotationBeanPostProcessor Active l’auto-wiring via les annotations @Autowired ou 
@Inject 
CommonAnnotationBeanPostProcessor Active la détection des annotations de la JSR-250 
AsyncAnnotationBeanPostProcessor Active la détection de l’annotation @Async 
ApplicationContextAwareProcessor Permet de passer le contexte applicatif Spring aux beans 
implémentant l’interface ApplicationContextAware 
ScriptFactoryPostProcessor Permet d’accéder au résultat de scripts (Groovy, JRuby ) 
• Par des frameworks tiers 
Post-Processeur Description 
BusExtensionPostProcessor Active la détection automatique d’extension de bus CXF 
Jsr181BeanPostProcessor Support de l’annotation @WebService par XFire
Usage des post-processeurs de bean 
• Problématique : enregistrer son propre plugin auprès du 
conteneur Spring pour traiter les instances de 
beans avant leur utilisation 
• Cas d’usage : Injecter un logger dans un bean 
15 
Créer sa propre annotation spring (1/2) 
@Service 
public class BankingService { 
private static final Logger LOGGER = 
LoggerFactory.getLogger(BankingService.class); 
… 
} 
@Service 
public class BankingService { 
@Logger 
private static Logger logger; 
… 
}
Usage des post-processeurs de bean 
Créer sa propre annotation spring (2/2) 
• Solution : créer une annotation et le post-processeur de 
bean chargé de l’interprêter 
@Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.FIELD }) 
public @interface Logger {} 
public class LoggerBeanPostProcessor implements BeanPostProcessor { 
16 
public Object postProcessBeforeInitialization(Object bean, 
String beanName) { 
ReflectionUtils.doWithFields(bean.getClass(), 
new ReflectionUtils.FieldCallback() { 
public void doWith(Field field) { 
if (field.getAnnotation(Logger.class) != null) { 
ReflectionUtils.makeAccessible(field); 
Logger logger =getLogger(bean.getClass().getName()); 
ReflectionUtils.setField(field, bean, logger); 
} } }); 
return bean; 
} … }
Externalisation de la configuration 
• Problématique 
o Le paramétrage d’une application web dépend de son environnement 
o Exemples : URL d’un web service, login / mot de passe, host d’un serveur 
mail 
o Comment externaliser leur paramétrage ? 
• Contraintes 
o L’EAR Validé en recette est celui déployé en production 
o Les paramètres doivent être externalisés en dehors de l’EAR 
o L’externalisation ne doit pas dépendre du serveur d’application 
o L’utilisation des URLResource de Websphere sont par exemple écartées 
• Solution envisagée 
o Utiliser un fichier de configuration qui sera accessible via le classpath 
o Activer le post-processeur de fabrique de beans 
PropertyPlaceholderConfigurer 
17 
Etude de Cas dans une application web
Externalisation de la configuration 
• Fichier de configuration 
18 
Injection de valeur 
Contenu du fichier config.properties: 
banking.iban.valid = true 
• Chargement par Spring 
<context:property-placeholder 
location="classpath:com/javaetmoi/config.properties" /> 
• Code Java 
@Service 
public class BankingService implements IBankingService{ 
@Value("${banking.valid.iban}") 
private Boolean validIban; 
… 
}
Chargement des ressources externes 
• Constat 
o Java n’offre pas de mécanisme unifié pour récupérer le contenu 
d’une ressource 
• Exemples de ressources : 
– Fichier texte, fichier de configuration XML, fichier properties, images … 
• Exemples de localisation : 
– Sur le système de fichier, dans un JAR inclu dans le classpath, via une URL … 
• Méthodes possibles 
o getClass().getResourceAsStream("path") 
o new URL("url").openConnection(). getInputStream() 
o new FileInputStream(new File("path")) 
• Problématique 
o Comment s’abstraire de la localisation d’une ressource ? 
19 
Méthodes hétérogènes
Chargement des ressources externes 
• Solution 
– Utiliser l’abstraction de ressources proposées par Spring via 
l’interface Resource 
• Une implémentation par type de localisation 
– FileSystemResource, ClassPathResource, UrlResource 
• Offre plusieurs fonctionnalités 
– Ouverture d’un flux, existante physique, description … 
• Localisation d’une ressource 
– La syntaxe des chemins d’une ressource est spécifique à Spring 
– Spring se base sur le préfixe pour déterminer quelle 
implémentation utiliser 
20 
Un mécanisme Unifié avec Spring 
Localisation de la ressource Exemple de chemins 
Classpath de la JVM classpath:com/javaetmoi/applicationContext-service.xml 
Accessible par une URL http://javaetmoi.com/feed.rss 
Sur le système de fichiers file:/d:/appli/demo/config.properties
Chargement des ressources externes 
• Utilisation par Spring 
– En interne, de nombreuses classes du framework utilisent l’interface Resource 
– Le contexte applicatif Spring dispose d’un chargeur de ressources 
– Exemple : new ClassPathXmlApplicationContext ( tableau de fichiers de conf ) 
• Injection de Ressources 
21 
Exemples d’utilisation 
public class MailAutomatiqueService { 
private Resource mailTemplate; 
// Getter 
} 
<bean id="emailService" 
class="com.javaetmoi.EmailService"> 
<property name="mailTemplate"> 
<value>classpath:com/javaetmoi/bfa/mail.vl</value> 
</property> 
</bean>

More Related Content

What's hot

Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Eric SIBER
 
Concevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring BootConcevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring BootDNG Consulting
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications JavaAntoine Rey
 
Architecture java j2 ee a partager
Architecture java j2 ee a partagerArchitecture java j2 ee a partager
Architecture java j2 ee a partageraliagadir
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application javaAntoine Rey
 
Microbox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien RoyMicrobox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien Royekino
 
Installation et Configuration ee JDK et de Tomcat
Installation et Configuration ee JDK et de TomcatInstallation et Configuration ee JDK et de Tomcat
Installation et Configuration ee JDK et de TomcatMohamed Ben Bouzid
 
JBoss - chapitre JMX
JBoss - chapitre JMXJBoss - chapitre JMX
JBoss - chapitre JMXFranck SIMON
 
Presentation Spring, Spring MVC
Presentation Spring, Spring MVCPresentation Spring, Spring MVC
Presentation Spring, Spring MVCNathaniel Richand
 
Presentation JEE et son écossystéme
Presentation JEE et son écossystémePresentation JEE et son écossystéme
Presentation JEE et son écossystémeAlgeria JUG
 
Une (simple) présentation de Apache Maven 2
Une (simple) présentation de Apache Maven 2Une (simple) présentation de Apache Maven 2
Une (simple) présentation de Apache Maven 2teejug
 
Tech Days Spring Intégration
Tech Days Spring IntégrationTech Days Spring Intégration
Tech Days Spring IntégrationArrow-Institute
 
Déploiement d'applications Java EE
Déploiement d'applications Java EEDéploiement d'applications Java EE
Déploiement d'applications Java EEjavalabsf
 

What's hot (20)

ParisJUG Spring Boot
ParisJUG Spring BootParisJUG Spring Boot
ParisJUG Spring Boot
 
Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)
 
Concevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring BootConcevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring Boot
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
 
Architecture java j2 ee a partager
Architecture java j2 ee a partagerArchitecture java j2 ee a partager
Architecture java j2 ee a partager
 
Spring 3.0
Spring 3.0Spring 3.0
Spring 3.0
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application java
 
Maven
MavenMaven
Maven
 
Microbox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien RoyMicrobox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien Roy
 
Installation et Configuration ee JDK et de Tomcat
Installation et Configuration ee JDK et de TomcatInstallation et Configuration ee JDK et de Tomcat
Installation et Configuration ee JDK et de Tomcat
 
Cours jee 1
Cours jee 1Cours jee 1
Cours jee 1
 
Spring mvc
Spring mvcSpring mvc
Spring mvc
 
JBoss - chapitre JMX
JBoss - chapitre JMXJBoss - chapitre JMX
JBoss - chapitre JMX
 
Presentation Spring, Spring MVC
Presentation Spring, Spring MVCPresentation Spring, Spring MVC
Presentation Spring, Spring MVC
 
Presentation JEE et son écossystéme
Presentation JEE et son écossystémePresentation JEE et son écossystéme
Presentation JEE et son écossystéme
 
Présentation1
Présentation1Présentation1
Présentation1
 
Une (simple) présentation de Apache Maven 2
Une (simple) présentation de Apache Maven 2Une (simple) présentation de Apache Maven 2
Une (simple) présentation de Apache Maven 2
 
Spring & SpringBatch FR
Spring & SpringBatch FRSpring & SpringBatch FR
Spring & SpringBatch FR
 
Tech Days Spring Intégration
Tech Days Spring IntégrationTech Days Spring Intégration
Tech Days Spring Intégration
 
Déploiement d'applications Java EE
Déploiement d'applications Java EEDéploiement d'applications Java EE
Déploiement d'applications Java EE
 

Viewers also liked

Les Streams de Java 8
Les Streams de Java 8Les Streams de Java 8
Les Streams de Java 8Antoine Rey
 
Microservices with .Net - NDC Sydney, 2016
Microservices with .Net - NDC Sydney, 2016Microservices with .Net - NDC Sydney, 2016
Microservices with .Net - NDC Sydney, 2016Richard Banks
 
pessimistic-development-presentation
pessimistic-development-presentationpessimistic-development-presentation
pessimistic-development-presentationJonathan Marbutt
 
Learned optimism
Learned optimismLearned optimism
Learned optimismAndrew Chaa
 
Introduction à Angular JS
Introduction à Angular JSIntroduction à Angular JS
Introduction à Angular JSAntoine Rey
 
Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample applicationAntoine Rey
 

Viewers also liked (6)

Les Streams de Java 8
Les Streams de Java 8Les Streams de Java 8
Les Streams de Java 8
 
Microservices with .Net - NDC Sydney, 2016
Microservices with .Net - NDC Sydney, 2016Microservices with .Net - NDC Sydney, 2016
Microservices with .Net - NDC Sydney, 2016
 
pessimistic-development-presentation
pessimistic-development-presentationpessimistic-development-presentation
pessimistic-development-presentation
 
Learned optimism
Learned optimismLearned optimism
Learned optimism
 
Introduction à Angular JS
Introduction à Angular JSIntroduction à Angular JS
Introduction à Angular JS
 
Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample application
 

Similar to Workshop Spring 3 - Tests et techniques avancées du conteneur Spring

#5 Java EE5 Client Lourd et Smart Client
#5 Java EE5  Client Lourd  et Smart Client#5 Java EE5  Client Lourd  et Smart Client
#5 Java EE5 Client Lourd et Smart ClientGuillaume Sauthier
 
Liferay france symposium 2012 - montée de version d’une instance liferay
Liferay france symposium 2012 - montée de version d’une instance liferayLiferay france symposium 2012 - montée de version d’une instance liferay
Liferay france symposium 2012 - montée de version d’une instance liferaySébastien Le Marchand
 
cours8-GL-minfo-1718.pdf
cours8-GL-minfo-1718.pdfcours8-GL-minfo-1718.pdf
cours8-GL-minfo-1718.pdfSliimAmiri
 
Spring 3 en production
Spring 3 en productionSpring 3 en production
Spring 3 en productionJulien Dubois
 
Play Framework
Play FrameworkPlay Framework
Play FrameworkArmaklan
 
Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017Julien Dubois
 
Bean Validation - Cours v 1.1
Bean Validation - Cours v 1.1Bean Validation - Cours v 1.1
Bean Validation - Cours v 1.1Laurent Guérin
 
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services Par Al...
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services  Par Al...XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services  Par Al...
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services Par Al...Publicis Sapient Engineering
 
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOps@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOlivier DASINI
 
Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Xavier NOPRE
 
Build automatique et distribution OTA avec Xcode 4.x et Jenkins
Build automatique et distribution OTA avec Xcode 4.x et JenkinsBuild automatique et distribution OTA avec Xcode 4.x et Jenkins
Build automatique et distribution OTA avec Xcode 4.x et JenkinsCocoaHeads France
 
Java version 11 - les 9 nouveautes
Java version 11 -  les 9 nouveautesJava version 11 -  les 9 nouveautes
Java version 11 - les 9 nouveautesAbdenour Bouateli
 
Environnements, Sources de propriétés et Profils avec Spring 3.1
Environnements, Sources de propriétés et Profils avec Spring 3.1Environnements, Sources de propriétés et Profils avec Spring 3.1
Environnements, Sources de propriétés et Profils avec Spring 3.1Fabien Baligand
 

Similar to Workshop Spring 3 - Tests et techniques avancées du conteneur Spring (20)

2
22
2
 
#5 Java EE5 Client Lourd et Smart Client
#5 Java EE5  Client Lourd  et Smart Client#5 Java EE5  Client Lourd  et Smart Client
#5 Java EE5 Client Lourd et Smart Client
 
Liferay france symposium 2012 - montée de version d’une instance liferay
Liferay france symposium 2012 - montée de version d’une instance liferayLiferay france symposium 2012 - montée de version d’une instance liferay
Liferay france symposium 2012 - montée de version d’une instance liferay
 
cours8-GL-minfo-1718.pdf
cours8-GL-minfo-1718.pdfcours8-GL-minfo-1718.pdf
cours8-GL-minfo-1718.pdf
 
Spring 3 en production
Spring 3 en productionSpring 3 en production
Spring 3 en production
 
Play Framework
Play FrameworkPlay Framework
Play Framework
 
Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017
 
Présentation nouveauté java7
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7
 
Bean Validation - Cours v 1.1
Bean Validation - Cours v 1.1Bean Validation - Cours v 1.1
Bean Validation - Cours v 1.1
 
YaJUG - Spring 3.0
YaJUG - Spring 3.0YaJUG - Spring 3.0
YaJUG - Spring 3.0
 
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services Par Al...
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services  Par Al...XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services  Par Al...
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services Par Al...
 
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOps@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
 
Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013
 
Build automatique et distribution OTA avec Xcode 4.x et Jenkins
Build automatique et distribution OTA avec Xcode 4.x et JenkinsBuild automatique et distribution OTA avec Xcode 4.x et Jenkins
Build automatique et distribution OTA avec Xcode 4.x et Jenkins
 
Java version 11 - les 9 nouveautes
Java version 11 -  les 9 nouveautesJava version 11 -  les 9 nouveautes
Java version 11 - les 9 nouveautes
 
Les annotations
Les annotationsLes annotations
Les annotations
 
Springioc
SpringiocSpringioc
Springioc
 
Environnements, Sources de propriétés et Profils avec Spring 3.1
Environnements, Sources de propriétés et Profils avec Spring 3.1Environnements, Sources de propriétés et Profils avec Spring 3.1
Environnements, Sources de propriétés et Profils avec Spring 3.1
 
tp-spring.pdf
tp-spring.pdftp-spring.pdf
tp-spring.pdf
 
tp-spring.pdf
tp-spring.pdftp-spring.pdf
tp-spring.pdf
 

Workshop Spring 3 - Tests et techniques avancées du conteneur Spring

  • 1. Workshop Spring - Session 3 Tests & Techniques avancées du conteneur Spring Conçu en décembre 2011 Réactualisé en novembre 2014 # 1
  • 2. Sommaire Tests avec pring-test , DBUnit et Mockito 3 Injection de beans de portées différentes 8 Support des JSR 250 et 330 11 Usage des post-processeurs de bean 13 Externalisation de la configuration 17 Accès aux ressources externes 19 2
  • 3. Spring et les Tests Conteneur léger accessible aux tests unitaires et d’intégration Support de JUnit 4 et TestNG Chargement du contexte Spring Injection de dépendances Mise en cache du contexte Extensions JUnit par Runner : SpringJUnit4ClassRunner Annotations : @ContextConfiguration, @Rollback, @Repeat … Listeners : DependencyInjectionTestExecutionListener … Bouchons prêts à l’emploi MockHttpSession, MockHttpServletRequest, MockPortletSession ... 3 Les apports du module Spring Test
  • 4. 4 Spring et les Tests Test d’intégration d’un DAO @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("applicationContext-daos.xml") @Transactionnal public class IntTestHibernateAccountDao { @Autowired private HibernateAccountDao accountDao; @Rollback(false) @Test public void chargerCompteParIBAN(){ String iban = = "FR70 3000 2005 5000 0015 7845 Z02"; Account account = accountDao.findAccountByIBan(iban); assertNotNull(account); assertEquals("Account 1", account.getDescription()); } }
  • 5. Retour d’Expérience projet Fixe un cadre technique d’utilisation de frameworks pour les tests : JUnit, spring-test, DbUnit, H2, Logback et Mockito Fournit une hiérarchie de classes réutilisables pour écrire un test unitaire Selon le besoin : test simple, avec Spring, JDBC, Hibernate, JSF Dans le but de tester une classe : notion de systemUnderTest (SUT) Fournit des annotations simplifiant la configuration des tests : @InjectInto : injection de propriétés dans l’instance testée @DataSet : charge un dataset DBUnit avant l’exécution du test @LoggingConfiguration : spécifie le fichier de configuration logback Outil de génération de dataset XML DbUnit à partir d’entités Hibernate ou JPA 5 Présentation d’une extension maison
  • 6. 6 Retour d’Expérience projet Test unitaire d’un DAO avec cette extension Jeu de données DbUnit : TestHibernateAccountDao-dataset.xml <?xml version='1.0' encoding='UTF-8'?> <dataset> <ACCOUNT ID="1" BIC="FR7030002005500000157845Z02" LABEL=“Account 1"/> <ACCOUNT ID="2" BIC="FR70300023455000021Z4234Y45" LABEL="Account 2"/> </dataset> + @LoggingConfiguration("classpath:logback-test-dao.xml") public class TestHibernateAccountDao extends AbstractDatasetSpringContextTest<HibernateAccountDao> { @Test public void findAccountByIBan() { String iban = "FR70 3000 2005 5000 0015 7845 Z02"; Account account = systemUnderTest.findAccountByIBan(iban); assertNotNull(account); assertEquals("Account 2", account.getDescription()); } }
  • 7. 7 Retour d’Expérience projet Test unitaire d’un service avec cette extension @LoggingConfiguration("classpath:logback-test-service.xml") public class TestPublishingService extends AbstractCustomSpringContextTest<IPublishingService> { @Mock @InjectInto private IPublishingWebService publishingWs; @Test(expected = UnavailablePublishingException.class) // Assertions public void generatePDFwithPublishingTimeout () throws InvalidDataException, UnavailablePublishingException { // Prépare les données financialInvestment = new FinancialInvestment(); // Bouchonne les services tiers when(publishingWs.save(any(Document.class) .thenThrow(new SocketTimeoutException()); // Exécute le scénario systemUnderTest.generatePDF(financialInvestment ); } }
  • 8. Injection de beans de portées différentes • Rappels • Un bean de portée Singleton se doit d’être thread-safe • Par défaut, un singleton est créé au démarrage du conteneur • Un bean de portée session est créé pour chaque session web utilisateur • Problématique – Injecter par auto-wiring un bean de portée Session dans un bean de portée Singleton • Cas d’usage – Avoir accès dans un service métier aux informations de l’utilisateur connecté – Besoin : contrôle des habilitations, historisation, logs … • Solution • Proxifier le bean de portée Session • Le proxy est chargé d’aiguiller les appels vers le bean session approprié 8 Injecter un bean de portée session dans un singleton (1/2) @Autowired protected UserDetails userDetails;
  • 9. 9 Injection de beans de portées différentes Injecter un bean de portée session dans un singleton (2/2) Service singleton Proxy Informations Utilisateur Conteneur Spring Contrôleur singleton James session John session +MISE EN OEUVRE <bean id="authenticatedUserDetails" scope="session" class="com.javaetmoi.core.security.UserDetailsFactory" factory-method="getUserDetails"> <aop:scoped-proxy /> </bean> getName() getName() +ILLUSTRATION Implémentation basée sur le SecurityContextHolder de Spring Security
  • 10. Injection de beans de portées différentes • RAPPEL – Une nouvelle instance est créée à chaque fois qu’un bean prototype est référencé • Problématique – Avoir un nouveau bean à chaque fois qu’on y fait appel depuis un singleton – Cas d’usage : Utiliser le pattern commande ou une classe non thread-safe depuis un singleton • Solution : Lookup ou injection de méthode 10 Injecter un prototype dans un singleton <bean id=“contractBuilder" class=“ContractBuilder" scope=“prototype“/> <bean id=“publishingService" class=“PublishingService"> <lookup-method name="getContractBuilder" bean="contractBuilder"/> </bean> public abstract class PublishingService { public void generatePDF() { ContractBuilder bld = getContractBuilder(); bld.setNumber("CA0000019876") // ... } abstract ContractBuilder getContractBuilder(); }
  • 11. Support des JSR • Common annotations 1.0 • Introduites dans Java EE 5 et dans Java 6 dans le package javax.annotation • Leur usage permet de coller aux standards et de se découpler de Spring • Annotations supportées • @PostConstruct : méthode appelée une fois le bean instancié et ses dépendances injectées • @PreDestroy : méthode appelée avant la destruction du bean • @RolesAllowed : sécurise l’appel d’une méthode (équivalent à @Secured) • @Resource : permet d’injecter une ressource JNDI (ex: DataSource) • Activation des annotations 1. Par un post processeur de beans Spring <bean class="org.springframework.context. annotation.CommonAnnotationBeanPostProcessor"/> 2. Ou par la balise XML annotation-config : <context:annotation-config/> 11 JSR 250 - Common annotations
  • 12. Support des JSR • API Légère dédiée à l’injection de dépendances o Standardisation des annotations utilisées dans Spring et Google Guice o 5 annotations et 1 interface disponibles dans le package javax.inject : @Inject @Named, Provider, @Qualifier, @Scope, @Singleton • Support o JSR-330 Supportée à 100% par Spring 3.x o L’annotation @Inject peut se subsTituer à @Autowired o Les annotations @Qualifier fonctionnent différemment o Le changement de portée par défaut des beans spring peut être résolu par la classe Jsr330ScopeMetadataResolver • Préconisations o A utiliser pour le développement de frameworks / OSS o Intéressant dans une application lorsque Spring est uniquement utilisé comme simple moteur d’injection de dépendances 12 JSR 330 - Dependency Injection for java
  • 13. Usage des post-processeurs de bean • Caractéristiques o Appelé pendant le processus de création de tout bean Spring o Implémente 2 méthodes appelées avant et après la méthode d’initialisation du bean o Peuvent être ordonnés • Etapes de mise à disposition d’un bean 1. Création du bean par constructeur ou appel de méthode statique 2. Valorisation des propriétés du bean 3. Résolution des références vers d’autres beans (wiring) 4. Appel de la méthode postProcessBeforeInitialization() de chaque post-processor 5. Appel des méthodes d’initialisation du bean 6. Appel de la méthode postProcessAfterInitialization() de chaque post-processor 7. Le bean est prêt à être utilisé 13 Fonctionnement
  • 14. Usage des post-processeurs de bean • Par spring 14 Utilisation au quotidien Post-Processeur Description AutowiredAnnotationBeanPostProcessor Active l’auto-wiring via les annotations @Autowired ou @Inject CommonAnnotationBeanPostProcessor Active la détection des annotations de la JSR-250 AsyncAnnotationBeanPostProcessor Active la détection de l’annotation @Async ApplicationContextAwareProcessor Permet de passer le contexte applicatif Spring aux beans implémentant l’interface ApplicationContextAware ScriptFactoryPostProcessor Permet d’accéder au résultat de scripts (Groovy, JRuby ) • Par des frameworks tiers Post-Processeur Description BusExtensionPostProcessor Active la détection automatique d’extension de bus CXF Jsr181BeanPostProcessor Support de l’annotation @WebService par XFire
  • 15. Usage des post-processeurs de bean • Problématique : enregistrer son propre plugin auprès du conteneur Spring pour traiter les instances de beans avant leur utilisation • Cas d’usage : Injecter un logger dans un bean 15 Créer sa propre annotation spring (1/2) @Service public class BankingService { private static final Logger LOGGER = LoggerFactory.getLogger(BankingService.class); … } @Service public class BankingService { @Logger private static Logger logger; … }
  • 16. Usage des post-processeurs de bean Créer sa propre annotation spring (2/2) • Solution : créer une annotation et le post-processeur de bean chargé de l’interprêter @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.FIELD }) public @interface Logger {} public class LoggerBeanPostProcessor implements BeanPostProcessor { 16 public Object postProcessBeforeInitialization(Object bean, String beanName) { ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() { public void doWith(Field field) { if (field.getAnnotation(Logger.class) != null) { ReflectionUtils.makeAccessible(field); Logger logger =getLogger(bean.getClass().getName()); ReflectionUtils.setField(field, bean, logger); } } }); return bean; } … }
  • 17. Externalisation de la configuration • Problématique o Le paramétrage d’une application web dépend de son environnement o Exemples : URL d’un web service, login / mot de passe, host d’un serveur mail o Comment externaliser leur paramétrage ? • Contraintes o L’EAR Validé en recette est celui déployé en production o Les paramètres doivent être externalisés en dehors de l’EAR o L’externalisation ne doit pas dépendre du serveur d’application o L’utilisation des URLResource de Websphere sont par exemple écartées • Solution envisagée o Utiliser un fichier de configuration qui sera accessible via le classpath o Activer le post-processeur de fabrique de beans PropertyPlaceholderConfigurer 17 Etude de Cas dans une application web
  • 18. Externalisation de la configuration • Fichier de configuration 18 Injection de valeur Contenu du fichier config.properties: banking.iban.valid = true • Chargement par Spring <context:property-placeholder location="classpath:com/javaetmoi/config.properties" /> • Code Java @Service public class BankingService implements IBankingService{ @Value("${banking.valid.iban}") private Boolean validIban; … }
  • 19. Chargement des ressources externes • Constat o Java n’offre pas de mécanisme unifié pour récupérer le contenu d’une ressource • Exemples de ressources : – Fichier texte, fichier de configuration XML, fichier properties, images … • Exemples de localisation : – Sur le système de fichier, dans un JAR inclu dans le classpath, via une URL … • Méthodes possibles o getClass().getResourceAsStream("path") o new URL("url").openConnection(). getInputStream() o new FileInputStream(new File("path")) • Problématique o Comment s’abstraire de la localisation d’une ressource ? 19 Méthodes hétérogènes
  • 20. Chargement des ressources externes • Solution – Utiliser l’abstraction de ressources proposées par Spring via l’interface Resource • Une implémentation par type de localisation – FileSystemResource, ClassPathResource, UrlResource • Offre plusieurs fonctionnalités – Ouverture d’un flux, existante physique, description … • Localisation d’une ressource – La syntaxe des chemins d’une ressource est spécifique à Spring – Spring se base sur le préfixe pour déterminer quelle implémentation utiliser 20 Un mécanisme Unifié avec Spring Localisation de la ressource Exemple de chemins Classpath de la JVM classpath:com/javaetmoi/applicationContext-service.xml Accessible par une URL http://javaetmoi.com/feed.rss Sur le système de fichiers file:/d:/appli/demo/config.properties
  • 21. Chargement des ressources externes • Utilisation par Spring – En interne, de nombreuses classes du framework utilisent l’interface Resource – Le contexte applicatif Spring dispose d’un chargeur de ressources – Exemple : new ClassPathXmlApplicationContext ( tableau de fichiers de conf ) • Injection de Ressources 21 Exemples d’utilisation public class MailAutomatiqueService { private Resource mailTemplate; // Getter } <bean id="emailService" class="com.javaetmoi.EmailService"> <property name="mailTemplate"> <value>classpath:com/javaetmoi/bfa/mail.vl</value> </property> </bean>