Spring WS拦截器 - 无法获得会话

时间:2016-05-25 15:36:21

标签: java spring hibernate web-services spring-mvc

好吧,我正在使用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;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

通过将@Repository bean - CredentialsDaoImpl标记为PROTOTYPE_SCOPE bean来解决问题。并检索回购。来自应用程序上下文的实例;

结果,spring为repo中的线程创建了新的存储库bean。被调用(从我的理解)创建一个与该线程相关的适当会话;