使用@Async会抛出org.springframework.aop.AopInvocationException

时间:2017-07-03 14:48:29

标签: java spring asynchronous

我有一种方法可以在DB中一个接一个地保存多个表中的数据。该方法使用@Async进行注释。该方法依次调用另一个DAO类,该类在DB中实际存储数据。

问题是数据确实成功存储在数据库中的所有表中,但我在服务器日志中看到以下异常。

例外:

org.springframework.aop.AopInvocationException: Null return value from advice does not match primitive return type for: public long com.ebayenterprise.publicapi.events.service.EventLogService.saveEventData(int,java.lang.String,java.lang.String,java.sql.Timestamp,java.sql.Timestamp,java.lang.String)
        at org.springframework.aop.framework.CglibAopProxy.processReturnType(CglibAopProxy.java:351)
        at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:83)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:646)
        at com.ebayenterprise.publicapi.events.service.EventLogService$$EnhancerBySpringCGLIB$$b06a3b16.saveEventData(<generated>)
        at com.ebayenterprise.publicapi.events.PublicApiMessageHandler.logEventData(PublicApiMessageHandler.java:91)
        at com.ebayenterprise.publicapi.events.PublicApiMessageHandler.handleMessage(PublicApiMessageHandler.java:80)
        at com.ebayenterprise.publicapi.events.jms.MessageHandler.onMessage(MessageHandler.java:30)
        at com.ebayenterprise.publicapi.events.jms.MessageListenerContainer.onMessage(MessageListenerContainer.java:54)
        at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:562)
        at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:500)
        at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:468)
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1102)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1094)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:991)
        at java.lang.Thread.run(Thread.java:745)

的applicationContext.xml

<task:executor id="myexecutor" pool-size="10"/>
<task:annotation-driven executor="myexecutor"/>

PublicApiMessageHandler.java

  if (eventDBLoggingEnabled) {
                long eventId = 0L;
                try {
                    logger.info("Saving event data in DB now........");
                    eventId =  eventLogService.saveEventData(routeId, incomingEventMessage, outgoingEventMessage, 
            incomingEventTimestamp, outgoingEventTimestamp, userId);
                } catch (Exception e) {
                    logger.error("Some error occured while storing data in event log tables for eventId: "
                            + eventId + " - " + e.getMessage(), e);
                }
            }

EventLogService.java

   @Async
public long saveEventData(int routeId, String incomingEventMessage, String outgoingEventMessage,
        Timestamp incomingEventTimestamp, Timestamp outgoingEventTimestamp, String userId) throws SQLException {
    String orderId = GenericUtil.extractOrderId(incomingEventMessage);
    EventType eventType = buildEventTypeData(incomingEventMessage);
    EventLog eventLog = eventBuilderService.buildEvent(eventType, routeId, orderId,
            incomingEventMessage, outgoingEventMessage, incomingEventTimestamp, outgoingEventTimestamp);
    long eventId = eventLogDao.save(eventLog, userId);
    if (eventId == 0L) {
        throw new RuntimeException(ERROR_MSG);
    }
    return eventId;
}

EventLogDao.java

@Repository
public class EventLogDao extends BaseEventLogDao {

    public EventLogDao(DataSource dataSource, PlatformTransactionManager transactionManager) {
        super(dataSource, transactionManager);
    }

    public long save(EventLog eventLog, String userId) {
        TransactionDefinition txDef = new DefaultTransactionDefinition();
        TransactionStatus txStatus = transactionManager.getTransaction(txDef);
        long eventId = 0L;
        try {
            eventId = getNextEventIdSequence();
            saveEventLogData(eventId, eventLog);
            saveEventLogMessageData(eventId, eventLog.getEventLogMessage());
            saveEventLogAuditData(eventId, userId, eventLog.getOutgoingEventTimestamp());
            transactionManager.commit(txStatus);
            return eventId;
        } catch (TransactionException ex) {
            transactionManager.rollback(txStatus);
            throw new RuntimeException("Error occurred during tx management in event log tables...", ex);
        }
    }

}

BaseEventLogDao.java

public abstract class BaseEventLogDao {

    protected final JdbcTemplate jdbcTemplate;
    protected final PlatformTransactionManager transactionManager;

    public BaseEventLogDao(DataSource dataSource, PlatformTransactionManager transactionManager) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.transactionManager = transactionManager;
    }

    public void saveEventLogData(long eventId, EventLog eventLog) {
        Object[] parameters = {eventId, eventLog.getRouteId(), eventLog.getEventType().getEventTypeId(),
            eventLog.getOrderId(), eventLog.getIncomingEventTimestamp(), eventLog.getOutgoingEventTimestamp()};
        int[] types = {Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP, Types.TIMESTAMP};
        int rowsAffected = jdbcTemplate.update(INSERT_EVENT_LOG_SQL, parameters, types);
    }

    public int saveEventLogMessageData(long eventId, EventLogMessage eventLogMessage) {
        Object[] parameters = {eventId, eventLogMessage.getIncomingEventMessage(), eventLogMessage.getOutgoingEventMessage()};
        int[] types = {Types.INTEGER, Types.VARCHAR, Types.VARCHAR};
        int rowsAffected = jdbcTemplate.update(EventLogConstants.INSERT_EVENT_LOG_MESSAGE_SQL, parameters, types);
        return rowsAffected;
    }

    public int saveEventLogAuditData(long eventId, String userId, Timestamp outgoingEventTimestamp) {
        long eventAuditId = getNextEventAuditIdSequence();
        Object[] parameters = {eventAuditId, eventId, userId, outgoingEventTimestamp};
        int[] types = {Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP};
        int rowsAffected = jdbcTemplate.update(INSERT_EVENT_LOG_AUDIT_SQL, parameters, types);
        return rowsAffected;
    }

    public long getNextEventIdSequence() {
        return jdbcTemplate.queryForLong(SELECT_EVENT_LOG_SEQUENCE_SQL);
    }

    public long getNextEventAuditIdSequence() {
        return jdbcTemplate.queryForLong(SELECT_EVENT_LOG_AUDIT_SEQUENCE_SQL);
    }

    public List<EventLog> getEventLogDetails() {
        return jdbcTemplate.query(SELECT_EVENT_LOG_SQL, new BaseEventLogDao.EventLogRowMapper());
    }

   //extra code removed for brevity
}

1 个答案:

答案 0 :(得分:0)

发现问题并修复它。这是因为没有使用Java 7中提供的Future功能和具有返回类型的方法。找到了这篇文章的解决方案(http://www.baeldung.com/spring-async

我的更改如下所述。

PublicApiMessageHandler.java(已更新)

if (eventDBLoggingEnabled) {
                long eventId = 0L;
                try {
                    logger.info("Saving event data in DB now........");
                    eventId = logEventData(route.getRouteId(), message, transformedMessage, incomingEventTimestamp,
                            outgoingEventTimestamp, DEFAULT_USER_ID);
                } catch (Exception e) {
                    logger.error("Some error occured while storing data in event log tables for eventId: "
                            + eventId + " - " + e.getMessage(), e);
                    errorAlertService.sendAlert(e, route, message, Alert.AlertType.ERROR_500);
                }
            }
        }
        return MessageHandler.Status.OK;
    }

    private long logEventData(int routeId, String incomingEventMessage, String outgoingEventMessage,
            Timestamp incomingEventTimestamp, Timestamp outgoingEventTimestamp, String userId)
            throws SQLException, Exception {
        long eventId = 0L;
        Future<Long> future = eventLogService.saveEventData(routeId, incomingEventMessage, outgoingEventMessage,
                incomingEventTimestamp, outgoingEventTimestamp, userId);
        while (true) {
            if (future.isDone()) {
                eventId = future.get();
                break;
            }
        }
        return eventId;
    }

EventLogService.java(已更新)

@Async
    public Future<Long> saveEventData(int routeId, String incomingEventMessage, String outgoingEventMessage,
            Timestamp incomingEventTimestamp, Timestamp outgoingEventTimestamp, String userId) throws SQLException {
        String orderId = GenericUtil.extractOrderId(incomingEventMessage);
        EventType eventType = buildEventTypeData(incomingEventMessage);
        EventLog eventLog = eventBuilderService.buildEvent(eventType, routeId, orderId,
                incomingEventMessage, outgoingEventMessage, incomingEventTimestamp, outgoingEventTimestamp);
        long eventId = eventLogDao.save(eventLog, userId);
        if (eventId == 0L) {
            throw new RuntimeException(ERROR_MSG);
        }
        return new AsyncResult<>(eventId);
    }