//$Id: ConversationalInterceptor.java,v 1.18 2007/02/22 20:21:22 gavin Exp $
package org.jboss.seam.interceptors;
import java.lang.reflect.Method;
import javax.faces.application.FacesMessage;
import javax.faces.event.PhaseId;
import org.jboss.seam.NoConversationException;
import org.jboss.seam.annotations.AroundInvoke;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.BeginTask;
import org.jboss.seam.annotations.Conversational;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Interceptor;
import org.jboss.seam.annotations.StartTask;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.core.Events;
import org.jboss.seam.core.FacesMessages;
import org.jboss.seam.core.Manager;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* Check that a conversational bean is not being invoked
* outside the scope of a long-running conversation.
*
* @author Gavin King
*/
@Interceptor(stateless=true,
around={ValidationInterceptor.class, BijectionInterceptor.class, BusinessProcessInterceptor.class})
public class ConversationalInterceptor extends AbstractInterceptor
{
private static final long serialVersionUID = 1127583515811479385L;
private static final LogProvider log = Logging.getLogProvider(ConversationalInterceptor.class);
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception
{
Method method = invocation.getMethod();
if ( isNoConversationForConversationalBean(method) )
{
@SuppressWarnings("deprecation")
String outcome = methodIsConversational(method) ?
method.getAnnotation(Conversational.class).ifNotBegunOutcome() :
getComponent().getBeanClass().getAnnotation(Conversational.class).ifNotBegunOutcome();
if ( "".equals(outcome) )
{
Events.instance().raiseEvent("org.jboss.seam.noConversation");
throw new NoConversationException( "no long-running conversation for @Conversational bean: " + getComponent().getName() );
}
else
{
//Deprecated functionality:
if ( Lifecycle.getPhaseId()==PhaseId.INVOKE_APPLICATION )
{
if ( log.isDebugEnabled() )
{
log.debug( "no long-running conversation for @Conversational bean: " + getComponent().getName() );
}
Events.instance().raiseEvent("org.jboss.seam.noConversation");
FacesMessages.instance().addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_WARN,
"org.jboss.seam.NoConversation",
"No conversation"
);
if ( method.getReturnType().equals(String.class) )
{
return outcome;
}
else if ( method.getReturnType().equals(void.class) )
{
return null;
}
}
}
}
return invocation.proceed();
}
private boolean isNoConversationForConversationalBean(Method method)
{
boolean classlevelViolation = componentIsConversational() &&
( !Manager.instance().isLongRunningOrNestedConversation() || ( componentShouldBeInitiator() && !componentIsInitiator() ) ) &&
!method.isAnnotationPresent(Begin.class) &&
!method.isAnnotationPresent(StartTask.class) &&
!method.isAnnotationPresent(BeginTask.class) &&
!method.isAnnotationPresent(Destroy.class) &&
!method.isAnnotationPresent(Create.class); //probably superfluous
if (classlevelViolation) return true;
boolean methodlevelViolation = methodIsConversational(method) &&
( !Manager.instance().isLongRunningOrNestedConversation() || ( componentShouldBeInitiator(method) && !componentIsInitiator() ) );
return methodlevelViolation;
}
private boolean methodIsConversational(Method method) {
return method.isAnnotationPresent(Conversational.class);
}
@SuppressWarnings("deprecation")
private boolean componentShouldBeInitiator(Method method) {
return method.getAnnotation(Conversational.class).initiator();
}
private boolean componentIsConversational() {
return getComponent().getBeanClass().isAnnotationPresent(Conversational.class);
}
@SuppressWarnings("deprecation")
private boolean componentShouldBeInitiator() {
return getComponent().getBeanClass().getAnnotation(Conversational.class).initiator();
}
@SuppressWarnings("deprecation")
private boolean componentIsInitiator()
{
return getComponent().getName().equals( Manager.instance().getCurrentConversationInitiator() );
}
}