/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed 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 org.openspaces.events.asyncpolling.config;
import org.openspaces.core.GigaSpace;
import org.openspaces.core.util.AnnotationUtils;
import org.openspaces.events.DynamicEventTemplateProvider;
import org.openspaces.events.SpaceDataEventListener;
import org.openspaces.events.TransactionalEvent;
import org.openspaces.events.asyncpolling.AsyncPolling;
import org.openspaces.events.asyncpolling.SimpleAsyncPollingContainerConfigurer;
import org.openspaces.events.support.AnnotationProcessorUtils;
import org.openspaces.events.support.EventContainersBus;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
/**
* A {@link org.openspaces.events.asyncpolling.AsyncPolling} annotation post processor. Creates an internal
* instance of {@link org.openspaces.events.asyncpolling.SimpleAsyncPollingEventListenerContainer} that wraps the given
* bean (if annotated) listener.
*
* @author kimchy
*/
public class AsyncPollingAnnotationPostProcessor implements BeanPostProcessor, ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
if (bean == null) {
return bean;
}
Class<?> beanClass = this.getBeanClass(bean);
if (beanClass == null) {
return bean;
}
AsyncPolling polling = AnnotationUtils.findAnnotation(beanClass, AsyncPolling.class);
if (polling == null) {
return bean;
}
GigaSpace gigaSpace = AnnotationProcessorUtils.findGigaSpace(bean, polling.gigaSpace(), applicationContext, beanName);
EventContainersBus eventContainersBus = AnnotationProcessorUtils.findBus(applicationContext);
SimpleAsyncPollingContainerConfigurer pollingContainerConfigurer = new SimpleAsyncPollingContainerConfigurer(gigaSpace);
pollingContainerConfigurer.name(beanName);
if (bean instanceof SpaceDataEventListener) {
pollingContainerConfigurer.eventListener((SpaceDataEventListener) bean);
} else {
pollingContainerConfigurer.eventListenerAnnotation(bean);
}
DynamicEventTemplateProvider templateProvider = AnnotationProcessorUtils.findDynamicEventTemplateProvider(bean);
if (templateProvider != null) {
pollingContainerConfigurer.dynamicTemplate(templateProvider);
}
pollingContainerConfigurer.concurrentConsumers(polling.concurrentConsumers());
pollingContainerConfigurer.receiveTimeout(polling.receiveTimeout());
pollingContainerConfigurer.performSnapshot(polling.performSnapshot());
pollingContainerConfigurer.autoStart(polling.autoStart());
// handle transactions (we support using either @Transactional or @TransactionalEvent or both)
TransactionalEvent transactionalEvent = AnnotationUtils.findAnnotation(beanClass, TransactionalEvent.class);
Transactional transactional = AnnotationUtils.findAnnotation(beanClass, Transactional.class);
if (transactionalEvent != null || transactional != null) {
if (transactionalEvent != null) {
pollingContainerConfigurer.transactionManager(AnnotationProcessorUtils.findTxManager(transactionalEvent.transactionManager(), applicationContext, beanName));
} else {
pollingContainerConfigurer.transactionManager(AnnotationProcessorUtils.findTxManager("", applicationContext, beanName));
}
Isolation isolation = Isolation.DEFAULT;
if (transactional != null && transactional.isolation() != Isolation.DEFAULT) {
isolation = transactional.isolation();
}
if (transactionalEvent != null && transactionalEvent.isolation() != Isolation.DEFAULT) {
isolation = transactionalEvent.isolation();
}
pollingContainerConfigurer.transactionIsolationLevel(isolation.value());
int timeout = TransactionDefinition.TIMEOUT_DEFAULT;
if (transactional != null && transactional.timeout() != TransactionDefinition.TIMEOUT_DEFAULT) {
timeout = transactional.timeout();
}
if (transactionalEvent != null && transactionalEvent.timeout() != TransactionDefinition.TIMEOUT_DEFAULT) {
timeout = transactionalEvent.timeout();
}
pollingContainerConfigurer.transactionTimeout(timeout);
}
eventContainersBus.registerContainer(beanName, pollingContainerConfigurer.pollingContainer());
return bean;
}
private Class<?> getBeanClass(Object bean) {
return AopUtils.getTargetClass(bean);
}
}