好吧,我正在使用spring web MVC进行保护,并在我的WebAppInitializer中配置了两个调度程序:
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(MvcConfig.class);
rootContext.register(ApplicationContextProvider.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher
= container.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
// Create servlet for WS
MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
messageDispatcherServlet.setApplicationContext(rootContext);
messageDispatcherServlet.setTransformWsdlLocations(true);
ServletRegistration.Dynamic messageDispatcher
= container.addServlet("messageDispatcher", messageDispatcherServlet);
messageDispatcher.setLoadOnStartup(2);
messageDispatcher.addMapping("/ws/*");
一个用于常规Web应用程序,另一个用于soap Web服务。
@EnableTransactionManagement(proxyTargetClass = true)
注释已设置,
我配置了HibernateTransactionManager
bean和SessionFactory;
会话工厂用于访问db - 通过DAO注释,注释为@Transactional
和@Repository
;
在大多数情况下,即使在Spring的ThreadPoolTaskExecutor
生成的新线程中,一切都像魅力一样;
但是当我尝试在WS拦截器中使用我的DAO存储库时,SessionFactory.getCurrentSession
失败了:
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread;
目前,问题可能会通过以下方式解决:
Session session;
try {
session = sessionFactory.getCurrentSession();
} catch (HibernateException e) {
session = sessionFactory.openSession();
}
但说实话我不喜欢这个解决方案。
这是我的hibernate属性:
hibernate.format_sql = false
hibernate.show_sql = false
hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
hibernate.hbm2ddl.auto = update
javax.persistence.validation.mode = none
WS拦截器配置:
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
PayloadRootSmartSoapEndpointInterceptor interceptor = new PayloadRootSmartSoapEndpointInterceptor(
authEndpointInterceptor, LeadServiceEndpoint.NAMESPACE_URI, "");
interceptors.add(interceptor);
super.addInterceptors(interceptors);
}
所以问题是 - 为什么我的会话工厂bean中没有会话,从Spring WS拦截器访问它?
非常感谢任何帮助;
添加更多详细信息:
拦截器:
@Component
public class AuthEndpointInterceptor implements EndpointInterceptor {
@Autowired
private AuthProvider defaultAuthProvider;
@Override
public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
// TODO Make marshaller as a bean
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.itsupportme.gpipeline.component.soap.ws.types");
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) messageContext.getRequest();
SoapBody requestBody = saajSoapMessage.getSoapBody();
Object obj = marshaller.unmarshal(requestBody.getPayloadSource());
if (!(obj instanceof KeySignatureAware)) {
// TODO Implement bad response functionality
return false;
}
AuthResultInterface authResult = defaultAuthProvider.doAuth((KeySignatureAware) obj);
if (!authResult.getStatus()) {
// TODO Implement bad response functionality
return false;
}
return true;
}
提供者:
@Service
@Transactional
public class DefaultAuthProvider implements AuthProvider {
@Autowired
private CredentialsDao credentialsDao;
@Override
public AuthResultInterface doAuth(KeySignatureAware keySignatureAware) {
// Check key and signature
if (keySignatureAware.getKey() == null) {
return new AuthResult(false, "Key is not provided.");
}
if (keySignatureAware.getSignature() == null) {
return new AuthResult(false, "Signature is not provided.");
}
// Find if such credentials are there
Credentials credentials = credentialsDao.findByKey(keySignatureAware.getKey());
if (credentials == null) {
return new AuthResult(false, "Invalid key provided");
}
...
}
DAO:
@Repository
@Transactional
public class CredentialsDaoImpl implements CredentialsDao{
@Autowired
SessionFactory sessionFactory;
@Override
@SuppressWarnings("unchecked")
public Credentials findByKey(String key) {
List<Credentials> credentialsList;
Session session = sessionFactory.getCurrentSession();;
credentialsList = session
.createQuery("from Credentials where apiKey = :apiKey")
.setParameter("apiKey", key)
.list();
if (credentialsList.size() > 0){
return credentialsList.get(0);
} else {
return null;
}
}
}
答案 0 :(得分:0)
通过将@Repository
bean - CredentialsDaoImpl
标记为PROTOTYPE_SCOPE
bean来解决问题。并检索回购。来自应用程序上下文的实例;
结果,spring为repo中的线程创建了新的存储库bean。被调用(从我的理解)创建一个与该线程相关的适当会话;