Étiquette : Java

[Java] Trucs et astuces pour Websphere et Eclipse

[Java] Trucs et astuces pour Websphere et Eclipse

Si vous utilisez l’IDE Eclipse au quotidien et le serveur IBM Websphere dans sa version 9 ou plus, voici quelques petits trucs et astuces pour vous aider dans vos tâches de développement.

Trucs et astuces pour Websphere et Eclipse

Désactiver l’auto-publish

Lorsqu’on se trouve dans Eclipse, et qu’on effectue un build du projet, l’action de publication – ou publish – du projet est réalisée automatiquement et ce même en mode debug du serveur de test. Cependant on peut modifier ce comportement grâce à l’astuce suivante.

  • Rendez-vous dans l’onglet Servers.
  • Double-cliquez sur le serveur WebSphere Application Server vX.Y.
  • Déroulez la catégorie Publishing.
  • Cochez l’option Never publish automatically.
  • Dans la barre d’outils de l’IDE, cliquez sur le bouton Enregistrer.

Lancer en mode debug

Ce mode du serveur est particulièrement utile afin que les modifications des actions et JSP soient immédiatement prises en compte. Et ce sans effectuer l’action de publication.

  • Rendez-vous dans l’onglet Servers.
  • Effectuez un clic droit sur votre serveur WebSphere.
  • Choisir Debug / Restart in Debug.

Publication d’applications en erreur

Par défaut il est impossible de publier une application avec du code en erreur.

Pour résoudre cela:

  • Dans Eclipse, allez dans le menu Window > Preferences.
  • Recherchez le bon paramètre avec le mot clé « Websphere ».
  • Déroulez la catégorie Server, sélectionner Websphere Application Server.
  • Cochez « Allow applications containing errors to be published on a server« .
  • Sauvegardez.

Supprimer la compilation des JSP

Quels sont les symptômes ? Par exemple, si vous renommez une classe de Tag Java, la JSP référencera l’ancien nom même après un publish. Ou encore, certains éléments de la page (ex : une variable statique) ont une valeur différente de celle définie dans le code.

Dès lors, si vous avez vidé le cache du navigateur et que cela persiste, c’est peut-être dû au cache de compilation des JSP géré par Websphere.

Sur votre PC ouvrez le répertoire des fichiers temporaires de votre serveur.

\WebSphere\AppServer_v9.0\profiles\AppSrv01\temp\TestNode01\server1

Supprimez le contenu du dossier. Lors du prochain rafraichissement des pages concernées par le problème, vous devriez obtenir le résultat escompté.

Supprimer les fichiers temporaires

De manière générale, lorsqu’on rencontre un problème avec Websphere, on peut nettoyer les fichiers temporaires générés dans les dossiers suivants. Il est préférable d’arrêter le serveur pour effectuer l’opération.

\WebSphere\AppServer_v9.0\profiles\AppSrv01\temp\TestNode01\server1
\WebSphere\AppServer_v9.0\profiles\AppSrv01\temp\wscache
\WebSphere\AppServer_v9.0\profiles\AppSrv01\wstemp


Ressources

[Sécurité] Découverte d’une faille de sécurité critique dans Spring

[Sécurité] Découverte d’une faille de sécurité critique dans Spring

Comme nous le rapporte le magazine Programmez! VMWare signale la présence d’une faille de sécurité critique dans son produit Spring, permettant l’exécution de code à distance (RCE). Cela touche les versions de Spring Framework 5.2.0 à 5.2.19 et 5.3.0 à 5.3.17, ainsi que des versions plus anciennes. Reprise sous l’identifiant CVE-2022-22965 et baptisée Spring4Shell, cette faille ne peut être exploitée que si certaines conditions sont réunies.

Faille de sécurité Spring

En effet, sont vulnérables des applications Spring MVC ou WebFlux, tournant sur une JDK 9 (ou supérieur) sur un serveur Tomcat, et qui ne sont pas déployées en tant qu’exécutables Spring Boot (mais bien sous la forme d’archives WAR). Dans sa note, VMWare met toutefois en garde que la faille pourrait être exploitée par d’autres moyens.

VMWare recommande de mettre à jour au plus vite vos applications avec une version plus récente de Spring Framework. S’il n’est pas possible pour vous de changer de version, des solutions de contournement sont proposées dans une publication sur le blog de Spring.

Sources

[Java] Mémo – Trucs et astuces impliquant l’API Stream

[Java] Mémo – Trucs et astuces impliquant l’API Stream

Java propose l’API Stream, qui permet de manipuler et effectuer des opérations sur un ensemble de données, telles qu’une collection, un tableau ou même un flux I/O. Elle offre diverses possibilités : tri, parcours de collections, extraction d’éléments à l’aide de filtres, etc.

Dans cet article nous allons voir comment effectuer un tri basique pour retourner une nouvelle liste mais également comment retourner une liste d’objets d’un type spécifique.

Trier une liste

On suppose que l’opération sera effectuée sur une liste d’objets de la classe Client. Cette dernière définit plusieurs membres dont un numéro de client (numClient) et son getter. Nous souhaitons récupérer une nouvelle liste de noms.

listeClients.stream()
	.sorted(Comparator.comparing(Client::getNumClient))
	.map(lo_c -> lo_c.getNomClient())
	.collect(Collectors.toList());

Dans cet exemple nous avons effectué plusieurs opérations sur le stream :

  • Une opération intermédiaire de tri, grâce à la méthode sorted() qui reçoit en paramètre un Comparator.
  • Une seconde opération intermédiaire qui permet de définir ce que l’on souhaite récupérer, en l’occurrence le nom de la personne.
  • Une troisième opération, finale cette fois, qui consiste en une réduction: on demande à ce que le résultat soit sous forme de liste.

Notez que si vous manipulez une List vous pouvez la trier directement à l’aide de la méthode sort(). La méthode effectue l’opération sur la liste existante sans en créer une copie de celle-ci.

Exemple:

listeClients.sort(Comparator.comparing(Client::getNumClient));

Retourner une liste d’un type spécifique

Comme on l’a vu ci-dessus, à l’aide de la méthode map(), on a obtenu une liste de chaines de caractères. Voyons comment aller plus loin pour retourner une liste d’un type spécifique. Toujours sur base d’un client, nous avons une classe nommée ClientDTO qui sera une version réduite. Elle contiendra uniquement le numéro de client et son nom, ainsi qu’un constructeur prenant en paramètre ces deux champs.

listeClients.stream()
	.sorted(Comparator.comparing(Client::getNumClient))
	.collect(Collectors.mapping(lo_c -> {
		return new ClientDTO(
			lo_c.getNumClient(), lo_c.getNomClient()
		);
	}, Collectors.toList()));

Cette fois on effectue un mappage à l’aide de Collectors.mapping(): la fonction en paramètre retourne une instance de ClientDTO avec les champs de notre classe Client. On demande ensuite à ce que le résultat final soit retourné sous forme de liste, comme dans l’exemple ci-dessus.

Bien sûr ce sont deux exemples parmi tant d’autres, l’API offrant énormément de possibilités. Et même si cela a été introduit dans Java 8 on n’a pas toujours la possibilité ou le temps d’en explorer les différentes méthodes. Voici quelques liens qui pourraient vous intéresser pour creuser le sujet:

Bon développement !

[Java] Filtre sur liste avec les streams

[Java] Filtre sur liste avec les streams

L’une des grosses améliorations de Java 8, c’est ce qu’on appelle les streams. C’est un nouveau pattern de manipulation de données et cela permet de se passer notamment des itérateurs que l’on connait. On peut les utiliser sur des collections ou même des tableaux.

On prend la classe suivante comme exemple :

public class MyObject
{
 private String sId;
 private String sName;
 
 // ...
}

Une méthode nous retourne alors une liste qui reprend des objets caractérisés par leur nom et un identifiant. On voudrait filtrer la liste pour ne récupérer que les objets nommés « chair » par exemple.

Stream<MyObject> lo_s = lo_listObj.stream().filter(
 myObj -> myObj.getName().equals("chair")
);

Le paramètre de la méthode filter() est un prédicat (type Predicate). Le code ci-dessus renvoie un stream que l’on peut ensuite manipuler pour retourner une collection ou bien un seul objet. Par exemple on pourrait utiliser la méthode collect() pour renvoyer une nouvelle liste.

List<Myobject> lo_list = lo_s.collect(Collectors.toList());

On peut aussi retourner le premier objet qui correspond au filtre, avec findFirst(). Cela retourne un objet de type Optional.

Optional<MyObject> lo_opt = lo_s.findFirst();

Plusieurs opérations sont possibles sur cet objet. On peut savoir s’il y a bien un résultat avec la méthode isPresent(), ou bien retourner directement le résultat ou une autre valeur si aucun objet n’avait été trouvé lors du filtre.

MyObject lo_result = lo_opt.orElse(lo_defaultObject);

La méthode orElse() renvoie la valeur qui avait été trouvée et si elle n’est pas présente, alors elle renvoie un autre objet du même type.

if (lo_opt.isPresent())
{
 MyObject lo_result = lo_opt.get();
}

L’exemple ci-dessus montre comment récupérer l’objet uniquement s’il est présent et pour également éviter l’exception NoSuchElementException. Cela peut être un raccourci à la méthode orElse(), tout dépend de quoi on a besoin en retour et ce qu’on va en faire.

[Java] Mémo – Validation de beans

[Java] Mémo – Validation de beans

En Java, il est possible d’utiliser la validation de beans pour permettre d’en valider son contenu, donc les différents membres de la classe. Par exemple, si on a une classe « Personne« , qui contient un nom et un prénom, on voudrait valider que ceux-ci ne dépassent pas une certaine taille ou même qu’ils respectent une expression régulière. Plutôt que de créer des méthodes visant à vérifier chaque élément un à un, on va se baser sur des annotations.

Prenons la classe suivante comme référence pour ce 1er exemple :

public class Person
{
    @Size(min = 1, max = 5, message = "cod: btw. 1 and 5")
    private String      cod;
 
    @Size(max = 60, message = "firstName: Length max 60")
    private String      firstName;

    @NotNull(message = "birthdate: mandatory")
    private LocalDate   birthdate;
 
    // ...
}

On utilise l’annotation Size pour définir la taille maximum qu’une chaine peut avoir. Si on ne spécifie pas de minimum, cela veut dire que la chaine peut être vide. A chaque fois on spécifie le paramètre « message » pour indiquer quel sera le message retourné lors de la validation.

Pour récupérer les erreurs sous forme de chaine :

Person lo_p = new Person();
Set<ConstraintViolation<T>> lo_violations = 
 Validation.buildDefaultValidatorFactory()
  .getValidator()
  .validate(lo_p);
for (ConstraintViolation<T> lo_violation : lo_violations)
{
    System.out.println(lo_violation.getMessage());
}

Ce code affiche les messages en fonction des champs qui sont en erreur par rapport à l’objet qu’on donne en paramètre de la méthode validate().

Si notre classe contient une liste d’objets que l’on veut aussi valider, ou un objet d’une autre classe, il faut rajouter une annotation Valid pour qu’il soit pris en compte lors de la validation.

public class PremObj
{
    @Size(min = 1, max = 20, message = "id: btw. 1 and 20")
    private String                  id;
 
    @Valid
    @NotNull(message = "liste_sousobj: Mandatory")
    private List<UnSousObj>  liste_sousobj;
 
    // ...
}

Chaque objet de la liste sera donc analysé. C’est aussi valable si on avait mis un seul objet de type « UnSousObj« . La classe que l’on référence doit évidemment posséder diverses annotations de validation.

Un champ peut également être validé sur base de valeurs d’une énumération. On peut ainsi utiliser l’annotation Enum (sur une variable de type String). Le paramètre obligatoire « enumClass » permet de spécifier la classe qui servira à la validation.

D’autres annotations utiles :

  • Pattern : sur une chaine, permet de faire en sorte qu’elle respecte une expression régulière.
  • Min : indique la valeur minimale d’un nombre.
  • Max : indique la valeur maximale d’un nombre.

Liens

Liste des annotations disponibles