【问题标题】:@Context injection in Stateless EJB used by JAX-RSJAX-RS 使用的无状态 EJB 中的 @Context 注入
【发布时间】:2015-03-18 21:00:04
【问题描述】:

我在下面有类似的设置。这是一个简化版本,但我认为它传达了基本思想。我正在使用 Jersey 2.16、Java 1.8 和 Glassfish 开源 4.1

public interface IReportService {
    String addNewReport(Report report);
}

@Path("reports")
public class ReportResource implements IReportService {
    /**
    * Service layer.
    */
    @EJB
    private transient ReportService service;

    @POST
    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    @Produces(MediaType.TEXT_PLAIN)
    @Override
    public String addNewReport(final Report report) {
       return service.addNewReport(report);
    }
}

@Stateless
@LocalBean
public class ReportService implements IReportService {

   @EJB
   private IReportPersistence reportPersistence;

   @Context
   SecurityContext secContext;

   public String addNewReport(final Report report) {
       report.setUserName(secContext.getUserPrincipal().getName());
       reportPersistence.persist(report);
    }
}

但是当我部署并尝试访问 Web 服务时,我从安全上下文中得到一个 NullPointer 异常。似乎根本没有注入上下文。我检查了一下,它是 secContext 变量本身,而不仅仅是 getUserPrincipal() 的返回值为空。 Glassfish 日志中除了我的 NullPointer 之外没有任何警告或异常(这会导致向 Web 客户端返回 500 错误)。

【问题讨论】:

    标签: java jakarta-ee glassfish ejb jax-rs


    【解决方案1】:

    问题是您在错误的地方使用了SecurityContext。您必须在 REST 资源类中使用它。

    您可以尝试以下方法:

    @POST
    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    @Produces(MediaType.TEXT_PLAIN)
    @Override
    public String addNewReport(final Report report, @Context SecurityContext sc) {
       report.setUserName(sC.getUserPrincipal().getName());
       return service.addNewReport(report);
    }
    

    更多详情请查看Jersey Documentation - Chapter 16. Security。

    在 EJB 内部,您必须使用 EJBContext(或 SessionContext)。

    【讨论】:

    • 啊,我明白了。我希望 Request Scoped SecurityContext 能够映射到无状态 EJB。虽然看起来没有运气。 Glassfish 不会抛出无法处理注释和注入值的警告或错误,这有点烦人。为了让 EJBContext 注入,我应该做些什么特别的事情?我已经试过了,它也是空的。
    【解决方案2】:

    谢谢,正如 unwichtich 所指出的,我已经解决了在 EJB 中使用 EJBContext 的问题。

    总之,SecurityContext 仅适用于 JAX-RS bean,我已在其他 java bean 中使用 EJBContext 对象代替 SecurityContext。 您也可以使用 SessionContext 对象,但 EJBContext 接口类似于 SecurityContext 之一。这是一个使用示例:

    @DeclareRoles({"administrator","operator","user"})
    @PermitAll
    @Stateless
    public class myFacade {
    
        @PersistenceContext(unitName = "myPersistencePU")
        private EntityManager em;
    
        @Resource EJBContext securityContext;
    
        public DataStuff find(Object id) {
            //Now the securityContext is != null :-D
            String username = securityContext.getCallerPrincipal().getName();
            if(username.equals("gino"){
                return null;
            }
            return getEntityManager().find(entityClass, id);
        }
    }
    

    它按预期自动神奇地工作,EJB 看到与 JAX-RS servlet 相同的 Principal(s)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多