Migration du code Open ENT NG vers Open ENT v3
Open ENT v3 s'appuie sur Quarkus et Vert.x 4. Voici les consignes pour migrer votre code vers Vert.x 4 :
-
Mettre à jour les dépendances :
- Assurez-vous que les dépendances de votre projet sont mises à jour vers Vert.x 4. Vérifiez votre fichier
pom.xml
oubuild.gradle
et remplacez les dépendances Vert.x 3 par leurs équivalents Vert.x 4.
- Assurez-vous que les dépendances de votre projet sont mises à jour vers Vert.x 4. Vérifiez votre fichier
-
Revoir les changements de l'API :
- Vert.x 4 a apporté plusieurs changements et améliorations à l'API. Consultez la documentation de l'API Vert.x 4 pour comprendre les nouvelles méthodes et classes. Portez une attention particulière aux changements dans les API principales, telles que
Vertx
,EventBus
etContext
.
- Vert.x 4 a apporté plusieurs changements et améliorations à l'API. Consultez la documentation de l'API Vert.x 4 pour comprendre les nouvelles méthodes et classes. Portez une attention particulière aux changements dans les API principales, telles que
-
Migration des mods Vert.x 3 vers des modules Quarkus
- Vert.x utilise des "mods" pour structurer les composants réutilisables et distribuables. Ces "mods" doivent être re-factorisés pour fonctionner dans l'écosystème Quarkus, souvent en adoptant des conventions Quarkus comme l'utilisation d'annotations CDI pour l'injection de dépendances, la gestion des configurations, etc.
Construction des applications Java
🪛 Open ENT v3 est construite avec Maven pour la partie backend et Yarn pour la partie frontend.
L'utilisation des dernières versions des outils de build sans l'usage des containers pour construire l'application est maintenant possible.
Les images suivantes sont remplacées par des images standards :
Outils | Version | Image Docker Open ENT NG | Image Docker Open ENT v3 |
---|---|---|---|
Node | 20.5.1 | opendigitaleducation/node::20-alpine-pnpm | node:lts-alpine3.20 |
Gradle | 4.5.1 (Java 8) | opendigitaleducation/gradle:4.5.1 | maven:3.9.8-amazoncorretto-21 |
Exemple avec maven
docker run -it --rm --name openent -v "$(pwd)":/mnt/ssd/Workspace-PassTech/ent/open-ent -w /mnt/ssd/Workspace-PassTech/ent/open-ent maven:3.9.8-amazoncorretto-21 mvn clean install
Changement de framework
Fonction | Open ENT NG | Open ENT v3 |
---|---|---|
Templating | Mustasche | Qute |
Cryptographie | fr.wseduc.webutils.security | Bouncy Castle |
Migration Mustache vers Qute
Fonction | Open ENT NG | Qute |
---|---|---|
I18n | {{#i18n}}admin.title{{/i18n}} | {i18n:['admin.title']} |
Migration des API de Cryptographie
Open ENT NG
BCrypt.hashpw(password, BCrypt.gensalt()));
Open ENT v3
SecureRandom secureRandom = new SecureRandom();
byte[] salt = new byte[12];
secureRandom.nextBytes(salt);
BCrypt.generate(password.getBytes(), salt, 12));
Migration des APIs Open ENT NG vers Open ENT v3
Open ENT NG
QueryBuilder query = QueryBuilder.start("_id").is(resourceId);
Open ENT v3
new JsonObject().put("_id", resourceId)
Suppression de la dépendance vers la lib MongoDB Helper
Open ENT NG
fr.wseduc.mongodb.MongoDB.parseIsoDate
Open ENT v3
org.entcore.common.utils.DateUtils.parseIsoDate
Open ENT NG
MongoDb.parseDate(date)
Open ENT v3
org.entcore.common.utils.DateUtils.parseIsoDate
Open ENT NG
MongoDb.formatDate(date)
Open ENT v3
org.entcore.common.utils.DateUtils.formatDate
In class fr.wseduc.mongodb.MongDB
Open ENT NG
public void find(String collection, JsonObject matcher, JsonObject sort, JsonObject keys,
Handler<Message<JsonObject>> callback)
Open ENT v3
io.vertx.ext.mongo.MongoClient.findOne(collection, query, Handler<AsyncResult<JsonObject>>)
Open ENT NG
final String prefix = getPathPrefix(config);
Open ENT v3
String prefix = DefaultResourcePath.DIRECTORY_HTTP_ROOT_PATH;
Open ENT NG
this.eb = Server.getEventBus(vertx);
Open ENT v3
this.eb = vertx.eventBus();
Migration des annotations
Open ENT NG
@ResourceFilter(SuperAdminFilter.class)
Open ENT v3
@Secured(roles = {Roles.SUPER_ADMIN})
Open ENT NG
@ResourceFilter(AdminFilter.class)
Open ENT v3
@Secured(roles = {Roles.SUPER_ADMIN, Roles.ADMIN_LOCAL})
Open ENT NG
UserUtils.getAuthenticatedUserInfos(eb, request)
.onSuccess(userInfos -> {
Open ENT v3
@Inject
JsonWebToken jwt;
UserInfos userInfos = new UserInfos(jwt);
Open ENT NG
notFound(request);
Open ENT v3
return Response.status(Response.Status.NOT_FOUND).build();
Open ENT NG
renderError(request);
Open ENT v3
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Internal Server Error: " + e.getMessage())
.build();
Open ENT NG
badRequest(request);
Open ENT v3
return Response.status(Response.Status.BAD_REQUEST)
.entity("Query parameter is missing or empty")
.build();
Open ENT NG
@BusAddress("event.store")
Open ENT v3
@ConsumeEvent("event.store")
Migration Vertx 3 vers Vertx 4 Voir Guide
Client Http Vert.x 3
client.putAbs()
Client Vert.x 4
client.request(HttpMethod.PUT,
Vert.x 3
eb.send
Vert.x 4
eb.request
final Future<Optional<String>> result = Future.future(); --> Promise<Optional<String>> promise = Promise.promise();
final Future<Void> result = Future.future(); --> Promise<Void> promise = Promise.promise();
Future<Entry<String, String>> future = Future.future(); --> Promise<Entry<String, String>> promise = Promise.promise();
return future; --> return promise.future();
futures.setHandler(res ->....) -> futures.onComplete(res ->
Migration du framework Web Utils vers JAXRS
JAX-RS est un framework basé sur Java utilisé pour créer des services web RESTful. Il fait partie de la suite Java EE (Enterprise Edition). Voici quelques adaptations de code avec le framework utilisé par défaut dans Open ET NG web-utils qui fonctionne uniquement avec Vert.x
@GET("/tenant/:id")
public void get(HttpServerRequest request) {
final String id = request.params().get("id");
@Get
@Path("/tenant/{id}")
public void get(HttpServerRequest request, @PathParam("id") String id) {
Migration des singletons Open ENT NG avec Jakarta EE
Pour transformer les classes singletons en un bean CDI avec Jakarta EE (anciennement Java EE), vous devrez procéder à quelques modifications. L'objectif est de tirer parti des fonctionnalités de CDI, telles que l'injection de dépendances, tout en éliminant le besoin d'une méthode getInstance pour gérer le singleton.
Utilisé :
@ApplicationScoped : Cette annotation permet à CDI de gérer le cycle de vie du bean. Une seule instance de JsonSchemaValidator sera créée pour l'application entière, remplaçant ainsi le besoin du modèle Singleton.
@Inject : Cette annotation est utilisée pour injecter automatiquement les instances nécessaires gérées par CDI.
Suppression du Singleton (getInstance) : Le code de gestion du singleton a été supprimé, car CDI gère automatiquement l'unicité de l'instance dans le contexte d'application.
Dépendances gérées par CDI : La gestion des dépendances est maintenant entièrement déléguée à CDI, simplifiant le code et améliorant l'intégration avec le reste de l'application Jakarta EE.
Migration des méthodes init des Verticle Vert.x
Chaque Vert.x Verticle avec Open ENT NG contient une phase d'initialisation permettant de déclarer les controllers et d'initialiser certaines classes partagées par ces controllers.
Les controllers sont remplacés par des Resources JAX-RS et l'initialisation se fait des injections automatiquement.
@Override
public void start() throws Exception {
final EventBus eb = getEventBus(vertx);
super.start();
MongoDbConf.getInstance().setCollection(SLOTPROFILE_COLLECTION);
setDefaultResourceFilter(new DirectoryResourcesProvider());
rm.get("/userbook/i18n", new Handler<HttpServerRequest>() {
@Override
public void handle(HttpServerRequest request) {
i18nMessages(request);
}
});
final StorageFactory storageFactory = new StorageFactory(vertx, config,
new MongoDBApplicationStorage("documents", Directory.class.getSimpleName()));
final Storage storageAvatar = new FileStorage(vertx, config.getString("avatar-path"),
config.getBoolean("avatar-flat", false), storageFactory.getMessagingClient());
final Storage defaulStorage = storageFactory.getStorage();
WorkspaceHelper wsHelper = new WorkspaceHelper(vertx.eventBus(), defaulStorage);
EmailFactory emailFactory = new EmailFactory(vertx, config);
EmailSender emailSender = emailFactory.getSender();
SmsSenderFactory.getInstance().init(vertx, config);
final JsonObject userBookData = config.getJsonObject("user-book-data");
UserService userService = new DefaultUserService(emailSender, eb, userBookData);
UserBookService userBookService = new DefaultUserBookService(eb, storageAvatar, wsHelper, userBookData);
TimelineHelper timeline = new TimelineHelper(vertx, eb, config);
ClassService classService = new DefaultClassService(eb);
SchoolService schoolService = new DefaultSchoolService(eb).setListUserMode(config.getString("listUserMode", "multi"));
GroupService groupService = new DefaultGroupService(eb);
SubjectService subjectService = new DefaultSubjectService(eb);
ConversationNotification conversationNotification = new ConversationNotification(vertx, eb, config);
DirectoryController directoryController = new DirectoryController();
directoryController.setClassService(classService);
directoryController.setSchoolService(schoolService);
directoryController.setUserService(userService);
directoryController.setGroupService(groupService);
directoryController.setSlotProfileService(new DefaultSlotProfileService(SLOTPROFILE_COLLECTION));
addController(directoryController);
vertx.setTimer(5000l, event -> directoryController.createSuperAdmin());
....
}
Les controllers sont remplacés par des Resources JAX-RS et l'initialisation se fait des injections automatiquement.
@ApplicationScoped
@Startup
public class DirectoryConfigService {
private JsonObject config;
@Inject
public DirectoryConfigService() {
this.loadConfig();
}
private void loadConfig() {
// Supposons que ConfigManager est une classe utilitaire personnalisée qui charge la configuration.
this.config = ConfigManager.getQuarkusConfig("directory");
}
@Produces
@OpenENT("directory")
public JsonObject getConfig() {
return config;
}
@Produces
@OpenENT("userBookData")
public JsonObject getConfigUserBookData() {
return config.getJsonObject("user-book-data");
}
@Produces
@OpenENT("emailSender")
public EmailSender getEmailSender(Vertx vertx, @OpenENT("directory")JsonObject config) {
EmailFactory emailFactory = new EmailFactory(vertx, config);
return emailFactory.getSender();
}
@Produces
@OpenENT("storage")
public Storage getStorage(Vertx vertx, @OpenENT("directory")JsonObject config) {
final StorageFactory storageFactory = new StorageFactory(vertx, config,
new MongoDBApplicationStorage("documents", DirectoryConfigService.class.getSimpleName()));
final Storage storageAvatar = new FileStorage(vertx, config.getString("avatar-path"),
config.getBoolean("avatar-flat", false), storageFactory.getMessagingClient());
final Storage defaulStorage = storageFactory.getStorage();
return defaulStorage;
}
}
Migration des tests unitaires
Les tests unitaires utilisent JUnit 4 ou certaines fois JUnit 5. Les annotations sont adaptées afin d'utiliser le contexte Quarkus et Vert.x
@RunWith(VertxUnitRunner.class)
public class FeederTest {
}
@QuarkusTest
@TestProfile(CustomTestProfile.class)
public class FeederTest {
}
Chaque test pourra avoir son propre profile avec ses variables d'environnements.
Usage du système de fichiers
Avec Vert.x 3 et les mods, les fichiers contenus dans un mods (un JAT Jar) étaient disponibles dans le répertoire mods. Ils étaient accédé par l'API :
final FileSystem fs = vertx.fileSystem();
Avec Vert.x 4, les fichiers contenus dans les modules quarkus sont conservés dans les librairies et disponibles dans le JAR.
Correspondance des urls
Certaines urls ne sont pas identiques entre Open ENT NG et Open ENT v3. Le nombre est vraiment limité pour simplifier les problèmes de montée de version.
Uniquement les API pour la partie authentification change en raison du passage du module auth vers la solution Keycloak
/auth/login
/realms/{{realm}}/protocol/openid-connect/token
Avec une variable realm généralement configurée à "openent"