我有一个简单的(webprofile)EJB 3.1应用程序,并尝试确定@ApplicationScoped
CDI Bean中的当前用户,所以我使用:
Principal callerPrincipal = this.sessionContext.getCallerPrincipal()
效果很好(因此我可以确定当前用户的名称)。
但是在任何(其他)EJB中发生任何异常之后,此调用将不再起作用(我需要重新启动服务器)!该方法不会返回调用者主体,而是引发此异常。
Caused by: java.lang.NullPointerException
at com.sun.ejb.containers.EJBContextImpl.getCallerPrincipal(EJBContextImpl.java:421)
at de.mytest.service.CurrentUserService.getCurrentUserId(CurrentUserService.java:102)
有人可以给我提示我做错了什么吗?
实现细节:
服务器Glassfish 3.1.2
CurrentUserService:
@ApplicationScoped
public class CurrentUserService {
@Resource
private SessionContext sessionContext;
public long getCurrentUserId() {
if (this.sessionContext == null) {
throw new RuntimeException("initialization error, sessionContext must not be null!");
}
/*line 102 */ Principal callerPrincipal = this.sessionContext.getCallerPrincipal();
if (callerPrincipal == null) {
throw new RuntimeException("callerPrincipal must not be null, but it is");
}
String name = callerPrincipal.getName();
if (name == null) {
throw new RuntimeException("could not determine the current user id, because no prinicial in session context");
}
return this.getUserIdForLogin(name);
}
抵制Faces Controller和CDI服务之间的EJB Facad
@Stateless
@RolesAllowed("myUser")
public class TeilnehmerServiceEjb {
@Inject
private CurrentUserService currentUserService;
public long currentUserId() {
return = currentUserService.getCurrentUserId();
}
}
web.xml
<security-constraint>
<web-resource-collection>
<web-resource-name>All Pages</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>myUser</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>mySecurityRealm</realm-name>
</login-config>
glassfish-web.xml
<security-role-mapping>
<role-name>myUser</role-name>
<group-name>APP.MY.USER</group-name>
</security-role-mapping>
最佳答案
它不起作用的原因是因为您的SessionContext对象被声明为全局变量,并且由于您使用的是@ApplicationScope,因此在构建应用程序时,仅通过一次IoC初始化该资源即可。
如果要将bean保留为@ApplicationScope,我建议您每次在执行操作的方法中手动需要SessionContext时尝试尝试访问SessionContext,而不是IoC手动使用JNDI API。
请参阅示例,该示例如何查看如何执行JNDI查找以使用以下命令手动访问资源:
public long getCurrentUserId() {
//..
try {
InitialContext ic = new InitialContext();
SessionContext sessionContext=(SessionContext) ic.lookup("java:comp/env/sessionContext");
System.out.println("look up injected sctx: " + sessionContext);
//Now do what you want with the Session context:
Principal callerPrincipal = sessionContext.getCallerPrincipal();
//..
} catch (NamingException ex) {
throw new IllegalStateException(ex);
}
//..
}
如果您有兴趣了解访问SessionContext的更多方法,请查看以下链接,我在其中找到了该代码片段:
http://javahowto.blogspot.com/2006/06/4-ways-to-get-ejbcontext-in-ejb-3.html
我希望这有帮助