7
votes

Envoi de courrier électronique avec le printemps dans un nouveau problème de thread

Une des fonctionnalités de l'application que je développe est qu'un e-mail est envoyé à chaque fois que l'utilisateur obtient sa facture inscrite dans notre système. Envoi d'un courrier électronique de Java App faciles surtout si vous utilisez le cadre de printemps. J'utilise JavamailRenderImpl et SimpleMailMessage à partir du cadre de printemps et ça marche bien.

Mais je dois envoyer un courrier électronique dans un nouveau thread afin que la communication avec SMTP Server ne ralentit pas le reste des processus d'applications. Le problème est que lorsque j'appelle xxx

méthode à partir d'un nouveau thread, le message électronique n'est pas envoyé, par opposition lors de l'envoi d'un même thread. J'ai essayé avec @Async Annotation, Executant Spring et Uni Vieux Java.Lang.thread Mais cela ne fonctionne pas.

peut être envoyé de manière asynchrone à Java avec le printemps? Quelqu'un a-t-il un problème similaire avec cela? Je peux poster des échantillons de code si nécessaire.

TNX


6 commentaires

Comment savez-vous que ce n'est pas envoyé? Que font les journaux des classes de printemps?


"Cela ne fonctionne pas" n'est jamais une phrase utile pour. Dites-nous ce que fait se produit, pas ce qui ne le fait pas.


Tout va bien, pas d'exception, aucune erreur n'a été signalée, mais l'email n'arrive pas. J'utilise Gmail comme serveur SMTP pour tester.


Le problème est-il que le courrier envoyé la routine n'est pas appelé (non asncys), ou est le problème que le courrier n'arrive pas?


Le problème est que ce courrier n'arrive pas. Même routine pour l'envoi de Works de messagerie et de courrier électronique est envoyée et reçue avec succès, mais lorsque je mets @Async Annotation ou l'appelez à partir d'un nouveau thread, ce n'est pas une exception ni des erreurs d'aucune sorte


@Marko Avez-vous réussi à savoir quel était le problème? Je suis confronté au même problème


4 Réponses :


3
votes

Ça devrait fonctionner.

Vous devez dire au printemps qu'il devrait faire attention à votre @Async Annotation par: xxx

et Il y a quelques limitations que vous devez respecter:

  • La méthode annotée doit appartenir à un haricot de ressort
  • L'invocation de la méthode annotée doit être exécutée à partir d'un grain de ressort différent (si vous utilisez un ressort standard AOP).

1 commentaires

J'ai mis l'annotation et l'appelant et le haricot contenant des appels d'envoi sont des haricots de printemps.



3
votes

1) Ajouter un espace de noms de tâches dans le contexte de printemps. Le XSD suivant est pour la libération de printemps 3.0. xmlns: tâche = "http://www.springframework.org/schema/task"

http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-tak -3.0.xsd

2) Déclarez l'exécuteur dans votre fichier de contexte de printemps. xxx

3 3) Configurez ceci à la tâche de printemps xxx

Celles-ci sont toutes la configuration dont vous avez besoin dans le fichier contextuel à ressort.

La méthode dont vous avez besoin pour l'annoter asynchrone avec @Async Annotaion.

Maintenant, toutes les méthodes annotées avec @Async seront traitées comme exécutant de la tâche de printemps asynchrone.


1 commentaires

Cela nécessite alors CGLIB2 sur CLASSPATH, lorsque cela est donné, CGLIB se plaint que certaines de mes classes de contrôleur n'offrent pas de constructeurs de No-Arg ... Arrh! mais je veux une injection de constructeur de dépendances



0
votes

L'un des problèmes connus d'exécution du code dans un fil asynchrone est que Les exceptions lancées par ce code sont perdu , sauf si Vous fournissez un gestionnaire spécifique pour les attraper . L'effet que vous voyez (nommément, la méthode @Async échouant à la fois d'exécuter correctement et de montrer un indice pour cette défaillance sous la forme d'un journal ou d'une stacktrace de quelque sorte) est typiquement produit par une telle exception , en effet jeté mais avalé par le fil asynchrone.

L'une des nombreuses raisons possibles pour lesquelles votre @Async fonctionne lorsque synchrone est que vous effectuez une opération de base de données à partir de la méthode. Cela fonctionne lorsque vous l'appelez probablement à partir d'une méthode @Transactional d'un autre @service , donc pour ce thread a session ou < code> EntityManager est trouvé; mais cela ne fonctionne pas lorsque vous êtes asynchrone, car dans ce cas, vous êtes sur un nouveau fil, et si la méthode @Async n'est pas @Transactional il n'y a pas de Session ou EntityManager qui pourrait effectuer l'opération.

TL; DR Fournissez un gestionnaire d'exception pour attraper des exceptions qui seraient avalées par le fil asynchrone autrement, ou pour le débogage, utilisez un gros essayer / catch pour Le corps de la méthode @ASYNC . Vous verrez probablement une exception à faire de l'exception, alors vous devrez prendre les mesures appropriées pour l'éviter.


5 commentaires

J'ai un problème similaire. Je me suis creusé dans le message d'exception. IT SAIS: "Impossible de relais un destinataire dans le domaine non accepté". Lors de l'envoi de courrier électronique synchrone, je ne reçois pas un tel problème et que l'e-mail est envoyé correctement. Le moment où je passe dans une approche asynchrone, il jette une telle erreur


@Przemek je ne pense pas que l'asynchronicité soit à blâmer en soi pour cette erreur. Est-il possible que, en allant de manière asynchrone, certaines données par ex. est correctement récupéré d'une base de données lorsque l'opération est synchrone est autrement manquante?


J'ai une méthode transactionnelle qui me permet d'obtenir les adresses électroniques de la DB, puis j'utilise les adresses de la méthode qui envoie des courriels. Dans la version synchrone, cela fonctionne, dès que je passe à l'asynchrone, je reçois une erreur telle que mentionnée précédemment. Ce nouveau thread doit avoir accès aux propriétés de messagerie fournies dans ma candidature.Propertoires, non?


@Przemek, vous devriez vérifier (par la journalisation ou la bonne méthode Old System.Out.PrintLN) si toutes les données dont vous avez besoin sont vraiment là.


Ok, j'ai compris ce que le problème était, bien que ce soit ma pure devinette. S'avère que le problème était lié aux délais de connexion SMTP. J'ai ajouté ces valeurs: printemps.mail.properties.mail.smtp.connectiontimeout = 5000 Spring.mail.mail.mail.properties.mail.smtp.timeout = 3000 Et maintenant, il fonctionne à la fois synchrone et asynchrone



0
votes

Vous devez activer la fonctionnalité au printemps:

@EnableAsync
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }
}


0 commentaires