JAX-RS使用的无状态EJB中的@Context注入

时间:2015-03-18 21:00:04

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

我在下面有这样的设置。这是一个简化版本,但我认为它得到了基本的想法。我正在使用Jersey 2.16,Java 1.8和Glassfish Open Source 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异常。似乎根本没有注入Context。我检查过它是secContext变量本身,而不仅仅是getUserPrincipal()的返回值为null。除了我的NullPointer之外,Glassfish日志中没有警告或异常(导致向Web客户端返回500错误)。

2 个答案:

答案 0 :(得分:3)

问题是你在错误的地方使用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)。

答案 1 :(得分:2)

谢谢,我已经解决了使用EJB内部的EJBContext,正如unwichtich指出的那样。

总之,SecurityContext仅适用于JAX-RS bean,我已将EJBContext对象替换为SecurityContext到其他java bean中。 您也可以使用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。