Slide 1

Slide 1 text

REX : entamer une migration dans une DSI Java Speaker : Jean-Philippe Baconnais - @JPhi_Baconnais

Slide 2

Slide 2 text

JPhi_Baconnais Tech Lead à la DSI de Pôle emploi

Slide 3

Slide 3 text

Contexte de la DSI Pôle emploi

Slide 4

Slide 4 text

Cobol 2000 Java avec FMK interne API Rest Java avec FMK interne 2007 2018 Premier test d’intégration Kotlin ? Développement Kotlin en production

Slide 5

Slide 5 text

Notre framework interne

Slide 6

Slide 6 text

Code fonctionnel Métrologie Logging Sécurité Annuaire Cache

Slide 7

Slide 7 text

Le Kotlin dans tout ça ?

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

“ Les nouveaux dév seront fait en Kotlin ! ”

Slide 10

Slide 10 text

https://unsplash.com/@kaip

Slide 11

Slide 11 text

L’infrastructure est trop complexe et créer de nouveaux composants en Kotlin serait compliqué !

Slide 12

Slide 12 text

Migrons progressivement notre code Java en Kotlin https://unsplash.com/@freegraphictoday

Slide 13

Slide 13 text

L’intégration de Kotlin dans notre éco-système

Slide 14

Slide 14 text

Architecture de notre code fonctionnel

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Choix de migration

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

public class Person implements Cloneable{ private String name; private Integer id; public Person(String name,Integer id){ this.name = name; this.id = id; } public String getName(){ return name; } public void setName(String name){ this.name = name; } public Integer getId(){ return id; } public void setId(Integer id){ this.id = id; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != this.getClass()) { return false; } Person guest = (Person) obj; return id == guest.id && (name == guest.getName || (name != null && name.equals(guest.getName())))); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + id; return result; } @Override public String toString(){ return"Person(name="+name+",id="+id") "; } @Override public Object clone(){ Person person = null; try { person = (Person) super.clone(); } catch(CloneNotSupportedException cnse) { cnse.printStackTrace(System.err); } person.name = (String) name.clone(); person.id = (Integer) id.clone(); return person; } }

Slide 19

Slide 19 text

data class User(val name: String, val id: Int)

Slide 20

Slide 20 text

Les étapes de modification de notre composant

Slide 21

Slide 21 text

1 / Installer le plugin Kotlin dans l’IDE

Slide 22

Slide 22 text

2 / Clic droit -> convertir en kotlin

Slide 23

Slide 23 text

3 / Déplacer les sources dans un package Kotlin

Slide 24

Slide 24 text

4 / Ajout de la dépendance Kotlin 1.3.21 org.jetbrains.kotlin kotlin-stdlib-jdk8 ${kotlin.version}

Slide 25

Slide 25 text

5 / Déclaration ressources Kotlin

Slide 26

Slide 26 text

org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} [...] src/main/java src/main/kotlin src/main/resources

Slide 27

Slide 27 text

org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} [...] src/main/java src/main/kotlin src/main/resources

Slide 28

Slide 28 text

6 / Quelques ajustements dans le code

Slide 29

Slide 29 text

Erreur de compilation : Property must be initialized or be abstract

Slide 30

Slide 30 text

class ConstantesServices { companion object { val MEDIA_TYPE_UTILISE:MediaType! = MediaType.APPLICATION_JSON_TYPE.withCharset(CharEncoding. UTF_8) } } class ConstantesServices { companion object { @kotlin.jvm.JvmField var MEDIA_TYPE_UTILISE = MediaType.APPLICATION_JSON_TYPE.withCharset(CharEncoding.UTF_8) } }

Slide 31

Slide 31 text

class ConstantesServices { companion object { val MEDIA_TYPE_UTILISE:MediaType! = MediaType.APPLICATION_JSON_TYPE.withCharset(CharEncoding. UTF_8) } } class ConstantesServices { companion object { @kotlin.jvm.JvmField var MEDIA_TYPE_UTILISE = MediaType.APPLICATION_JSON_TYPE.withCharset(CharEncoding.UTF_8) } }

Slide 32

Slide 32 text

7 / Les tests

Slide 33

Slide 33 text

Mockito 1.9 ⇒ 2

Slide 34

Slide 34 text

Whitebox

Slide 35

Slide 35 text

org.mockito.exceptions.base.MockitoException: Cannot mock/spy class data.MiniSite Mockito cannot mock/spy because : - final class

Slide 36

Slide 36 text

mock-maker-inline

Slide 37

Slide 37 text

Et ça marche !

Slide 38

Slide 38 text

Migration réussie Le composant fonctionne sans régression Plus value pas très haute Mais du Kotlin a été intégré !

Slide 39

Slide 39 text

La suite ?

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Faire des tests Kotlin

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

@Test fun givenServiceMock_whenCallingMockedMethod_thenCorrectlyVerified() { // given val service = mockk() every { service.getDataFromDb("Expected Param") } returns "Expected Output" // when val result = service.getDataFromDb("Expected Param") // then verify { service.getDataFromDb("Expected Param") } assertEquals("Expected Output", result) }

Slide 44

Slide 44 text

Bencher le composant

Slide 45

Slide 45 text

Installation en production ! https://unsplash.com/@doran_

Slide 46

Slide 46 text

Merci ! JPhi_Baconnais