0

我在我的应用程序的 JPA/EJB 3/JSF 2/Spring Security 3 中使用 glassfish 3.1.2。我想编写一个像这样的自定义 UserdetailsS​​ervice:

import org.apache.log4j.Logger;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
    public class MyUserDetailsService implements UserDetailsService {

        private static final Logger logger = Logger.getLogger(MyUserDetailsService.class);
        @EJB
        private CollaborateurFacadeLocal collaborateurFacade;

        @Override
        public UserDetails loadUserByUsername(String userName) {
            Collaborateur collab = getUser(userName);
            if (collab == null) {
                throw new UsernameNotFoundException(userName + " not found");
            }
            User user = new User(collab);
            if (user == null) {
                throw new UsernameNotFoundException(userName + " not found");
            }
            return user;
        }
    }

所以我试图在我的 MyUserDetailsS​​ervice 中注入一个 EJB,以便能够在我的 Spring Security 上下文文件中将它用作身份验证提供程序:“applicationContext-security.xml”,如下所示:

<authentication-manager>
        <authentication-provider user-service-ref="myUserDetailsService">
        </authentication-provider>
    </authentication-manager>

问题是我陷入了由空协作外观引起的 NullPointerException。

我尝试了几件事,其中包括:

  • 使用上下文查找 EJB(就像这里的那个):解决方案有效,但这不是我想要的:因为 EJB 的名称可能会被修改。

  • 将 MyUserDetailsS​​ervice 类作为 JSF 2 托管 bean,collaborateurFacade 一直保持到 null。

  • 将 MyUserDetailsS​​ervice 类作为 JSF 2 托管 bean 并具有 ApplicationScoped 范围,collaborateurFacade 直到 null。

问题:是否有任何干净的方法可以在 MyUserDetailsS​​ervice 类中注入 EJB?

我知道我可以使用 @Service 注释来注释我的类(请参阅此链接),然后我将陷入我不想要的 EJB 和 Spring 的混合

4

2 回答 2

2

这是一个简单的例子,理论上应该有效

  1. 将其添加到您的上下文配置中
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">  
    <property name=”alwaysUseJndiLookup” value=”true” />  
</bean>  

2. 我猜你有一个本地 EJB,因为你尝试使用 @EJB 注释。您必须为您的 EJB 提供一个映射名称。例如对于无国籍的一种用途

@Stateless(name = "ejb/CollaborateurFacade", mappedName = "ejb/CollaborateurFacade")
class CollaboratorFacade {}

3.在你的spring bean中使用mappedName

@EJB(mappedName = "ejb/CollaborateurFacade")
private CollaborateurFacadeLocal collaborateurFacade;

我知道您写道,EJB 的名称是一个需要修改的主题,但我不明白您如何能以您尝试这样做的方式避免这种情况。

还有另一种可能的解决方案(基于xml!)http://czetsuya-tech.blogspot.ca/2012/05/how-to-call-stateless-ejb-from-spring.html

于 2013-05-17T17:23:37.507 回答
1

我想通过以下方式解决我的问题:不重命名我的外观 (EJB),并且必须使用我在类注释 @EJB 中定义的名称来查找我的 EJB。然后我的 UserDetailsS​​ervice 变成这样:

@EJB(name = "collaborateurFacadeLocal", beanInterface = CollaborateurFacadeLocal.class)
public class SiUserDetailsService implements UserDetailsService {

    private static final Logger logger = Logger.getLogger(SiUserDetailsService.class);
    private CollaborateurFacadeLocal collaborateurFacade;

    private static final String COLLABORATEUR_EJB_LOOKUP_PATH = "java:comp/env/collaborateurFacadeLocal";

    @Override
    public UserDetails loadUserByUsername(String userName) {
        User user;
        Collaborateur collab = getUser(userName);
        if (collab == null) {
            throw new UsernameNotFoundException(userName + " not found");
        }
        user = new User(collab);
        if (user == null) {
            throw new UsernameNotFoundException(userName + " not found");
        }
        return user;
    }

    private Collaborateur getUser(String userName) {
        try {
            InitialContext initialContext = new InitialContext();
            collaborateurFacade = (CollaborateurFacadeLocal) initialContext.lookup(COLLABORATEUR_EJB_LOOKUP_PATH);
            return collaborateurFacade.findUserByUserName(userName);
        } catch (NamingException ex) {
            logger.error("Could not lookup for EJB CollaborateurFacadeLocal with lookup path " + COLLABORATEUR_EJB_LOOKUP_PATH);
        }
        return null;
    }
}

java:comp/env/collaborateurFacadeLocal 中的 CollaborateurFacadeLocal 是 @EJB(name = 注释中的一个,将其与属性 @EJB(name =

这边走:

  • 如果外观名称更改,我的 SiUserDetailsS​​ervice 中将出现编译错误,并且仅在我的 siUserDetailsS​​ervice 类中更改其名称,查找仍然有效。
  • 如果耳朵名称发生变化,我的 SiUserDetailsS​​ervice 仍然有效,因为我不使用耳朵名称进行查找。

我的 Spring Security 上下文文件仍然是:

<beans:bean id = "siUserDetailsService" class = "com.xxx.xxx.beans.SiUserDetailsService" />  

    <authentication-manager>
        <authentication-provider user-service-ref="siUserDetailsService">
        </authentication-provider>
    </authentication-manager>
于 2013-05-24T08:31:25.377 回答