Skip to content

Java and co

MAIRE Jérémy edited this page Feb 16, 2026 · 20 revisions

Spring Data

Projections

Pour récupérer seulement quelques champs via Spring Data JPA, on peut utiliser les projections

https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html

(soit en déclarant des interfaces, soit en déclarant des records)

Doc pour construire les requêtes https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.html

Hibernate / Eager

@EntityGraph allows you to define a graph of entities that should be fetched from the database in a single selection for a specific use case. We can define an EntityGraph on the repository method to eagerly fetch the required associations. This makes sure the data is already loaded when the session is open, preventing the LazyInitializationException. Yet, we preserve the benefits of lazy loading, since we have complete control over when the eager fetch is applied.

source : https://www.tomaszezula.com/optimizing-eager-fetch-with-spring-data-and-entitygraph-annotation/

Thread Local

But : stocker des données pour les traitements effectués dans un thread

Bien penser à déclarer la variable ThreadLocal en static (question de perf) et à nettoyer après

Validation de données

https://medium.com/googledeveloperseurope/advanced-jakarta-3-0-validation-pretty-little-magic-ull-fall-in-love-with-21969ff3006a

Pour valider des données (par exemple en entrée d'un controleur Rest ou d'un consumer Kafka), on peut ajouter des annotations sur le DTO. Il existe certaines annotations pré codées (@NotNull par exemple) mais il est possible d'en coder des spécifiques avec une classe implémentant ConstraintValidator

TU, liste

Si on une liste d'objets sur lesquels on veut faire des assertions, par exemple une liste de livres, on peut faire

assertThat(books)
.extracting(Book::getTitle, Book::getLanguage, Book::getAuthor)
.containsExactlyInAnyOrder(
tuple("LoTR","English","JRR Tolkien"),
tuple("La nuit des temps", "French", "Barjavel"));

Si on doit vérifier qu'un message fait partie d'une liste (cas d'un message s'affichant en français en local et en anglais sur la pic), on peut utiliser

    assertThat(result)
        .extracting(result::getMessage)
        .singleElement()
        .satisfies(
            m ->
                assertThat(m)
                    .containsAnyOf(taille)
                    .containsAnyOf(taille, "la taille doit être", "size must be"));
    // "taille" en local sur PC français et "size" sur PIC

Lecture / videos

https://ivan.canet.dev/blog/2024/10/07/flee-throwable.html

https://medium.com/@wakefulinsomnia/how-does-java-classloader-system-work-82eaf378f73b

https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding

https://advancedweb.hu/a-categorized-list-of-all-java-and-jvm-features-since-jdk-8-to-21/

https://javaconceptoftheday.com/java-9-try-with-resources-improvements/ (d'autres pages expliquant les changements entre une version et une autre)

https://inside.java/2025/01/28/jvm-start-up/

https://www.youtube.com/@JakobJenkov

https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Record.java

https://nipafx.dev/#channels~~articles dev at Oracle (or at least publish videos on official Java YT channel)

Validation dans un builder https://softwareengineering.stackexchange.com/questions/241309/builder-pattern-when-to-fail/241319#241319

Async en Java

Création d'un pool de thread

Pour cela on va utiliser une des méthodes de Executors, par exemple newFixedThreadPool si on souhaite avoir un pool de thread fixe.

Appel du code asynchrone

On va utiliser soit du Callable soit du Runnable. Puis on va utiliser la méthode submit pour lui passer notre code.

Pièges classiques

Il faut bien penser à supprimer le pool de thread à l'extinction de l'application, sinon la JVM ne va pas s'arrêter.

Certaines variables ne sont pas partagées entre les différents threads.

Tests

Mockito possède une méthode timeout qui permet d'attendre qu'une méthode soit appelée.

Bonus

Aller jeter un oeil dans les classes du package java.util.concurrent

Misc tips

Pour debugger un erreur 400 bad request sur un controller Spring, passer en debug les logs de org.springframework.web.servlet.mvc.method.annotation

Java core

Mémoire

Stack / Heap / Metaspace

Stack memory : variables locales, appels de méthodes, références de données (si plein : stack overflow). Allocation statique. Valeurs primitives. N'existe que le temps de l'exécution d'une méthode. Propre à un seul thread.

Heap memory : new objets et données dynamiques au run time, pool de strings, stockage de données. Différentes générations (young, old, permanent) Si plein : out of memory. Nettoyé par GC. Partagée entre les différents threads.

Heap Size > Stack size

heap : zone sans ordre alors que stack : LIFO (permet de faire de la récursivité) https://www.baeldung.com/java-memory-management-interview-questions + https://javamidnight.blogspot.com/2017/11/la-difference-entre-la-memoire-heap-et.html

Meta Space : pour stocker les méta données. Sa taille peut varier (au contraire de la heap). Remplace la permanent generation depuis Java 8.

Fuite mémoire

Une fuite mémoire est présente quand des objets sont encore présents dans la heap mais ne sont plus utilisés et ne sont pas nettoyés par le GC (conséquence finale : OutOfMemory Error). GC nettoie que les objets qui ne sont plus référencés.

Parmi les causes, on a les champs static, les ressources non fermées (streams, connexions => bien fermer dans les finally ou faire un try with resources). On a aussi une mauvaise implémentation de hashcode/equals qui va empêcher certains caches de fonctionner comme prévu ou bien une mauvaise utilisation des ThreadLocals

https://www.baeldung.com/java-memory-leaks

Equals Hashcode

Hashcode permet d'être plus performant (surtout si on a beaucoup de champs à comparer dans le equals) car comparaison d'entiers plutôt que champs à champs. Si deux objets sont égaux alors ils doivent avoir le même hashcode (réciproque fausse)

https://codegym.cc/fr/groups/posts/fr.264.methodes-equals-et-hashcode-bonnes-pratiques

Execptions

Checked exception : celles qu'on va vérifier avec les try/catch (ex : FileNotFound). Erreurs "attendues". (super classe : Exception) Vérifiées à la compilation.

Unchecked exception : erreurs inatendues, type NullPointer (super classe : RuntimeException)

Multi threading

Le mot clé synchronize a deux rôles :

  • il empêche deux threads de modifier une donnée en même temps
  • il prévient l'ensemble des threads qu'une donnée a été modifiée

=> besoin de synchroniser la lecture ET l'écriture

Le mot clé volatile ne gère pas l'exclusion mutuelle. Il assure qu'un thread va bien lire la version la plus à jour d'une donnée.

i++ n'est pas thread safe car il y a deux opérations en une (une lecture de i et une écriture de i)

Ops

Pour générer des images Docker sans dockerfile : https://github.com/GoogleContainerTools/jib

Clone this wiki locally