【问题标题】:EJB @PostConstruct not called未调用 EJB @PostConstruct
【发布时间】:2017-01-12 20:36:59
【问题描述】:

当我想用@PostConstruct 调用一个方法时,该方法不会被调用。我没有从服务器收到任何错误或日志。我是否必须添加一些配置 xml 文件或添加额外的注释才能调用该方法?

Serlvet:

public class PersonServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = LoggerFactory.getLogger(PersonServlet.class);

    @EJB
    Storage storage;

    protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
      try {
        HttpSession session = req.getSession(true);
        storage = (Storage) session.getAttribute(Storage.class.getName());
        if (storage == null) {
           storage = new Storage();
           session.setAttribute(Storage.class.getName(), storage);
        }     
        // create odata handler and configure it with CsdlEdmProvider and Processor
        OData odata = OData.newInstance();
        ServiceMetadata edm = odata.createServiceMetadata(new PersonEdmProvider(), new ArrayList<EdmxReference>());
        ODataHttpHandler handler = odata.createHandler(edm);
        handler.register(new PersonEntityCollectionProcessor(storage));
        handler.register(new PersonEntityProcessor(storage));
        handler.register(new PersonPrimitiveProcessor(storage));

        // let the handler do the work
        handler.process(req, resp);
      } catch (RuntimeException e) {
        LOG.error("Server Error occurred in ExampleServlet", e);
        throw new ServletException(e);
      }
    }
}

人道

@Stateless
public class PersonDAO {

    @PersistenceContext
    private EntityManager em;

    public List<Person> getAllPersons() {

        return 
            em.createQuery("SELECT p FROM T_Person p", Person.class).getResultList();

    }

}

存储:

@Stateless
public class Storage {

    @EJB
    PersonDAO psDAO;

    private List<Entity> personList;

    public Storage() {
        personList = new ArrayList<Entity>();
    }

    @PostConstruct
     private void initSampleData(){
         psDAO.getAllPersons();
    }
}

PersonEntityCollectionProcessor:

public class PersonEntityCollectionProcessor implements EntityCollectionProcessor {

    private OData odata;
    private ServiceMetadata serviceMetadata;
    private Storage storage;

    public PersonEntityCollectionProcessor(Storage storage) {
        this.storage = storage;
    }

    public void init(OData odata, ServiceMetadata serviceMetadata) {
        this.odata = odata;
        this.serviceMetadata = serviceMetadata;
    }

}

【问题讨论】:

  • 提供的任何答案是否解决了您的问题?

标签: java glassfish ejb javabeans postconstruct


【解决方案1】:

我认为问题在于您的这部分代码:

    storage = (Storage) session.getAttribute(Storage.class.getName());
    if (storage == null) {
       storage = new Storage();
       session.setAttribute(Storage.class.getName(), storage);
    }    

这样,您将创建Storage 的非托管实例,而不是使用注入的实例,因此不会调用@PostConstruct。 如果这段代码执行时通过@EJB注入的Storage的实例是null,则可能是注入有问题。

您可以删除这 5 行,它应该可以工作。您无需在会话中手动保存实例。

【讨论】:

    【解决方案2】:

    大多数 EJB 都是延迟初始化的,所以 @PostConstruct 仅在您实际使用该 bean 的实例时才/第一次调用。

    这就是说;您从不使用 servlet 存储的实际 sessionbean,因此无需调用 @PostConstruct

    您从会话中覆盖它,或重新创建它

        storage = (Storage) session.getAttribute(Storage.class.getName());
        if (storage == null) {
           storage = new Storage();
           session.setAttribute(Storage.class.getName(), storage);
        }     
    

    【讨论】:

    • 感谢您的回答!这就是问题所在。
    • @Stateless bean 存储到会话中也是没有意义的,因为它不应该存储任何状态。无状态 bean 应该被视为具有静态方法的类 - 它们可以随时重新创建,并且您不应依赖方法调用之间的任何实例数据。您可能想改用@Stateful
    猜你喜欢
    • 2015-05-01
    • 2012-12-18
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 2012-10-28
    相关资源
    最近更新 更多