我有一种方法可以在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
}
答案 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);
}