Comment résoudre les erreurs « ClassNotFoundException » avec ma fonction Java Lambda ?

Date de la dernière mise à jour : 28/02/2020

Lorsque j'exécute ma fonction AWS Lambda écrite en Java, je reçois des erreurs « ClassNotFoundException » ou « NoSuchMethodError ». Comment les éliminer ?

Brève description

Le runtime Java génère des erreurs « ClassNotFoundException » lorsqu'il essaie de charger une classe par son nom complet (le package avec le nom de classe) et ne parvient pas à localiser la classe. Le runtime déclenche des erreurs « NoSuchMethodError » lorsqu'une version de dépendance référencée est différente de la version package.

Pour plus d'informations sur la structure du package de déploiement de la fonction Java, consultez la rubrique Creating a ZIP Deployment Package for a Java Function (Création d'un package de déploiement ZIP pour une fonction Java).

Solution

Passez en revue la structure et le contenu du package de déploiement de votre fonction Lambda Java pour déterminer la cause de l'erreur. La bonne pratique consiste à utiliser zipinfo pour afficher le fichier Java de sortie de votre système de génération. Vous pouvez également télécharger le package en procédant de l'une des manières suivantes :

  • Exécutez la commande Lambda get-function à partir de l'interface de ligne de commande AWS (AWS CLI). La sortie de la commande affiche une URL pré-signée que vous pouvez utiliser pour télécharger le fichier. Pour plus d'informations, consultez la rubrique Récupérer une fonction Lambda.
    Remarque : si vous utilisez cette option, dans la sortie, vérifiez également la configuration de la valeur du gestionnaire de votre fonction. Vous aurez besoin de cette valeur pour l'étape suivante.
  • Sur la page Functions (Fonctions) de la console Lambda, choisissez votre fonction. Choisissez Actions, puis Export function (Exporter fonction). Dans la boîte de dialogue Export your function (Exporter votre fonction), choisissez Download deployment package (Télécharger le package de déploiement).

Recherchez l'un des problèmes suivants. Une fois que vous avez identifié et résolu les problèmes, regroupez et chargez manuellement votre fonction Lambda. Ensuite, vérifiez si vous obtenez toujours l'erreur.

Confirmer le nom de méthode du gestionnaire de fonction

Vérifiez le nom du gestionnaire de votre fonction Lambda en procédant de l'une des manières suivantes :

Pour plus d'informations, consultez la rubrique Gestionnaire de fonctions AWS Lambda dans Java.

Afficher la structure du package de déploiement

Exécutez la commande suivante pour afficher la structure de fichier du package de déploiement de votre fonction Lambda :

Remarque : cette commande est valide uniquement pour les systèmes Linux/Unix/macOS. Remplacez my-deployment-package.zip par le nom de fichier de votre package de déploiement.

$ zipinfo my-deployment-package.zip

Vérifier la présence de problèmes lors de l'utilisation d'un pipeline CI/CD

Si vous utilisez un pipeline d'intégration et de livraison continues (CI/CD) pour empaqueter et déployer votre fonction, vérifiez les points suivants :

  • Toutes les dépendances requises ont été regroupées lors de l'empaquetage de la fonction.
  • Toutes les versions de dépendances référencées sont correctes.
  • Si vous utilisez une source compartiment Amazon Simple Storage Service (Amazon S3) et que la gestion des versions du compartiment est activée, l'URL du compartiment S3 existe et pointe vers la dernière version d'un fichier.
  • Les modifications de code ont été déployées avant le déploiement du changement de configuration du gestionnaire. (Lambda ne dispose pas d'un mécanisme de mise à jour du code et ne peut être configuré en une modification atomique.)

Vérifier les problèmes liés au fichier de classe

Vérifiez ce qui suit pour la classe nommée dans l'erreur « ClassNotFoundException » :

  • Elle est incluse dans le package de déploiement. Si vous ne trouvez pas la classe, elle n'a peut-être pas été regroupée lorsque vous avez créé le package de déploiement.
  • Son nom de classe groupée est identique à la valeur renseignée pour le gestionnaire de votre fonction. Par exemple, si la valeur du gestionnaire de votre fonction est « com.amazonaws.lambda.demo .LambdaFunctionHandler », Lambda attend un nom de classe « LambdaFunctionHandler.class » dans le répertoire de fonctions « /com/amazonaws/demo/ ». Pour plus d'informations, consultez la rubrique Gestionnaire de fonctions AWS Lambda dans Java.
  • Elle se trouve dans /lib ou dans le répertoire racine.
  • Son emplacement est spécifié dans une variable d'environnement Java CLASSPATH.
  • Si elle est référencée en tant que couche Lambda, son contenu n'a pas été extrait dans un répertoire autre que java/lib.
  • Il s'agit de la même version que la classe fournie avec votre fonction. Si ce n'est pas le cas, vérifiez si votre ordinateur local avait une version différente de celle que vous avez empaquetée.

Pour plus d'informations sur l'empaquetage des fonctions Java, consultez la rubrique Package de déploiement AWS Lambda dans Java.

Vérifier les problèmes liés au fichier JAR

Vérifiez si votre fonction s'exécute comme prévu sur un ordinateur local ou à partir d'une application AWS Serverless Application Model (AWS SAM). Si votre fonction échoue uniquement lorsqu'elle est appelée à partir de Lambda, il peut y avoir des problèmes avec les dépendances référencées (fichiers JAR).

Conseil : envisagez d'utiliser l'environnement de développement intégré (IDE) Eclipse pour créer vos fonctions Lambda Java. La création d'un projet à l'aide de plug-ins disponibles dans Eclipse configure automatiquement votre projet pour une compilation appropriée. Pour plus d'informations, consultez la rubrique Utilisation de Lambda avec AWS Toolkit for Eclipse.

Vérifiez ce qui suit pour les fichiers JAR situés dans un répertoire local et spécifiés dans une variable d'environnement Java CLASSPATH :

  • Les fichiers sont inclus dans le package de déploiement de votre fonction. Si vous ne trouvez pas de fichiers JAR référencés, ils n'ont peut-être pas été regroupés lorsque vous avez créé le package de déploiement.
  • Les versions de fichier sont les mêmes que les fichiers du package de déploiement.

Si des fichiers sont manquants ou si leurs versions sont incorrectes, copiez toutes les dépendances (fichiers JAR) dans /lib ou dans le répertoire racine. Veillez à référencer les versions correctes. Chargez ensuite le contenu compressé.

Remarque : si vous utilisez un outil de génération tel qu'Apache Maven ou Gradle, veillez à utiliser tous les plug-ins nécessaires (par exemple, le plug-in Apache Maven Shade) pour regrouper toutes les dépendances requises lors de la création de l'artefact de déploiement.

Pour plus d'informations sur l'empaquetage des fonctions Java, consultez la rubrique Package de déploiement AWS Lambda dans Java.

Vérifier les problèmes d'autorisations

Lambda nécessite que les fichiers de package zip disposent d'autorisations de lecture globales. Pour plus d'informations, consultez la rubrique Comment résoudre les erreurs « autorisation refusée » ou « impossible d'importer le module» dans Lambda lors du téléchargement d'un package de déploiement ?