I'm using Apache Shiro 1.2.0 in a long-running application that reads messages from a queue and and takes action. The action taken requires a Shiro authenticated session, so I've implemented an "ActAsAuthenticationToken" and custom credentials matcher which allows us to login in with only the username. I'm using the DefaultSecurityManager with only my custom realm and subject factory injected. Everything else should be default.
As it is configured, everything worked fine for a while, but as the application ran a long time (not that long - like a full day) I started to get this stack trace whenever I did anything that required the session:
Caused by: org.apache.shiro.session.UnknownSessionException: There is no session with id [f5b7c3bf-2c53-40e9-a707-37f4265970aa]
at org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:170)
at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSessionFromDataSource(DefaultSessionManager.java:236)
at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSession(DefaultSessionManager.java:222)
at org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doGetSession(AbstractValidatingSessionManager.java:118)
at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupSession(AbstractNativeSessionManager.java:105)
at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupRequiredSession(AbstractNativeSessionManager.java:109)
at org.apache.shiro.session.mgt.AbstractNativeSessionManager.getAttribute(AbstractNativeSessionManager.java:206)
at org.apache.shiro.session.mgt.DelegatingSession.getAttribute(DelegatingSession.java:141)
at org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
at org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
at org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
at com.factorlab.security.FactorlabDelegatingSubject.getUser(FactorlabDelegatingSubject.java:34)
at com.factorlab.security.FactorlabDelegatingSubject.getUser(FactorlabDelegatingSubject.java:10)
at com.factorlab.persistence.AbstractEntityDao.getCurrentUser(AbstractEntityDao.java:227)
at com.factorlab.persistence.AbstractEntityDao.fireEvent(AbstractEntityDao.java:215)
at com.factorlab.persistence.AbstractEntityDao.saveOrUpdate(AbstractEntityDao.java:190)
at com.factorlab.persistence.AbstractEntityDao.saveOrUpdate(AbstractEntityDao.java:177)
at com.factorlab.persistence.AbstractEntityDao.saveOrUpdate(AbstractEntityDao.java:38)
at sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
at $Proxy72.saveOrUpdate(Unknown Source)
at com.factorlab.observations.sales.OpportunityScoreUpdateServiceImpl.receiveOpportunityEvent(OpportunityScoreUpdateServiceImpl.java:83)
at sun.reflect.GeneratedMethodAccessor103.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy76.receiveOpportunityEvent(Unknown Source)
at sun.reflect.GeneratedMethodAccessor102.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:69)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:84)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102)
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:126)
at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:227)
at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:127)
at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:73)
... 49 more
The really weird part (as far as I'm concerned) is that I have a successful login (or at least an indication that I already have been authenticated right before I get the error:
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
@Trace(dispatcher = true)
public void receiveOpportunityEvent(EntityEvent<Opportunity> event) {
sessionFactory.getCurrentSession().refresh(event.getEntity());
log.info("OpportunityScoreUpdateService receiveOpportunityEvent: " + event);
//
//
// Here we see that we are either authenticated or we log in successfully
//
//
if (!securityUtils.getSubject().isAuthenticated()) {
try {
securityUtils.getFactorlabSubject().login(new ActAsAuthenticationToken(event.getEventUsername()));
} catch (RuntimeException e) {
log.error("Could not log in user " + event.getEventUsername() + ": " + e.getMessage(), e);
return;
}
}
if (event.getEntity() instanceof ObservedOpportunity) {
ObservedOpportunity opportunity = (ObservedOpportunity) event.getEntity();
opportunity = (ObservedOpportunity) opportunityDao.getById(opportunity.getId(), SkippedCheck.PERMISSION, SkippedCheck.DELETED);
if (!opportunity.isDeleted()) {
List<Stage> stages = stageDao.getAllByZone(opportunity.getZone(), SkippedCheck.PERMISSION);
Map<Stage, Double> originalScoresByStage = new HashMap<Stage, Double>();
Map<Stage, Double> newScoresByStage = new HashMap<Stage, Double>();
final Double originalTotal = opportunity.getTotalScore();
for (Stage stage : stages) {
originalScoresByStage.put(stage, opportunity.getScoreByStage(stage));
double score = calculator.getScoreForOpportunityAndStage(opportunity, stage);
opportunity.setScoreByStage(stage, score);
newScoresByStage.put(stage, opportunity.getScoreByStage(stage));
}
final double newTotalScore = calculator.getTotalScoreForOpportunity(opportunity);
opportunity.setTheTotalScore(newTotalScore);
final boolean scoreChanged = originalTotal == null ||
Math.round(originalTotal) != Math.round(newTotalScore) ||
checkStageScoresChanged(originalScoresByStage, newScoresByStage);
if (scoreChanged) {
opportunity.setScoreCalculated(new Date());
//
//
// Here is where we get the exception
//
//
opportunityDao.saveOrUpdate(opportunity, SkippedCheck.PERMISSION);
} else {
opportunityDao.refresh(opportunity);
}
}
}
}
What could be causing this exception?