Add ActionEventIntercepter to implement origianl ActionEventCallback in Spring AOP

This commit is contained in:
Kelven Yang 2013-01-14 17:44:31 -08:00
parent 96bd1d4172
commit f304df44df
5 changed files with 150 additions and 9 deletions

View File

@ -33,7 +33,7 @@
<context:annotation-config />
<context:component-scan base-package="org.apache.cloudstack, com.cloud" />
<!--
@DB support
-->
@ -44,7 +44,7 @@
<aop:around pointcut-ref="captureAnyMethod" method="AroundAnyMethod"/>
</aop:aspect>
</aop:config>
<bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
<!--

View File

@ -40,13 +40,14 @@ import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.dao.VMInstanceDaoImpl;
@Component
@Local(value={HostPodDao.class})
public class HostPodDaoImpl extends GenericDaoBase<HostPodVO, Long> implements HostPodDao {
private static final Logger s_logger = Logger.getLogger(HostPodDaoImpl.class);
@Inject VMInstanceDaoImpl _vmDao;
@Inject VMInstanceDao _vmDao;
protected SearchBuilder<HostPodVO> DataCenterAndNameSearch;
protected SearchBuilder<HostPodVO> DataCenterIdSearch;

View File

@ -0,0 +1,137 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.event;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import com.cloud.user.UserContext;
@Aspect
public class ActionEventInterceptor {
public ActionEventInterceptor() {
}
@Pointcut(value="execution( * *(..))")
public void anyMethod() {
}
@Around("anyMethod() && @annotation(ActionEvent)")
public Object AroundAnyMethod(ProceedingJoinPoint call) throws Throwable {
MethodSignature methodSignature = (MethodSignature)call.getSignature();
Method targetMethod = methodSignature.getMethod();
if(needToIntercept(targetMethod)) {
EventVO event = interceptStart(targetMethod);
boolean success = true;
Object ret = null;
try {
ret = call.proceed();
} catch (Throwable e) {
success = false;
interceptException(targetMethod, event);
throw e;
} finally {
if(success){
interceptComplete(targetMethod, event);
}
}
return ret;
}
return call.proceed();
}
public EventVO interceptStart(AnnotatedElement element) {
EventVO event = null;
Method method = (Method)element;
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
if (actionEvent != null) {
boolean async = actionEvent.async();
if(async){
UserContext ctx = UserContext.current();
long userId = ctx.getCallerUserId();
long accountId = ctx.getAccountId();
long startEventId = ctx.getStartEventId();
String eventDescription = actionEvent.eventDescription();
if(ctx.getEventDetails() != null){
eventDescription += ". "+ctx.getEventDetails();
}
EventUtils.saveStartedEvent(userId, accountId, actionEvent.eventType(), eventDescription, startEventId);
}
}
return event;
}
public void interceptComplete(AnnotatedElement element, EventVO event) {
Method method = (Method)element;
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
if (actionEvent != null) {
UserContext ctx = UserContext.current();
long userId = ctx.getCallerUserId();
long accountId = ctx.getAccountId();
long startEventId = ctx.getStartEventId();
String eventDescription = actionEvent.eventDescription();
if(ctx.getEventDetails() != null){
eventDescription += ". "+ctx.getEventDetails();
}
if(actionEvent.create()){
//This start event has to be used for subsequent events of this action
startEventId = EventUtils.saveCreatedEvent(userId, accountId, EventVO.LEVEL_INFO, actionEvent.eventType(), "Successfully created entity for "+eventDescription);
ctx.setStartEventId(startEventId);
} else {
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, actionEvent.eventType(), "Successfully completed "+eventDescription, startEventId);
}
}
}
public void interceptException(AnnotatedElement element, EventVO event) {
Method method = (Method)element;
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
if (actionEvent != null) {
UserContext ctx = UserContext.current();
long userId = ctx.getCallerUserId();
long accountId = ctx.getAccountId();
long startEventId = ctx.getStartEventId();
String eventDescription = actionEvent.eventDescription();
if(ctx.getEventDetails() != null){
eventDescription += ". "+ctx.getEventDetails();
}
if(actionEvent.create()){
long eventId = EventUtils.saveCreatedEvent(userId, accountId, EventVO.LEVEL_ERROR, actionEvent.eventType(), "Error while creating entity for "+eventDescription);
ctx.setStartEventId(eventId);
} else {
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, actionEvent.eventType(), "Error while "+eventDescription, startEventId);
}
}
}
private boolean needToIntercept(Method method) {
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
if (actionEvent != null) {
return true;
}
return false;
}
}

View File

@ -34,8 +34,10 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.cluster.agentlb.HostTransferMapVO;
import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.ClusterDaoImpl;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
@ -115,10 +117,10 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
protected Attribute _msIdAttr;
protected Attribute _pingTimeAttr;
@Inject protected HostDetailsDaoImpl _detailsDao;
@Inject protected HostTagsDaoImpl _hostTagsDao;
@Inject protected HostTransferMapDaoImpl _hostTransferDao;
@Inject protected ClusterDaoImpl _clusterDao;
@Inject protected HostDetailsDao _detailsDao;
@Inject protected HostTagsDao _hostTagsDao;
@Inject protected HostTransferMapDao _hostTransferDao;
@Inject protected ClusterDao _clusterDao;
public HostDaoImpl() {
}

View File

@ -37,6 +37,7 @@ import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDaoImpl;
import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.tags.dao.ResourceTagsDaoImpl;
import com.cloud.utils.Pair;
@ -85,7 +86,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
protected SearchBuilder<VMInstanceVO> NetworkTypeSearch;
protected GenericSearchBuilder<VMInstanceVO, String> DistinctHostNameSearch;
@Inject ResourceTagsDaoImpl _tagsDao;
@Inject ResourceTagDao _tagsDao;
@Inject NicDao _nicDao;
protected Attribute _updateTimeAttr;
@ -103,7 +104,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
" AND host.pod_id = ? AND host.cluster_id = ? AND host.type = 'Routing' " +
" GROUP BY host.id ORDER BY 2 ASC ";
@Inject protected HostDaoImpl _hostDao;
@Inject protected HostDao _hostDao;
public VMInstanceDaoImpl() {
}