Spring重试模板阻止了我的响应队列

问题描述 投票:0回答:1

我有一个应用程序,我在该应用程序中发送队列消息以获取我的用户对象的referenceNumber。然后等待队列响应,然后再响应REST调用。但是,我必须等待配置的时间才能返回队列响应。

UserManagerImpl

// REST CALL to persist
public User Persist(User user) {
...
...
 // Building the message for sending to QUEUE
 UserEnvelopeV1_0 userEnvelope =buildUserEnvelope(user);
// This is the place i send the queue message
userQueueClient.send(userEnvelope);
// Update Request time
updateRequestDetails(user.getUserId);
// This is the call i am going retry
boolean userValid = userRetryTemplate.doUserReferenceRetry(userId);
if (!userValid ) {
                  //remove User Object
                  throw Exception
                }
...
}

// update the request time for reference Number
private void updateRequestDetails(String userId) {
 User user = userRepository.findById(userId);
        if (user != null) {
            user.setRefRequestDateItem(DateHelper.createXMLGregorianCalendar());
            userRepository.saveAndFlush(bankAccount);
        }

public void updateReference(String userId, String referenceNumber) {

        User user = userRepository.findById(userId);
        if (user != null) {
            user.setReference(referenceNumber);
            user.setResponseDate(DateHelper.createXMLGregorianCalendar());
            userRepository.saveAndFlush(bankAccount);
        }
    }

UserQueueClient:

@Component
public class UserQueueClient {



    @JmsListener(id = "#{T(java.util.UUID).nameUUIDFromBytes('${in.res}",
            destination = "${in.res}", containerFactory = "containerFactory")
    public void receive(Message message, UserEnvelopeV1_0 envelope) throws{


        try {
            String userId = envelope.getHeader().getMessageIdentification().getUserId();
 ApplicationInformationStructure applicationInformation = envelope.getBody().getApplicationInformation();

if(CollectionUtils.isNotEmpty(applicationInformation.getApplicationInformationResult())) {
          String referenceNumber = applicationInformation.getApplicationInformationResult().getRefNumber();      

                userManager.updateReference(userId, referenceNumber);
            }

        } catch (Exception e) {
            //
        }
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void send(UserEnvelopeV1_0 sarsSoapEnvelope) throws JMSException {


        envelope.setHeader();

        Message message = sendToQueue(envelope, requestQueue, responseQueue,
                userId);

        applicationEventPublisher.publishEvent(new MessageLogEvent("USER_GET_REF_NUMBER", message, MessageType.XML,
                requestQueue, MessageDirection.SEND, true, false, new Date(), userId));

    }
}

UserRetryTemplate



@Component
public class UserRetryTemplate {


    @Value("${retry.max.attempts:5}")
    private int maxAttempts;

    @Value("${response.waiting.time.in.seconds:60}")
    private long maxDelay;

    @Autowired
    private UserRepository userRepository;

    private static final long INITIAL_INTERVAL = 2000L;

    public RetryTemplate retryTemplate() {

        // Max timeout in milliseconds
        long maxTimeout = maxDelay*1000;

        //double multiplier = (maxTimeout - INITIAL_INTERVAL)/((maxAttempts-2)*6000);

        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(maxAttempts);


        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        backOffPolicy.setBackOffPeriod(maxTimeout/(maxAttempts-1));

        RetryTemplate template = new RetryTemplate();
        template.setRetryPolicy(retryPolicy);
        template.setBackOffPolicy(backOffPolicy);
        return template;
    }

    public boolean doUserReferenceRetry(String userId) {
        boolean isUserReferenceValid = true;
        try {
            boolean isValidBankAccount = retryTemplate().execute(context -> {
                logger.info("Attempted {} times", context.getRetryCount());
                User user = userRepository.findById(userId);
                logger.info("User Retry :" + user);

                if (bankAccount.getRefResponseDateItem() == null || bankAccount.getReferenceNumber == null) {
                    logger.info("response not yet received");
                    throw new IllegalStateException("User Response not yet received");
                }
                if (bankAccount.getReferenceNumber != null)) {
                    return true;
                }
                throw new IllegalStateException("Response not yet received");
            });
            return isUserReferenceValid ;
        } catch (IllegalArgumentException e) {

        }
        return true;
    }

}

因此,我实现了一种逻辑,在该逻辑中,我将发送队列消息并进行Spring重试(针对配置的时间),以检查数据库中的referenceNumber是否已更新。另外,当队列响应返回时,我将使用referenceNumber更新数据库。

但是,当我实现上述逻辑时,spring重试将一直重试直到配置的时间,但是我的Spring应用程序未处理任何响应队列。Spring应用程序是否可以并行运行两个进程。

问题是,如果我删除弹簧重试机制,响应队列正在处理我的响应并使用参考号更新用户记录。

但是当我添加重试逻辑时,响应队列不再处理我的队列。

java spring spring-jms spring-retry
1个回答
0
投票

我发现下划线令人困惑。

“,我将在其中发送队列消息并进行Spring重试(配置的时间)以检查数据库中的referenceNumber是否已更新。此外,当队列响应返回时,我将使用referenceNumber。“

在一行中,您说您正在等待参考号更新,而在另一行中,您说您正在更新数据库。这里的生产者是谁?有两个不同的线程吗?生产者和消费者在这种情况下就是你。

如果要在配置的时间内阻止当前线程您可以考虑使用poll(长超时,TimeUnit单位)方法来阻止队列]

poll(long timeout, TimeUnit unit) – retrieves and removes the head of the queue, waiting up to the specified wait time if necessary for an element to become available. Returns null after a timeout

请编辑问题并提供足够的细节。

© www.soinside.com 2019 - 2024. All rights reserved.