Table of Contents
Key Facts and Overview
- ServletContextListener runs contextInitialized() during a deployment operation
- ServletContextListener runs contextDestroyed() during a un-deployment operation
- This allows to cleanup or initialize certain objects factories, loggers, ..
- Without a clean shutdown you may encounter following Exception during redeployment of a WEB applications
12:54:21.020 Object: com.hhu.wfjpa2el.Emp2[ empno=9997 ] is not a known entity type. 12:54:21.020 java.lang.IllegalArgumentException: Object: com.hhu.wfjpa2el.Emp2[ empno=9997 ] is not a known entity type. at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4228) at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:496) at com.hhu.wfjpa2el.JPATestBean.runJPA(JPATestBean.java:137) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- To solve this reboot your Webserver or shutdown() the Entity Manager Factory
JAVA Code
- JPATestBean() constructor stores/binds a object reference of the current JPATestBean() reference via JNDI
- shutdown() is invoked by ServletContextListener function contextDestroyed() and stops the Entity Manager Factory.
- ServletContextListener is using JNDI lookup to get the object reference
JPATestBean.java public JPATestBean() throws Exception { ctx = new InitialContext(); ctx.rebind(jndiName, this); logger.info("Constructor JPATestBean() called and bound to JNDI !"); } static { emf = Persistence.createEntityManagerFactory("jpaELPU"); threadLocal = new ThreadLocal<EntityManager>(); } public void shutdown() { logger.info("\nWeb Application shutdown ..." ); closeEntityManager(); logger.info("Closing Entitiy Manager Factory ..." ); emf.close(); emf=null; System.gc(); logger.info("Leaving Web Application shutdown" ); } ... Implementing ServletContextListener - contextDestroyed() uses JNDI lookup to read an object reference from our JPATestBean() instance - contextDestroyed() invokes shutdown methode to run a clean application shutdown web.xml entry ./src/main/webapp/WEB-INF/web.xml .. <listener> <listener-class>com.hhu.wfjpa2el.ServletContextListenerImpl</listener-class> </listener> Java Code for ServletContextListener package com.hhu.wfjpa2el; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.slf4j.LoggerFactory; public class ServletContextListenerImpl implements ServletContextListener { final static org.slf4j.Logger logger = LoggerFactory.getLogger(ServletContextListenerImpl.class); private JPATestBean jtb; private final String jndiName = "java:global/myJPATestBean"; private InitialContext ctx; @Override public void contextInitialized(ServletContextEvent arg) { logger.info("+++ ServletContextListener : contextInitialized - no action \n"); } @Override public void contextDestroyed(ServletContextEvent arg) { System.out.println("+++ ServletContextListener: running contextDestroyed()...."); try { ctx = new InitialContext(); jtb = (JPATestBean)ctx.lookup(jndiName); jtb.shutdown(); logger.info("+++ ServletContextListener: Leaving contextDestroyed() without Exception\n"); } catch (NamingException ex) { //Logger.getLogger(ServletContextListenerImpl.class.getName()).log(Level.SEVERE, null, ex); logger.error("+++ Error in contextDestroyed()\n" + ex); } } }
Reference