0

i have a requirement where i need to send a email but if the email server is down or any error occurs while sending a email that need to be retry for a specific number of times

below is my bean properties

@Bean(destroyMethod = "")
    public JndiTemplate jndiTemplate() {
        Properties environment = new Properties();
        environment.put(Context.INITIAL_CONTEXT_FACTORY, env.getProperty("XXXXXX"));
        environment.put(Context.PROVIDER_URL, env.getProperty("XXXXXX"));
        JndiTemplate jndiTemplate = new JndiTemplate();
        jndiTemplate.setEnvironment(environment);
        return jndiTemplate;
    }

    @Bean(destroyMethod = "")
    public JndiObjectFactoryBean jmsConnFactory() {
        JndiObjectFactoryBean jmsConnFactory = new JndiObjectFactoryBean();
        jmsConnFactory.setJndiTemplate(jndiTemplate());
        jmsConnFactory.setJndiName(env.getProperty("XXXXX"));
        return jmsConnFactory;
    }

    @Bean(destroyMethod = "")
    public JndiObjectFactoryBean jmsDestanation() {
        JndiObjectFactoryBean destination = new JndiObjectFactoryBean();
        destination.setJndiTemplate(jndiTemplate());
        destination.setJndiName(env.getProperty("XXXXXX"));
        return destination;
    }

    @Bean
    public JmsTemplate jmsTemplate() {
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setDefaultDestination(jmsDestanation());
        jmsTemplate.setConnectionFactory(jmsConnFactory());
        return jmsTemplate;
    }

    @Bean
    public JmsReceiver jmsReciver() {
        return new JmsReceiver();
    }

    @Bean
    public JmsExceptionListener jmsExceptionListener(){
        return new JmsExceptionListener();
    }

    @Bean
    public JmsErrorHandleListener jmsErrorHandleListener(){
        return new JmsErrorHandleListener();
    }   

    @Bean
    public DefaultMessageListenerContainer jmsQueueListner() {
        DefaultMessageListenerContainer listner = new DefaultMessageListenerContainer();
        listner.setDestination(jmsDestanation());
        listner.setConnectionFactory(jmsConnFactory());
        listner.setMessageListener(jmsReciver());
        listner.setExceptionListener(jmsExceptionListener());
        listner.setErrorHandler(jmsErrorHandleListener());  
        return listner;
    }

and below is my Listener class and error class

public class JmsReceiver implements MessageListener {

    @Autowired
    JavaMailSender jMailsender;

    @Override
    public void onMessage(Message message) {
        TextMessage text = (TextMessage) message;
        ObjectMapper objectMapper = new ObjectMapper();
        MimeMessage mimeMessage = jMailsender.createMimeMessage();  

        try {
            JmsMessage inMessage = objectMapper.readValue(text.getText(), JmsMessage.class);    
            //this is failing and go to the JmsErrorHandleListener
            jMailsender.send(mimeMessage);

        } catch (JMSException | IOException | MessagingException ex) {
            logger.error("Exception on reading message ",ex);
        }
    }
}

public class JmsErrorHandleListener implements ErrorHandler {

    @Override
    public void handleError(Throwable t) {
        /// not sure how to retry from hear becoz the message was allready read
        /// some how i need to inform the weblogic this message was not read yet
    }
}

when the message arrives to the onMessage it will throw an error then executes the JmsErrorHandleListener but since the message is already read im not sure how to call the send method again and again

user2567005
  • 271
  • 1
  • 13
  • 27
  • 1
    Which acknowledgement mode are you using? I believe if you use "CLIENT_ACKNOWLEDGE", then the message should be redelivered until you call the acknowledge method of Message class or the maximum number of redeliveries is reached. So, only acknowledge the message if your processing is successful. Check the acknowledgement modes in below link for further details: https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.dev.doc/q032230_.htm – Rahul Feb 14 '18 at 08:43
  • since i don't use any mode, i think think it's the default mode, which is AUTO – user2567005 Feb 14 '18 at 10:57

1 Answers1

0

try with below config, spring DMLC manage Exception's to retry MessageListener execution, if jMailsender.send(mimeMessage); fails JmsReceiver.onMessage will be retried 5s later indefintely, see DMLC backoff property

@Bean
public org.springframework.jms.listener.adapter.MessageListenerAdapter jmsReciver() {
    return new org.springframework.jms.listener.adapter.MessageListenerAdapter(receiver());
}

@Bean
public JmsReceiver receiver() {
    return new JmsReceiver();
}


public class JmsReceiver {

    @Autowired
    JavaMailSender jMailsender;

    @Override
    public void onMessage(Message message) throws JMSException {
        TextMessage text = (TextMessage) message;
        ObjectMapper objectMapper = new ObjectMapper();
        MimeMessage mimeMessage = jMailsender.createMimeMessage();  

        try {
            JmsMessage inMessage = objectMapper.readValue(text.getText(), JmsMessage.class);    
            //this is failing and go to the JmsErrorHandleListener
            jMailsender.send(mimeMessage);

        } catch (Throwable ex) {
            logger.error("Exception on reading message ",ex);
            throw new JMSException(ex.getMessage());
        }
    }
}
Hassen Bennour
  • 3,885
  • 2
  • 12
  • 20