OutOfMemoryError - Singleton PK Generator
john_anderson_ii Jun 29, 2004 7:07 PMAs a learning project, I'm writing an OSS J2EE application for help desk call tracking. The "tickets" use their ticket number as their primary key in the database, and the TICKETS table is access via a CMP bean. For several reasons I've decided to not use the auto-increment method for generating the PKs. Mainly I would like to remain as database independent as possible, and I would like to recyle the ticket numbers of tickets that are closed and pushed out of the database into an XML archive. To accomplish generating the Primary Keys (ticket numbers) I've written the following singleton bean following the wonderful example provided on these forums.*
The following bean basically creates a TreeSet with all possible primary keys, then removes the primary keys that are already used. This bean does all this on first use, and remains in memory so that subsequent requests for new PKs are fast.
/* * Created on Jun 28, 2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package org.jcallcenter.ejb.core; import java.rmi.RemoteException; import javax.ejb.EJBException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.RemoveException; import javax.ejb.CreateException; import javax.ejb.ObjectNotFoundException; import javax.naming.Context; import javax.naming.InitialContext; import java.util.TreeSet; import java.util.Iterator; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.PreparedStatement; import java.sql.Connection; import java.sql.SQLException; import org.jcallcenter.supporting.core.EJBNameFactory; /** * @author janderson * * @ejb.bean * name = "PKTicket" * display-name = "PKTicket EJB" * view-type = "local" * jndi-name = "ejb/callcenter/core/PKTicket" * schema = "PKTICKET" * type = "BMP" * primkey-field = "MyPK" * * @jboss.persistence * create-table = "true" * table-name = "PKTICKET" * * @ejb.persistence * table-name = "PKTICKET" * * This class will act as a singleton for tracking Primary Keys. For all practical * purposes it will look like a normal entity bean attached to a database table. * However, it won't really be attached to any specific table. * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class PKTicketBean implements EntityBean { /* * Get the name of the Datasource */ private static final String DATASOURCE_NAME = EJBNameFactory.DATASOURCE_NAME; /* * Declare the maximum value for a Ticket Number (primary Key) */ private static final Integer MAX_VALUE = new Integer(999999); /* * Declare the Entity Context */ private EntityContext ctx; /* * The following string will be used as a fake primary key for the fake table * this bean belongs to. Since this is a singleton only one instance will actually * exist, but a primary key is required by the container. */ public String defaultName; /* * An Tree to hold the Primary Keys from the ticket table. * */ private TreeSet pks = new TreeSet(); /* * An Integer to hold the PK of this object. */ private Integer pk = new Integer(0); /* * This string will be used to set the name, think primary key, of this bean. */ public static final String MY_NAME = "default"; /* * A Tree to hold the Available Primary Keys. */ private TreeSet availPks = new TreeSet(); /* * Generic constructor method. */ public PKTicketBean() { super(); } /* * This method returns an Integer that contains the next primary key from * the ticket table. If the next primary key is out of range, this method * returns a -1. */ /** * @ejb.interface-method */ public Integer getPKs(){ Integer I = (Integer) availPks.first(); int comp = I.compareTo(MAX_VALUE); Integer rval = new Integer(-1); if(comp < 0){ rval = I; availPks.remove(I); } return rval; } /* * The next two getters and setter will never be used. This is just to keep * the EJB Spec happy. */ /** * */ public String getMyPK(){ return defaultName; } public void setMyPK(String name){ this.defaultName = name; } /* * This method should never be used, but it can be used to reset the pk or * something maybe. */ /** * @ejb.interface-method */ public void setPK(Integer pk){ this.pk = pk; } public void ejbActivate() throws EJBException, RemoteException { } /* * It is here that we will intitialize the TreeList pks. This should be done * once and only once upon deployment. It should be re-initialized whenever * records are purged off. It will have to be called implicity since it has * no means for detection. * */ public void ejbLoad() throws EJBException, RemoteException { Connection c = null; DataSource dataSource; String sql = "SELECT ID FROM TICKET"; PreparedStatement statement = null; Context context = null; ResultSet rs = null; //Replace me with a log4j directive. System.out.print("Refreshing the Ticket ID pool. This can take time..."); try{ context = new InitialContext(); dataSource = (DataSource) context.lookup(DATASOURCE_NAME); c = dataSource.getConnection(); statement = c.prepareStatement(sql); rs = statement.executeQuery(); if(rs.next()){ //Rows were returned, pks exists. rs.beforeFirst(); while(rs.next()){ Integer I = new Integer(rs.getInt(1)); //replace me with a log4j directive System.out.print("."); pks.add(new Integer(rs.getInt(1))); } }else{ //Rows were not returned, no PKs exists yet. pks.add(new Integer(0)); } System.out.println(".Done!"); }catch(Exception e){ throw new EJBException("An Error was encountered while getting used Ticket ID's"+ ". Message: " +e); }finally{ try{ c.close(); }catch(SQLException e){ throw new EJBException("An Error was encountered while getting used Ticket ID's"+ ". Message: " +e); } } initializeAvailablePKs(); } /* * This method will take the PKs pulled from the DB and compare it to a list * of all possible PKs. The PKs from the DB will be removed from the list of * available PKs. */ private void initializeAvailablePKs(){ int counter = MAX_VALUE.intValue(); while(counter >= 0){ availPks.add(new Integer(counter)); counter--; } Iterator iterator = pks.iterator(); while(iterator.hasNext()){ Integer removal = (Integer) iterator.next(); System.out.println("Removing Key " +removal.toString()+ " from Available PKs"); boolean b = availPks.remove(removal); if(b){ System.out.println("Removed!"); } } } /* * This method should probably not ever need to be called unless records * have be purched off to be archived. It can be can be * used to refresh the data in this bean. */ public String ejbCreate() throws CreateException, RemoteException{ this.ejbLoad(); return null; } /*EJB Happiness Method */ public void ejbPostCreate(){ } /* * Okay,this may seem a bit weird. We can't use localhome.create() to get * a reference to this bean because we would be refreshing the data every * single time we called it. Instead we want to return a reference to this * bean by Primary Key....er rather our fake primary key since we aren't really * persisting any data anyway. */ public String ejbFindByPrimaryKey(String defaultName)throws ObjectNotFoundException, ObjectNotFoundException { if(!defaultName.equals(MY_NAME)){ throw new ObjectNotFoundException(); }else{ this.defaultName = defaultName; } return defaultName; } /*Generic EJB Methods follow*/ public void ejbPassivate() throws EJBException, RemoteException { } public void ejbRemove() throws RemoveException, EJBException, RemoteException { } public void ejbStore() throws EJBException, RemoteException { } public void setEntityContext(EntityContext arg0) throws EJBException, RemoteException { this.ctx = arg0; } public void unsetEntityContext() throws EJBException, RemoteException { ctx = null; } }
The following code is from the CMP bean's facade that get's the next available primary key from PKTicket and passes it to Ticket's ejbCreate() method.
/* * Created on Jun 22, 2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package org.jcallcenter.ejb.core; import java.rmi.RemoteException; import javax.ejb.EJBException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.ejb.CreateException; import javax.ejb.ObjectNotFoundException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.jcallcenter.interfaces.core.*; import org.jcallcenter.supporting.core.*; /** * @author janderson * * @ejb.bean * name = "TicketFacade" * display-name = "TicketFacade EJB" * description = "Accessor for TicketBean" * view-type = "remote" * type = "Stateless" * jndi-name = "ejb/CallCenter/Core/TicketFacade" * @ejb.ejb-ref * ejb-name = "Ticket" * ref-name = "ejb/CallCenter/Core/Ticket" * view-type = "local" * @jboss.ejb-local-ref * ref-name = "ejb/CallCenter/Core/Ticket" * jndi-name = "CallCenter/Core/Ticket" * @ejb.ejb-ref * ejb-name = "PKTicket" * ref-name = "ejb/CallCenter/Core/PKTicket" * view-type = "local" * @jboss.ejb-local-ref * ref-name = "ejb/CallCenter/Core/PKTicket" * jndi-name = "CallCenter/Core/PKTicket" * * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class TicketFacadeBean implements SessionBean { TicketLocalHome ticketHome = null; PKTicketLocalHome pksHome = null; /** * */ public TicketFacadeBean() { super(); } /* * The next methods are for looking up local interfaces. */ /** * @ejb.interface-method * */ public void newTicket(){ try{ PKTicketLocal pks = pksHome.findByPrimaryKey(PKTicketBean.MY_NAME); Integer I = pks.getPKs(); TicketLocal ticket = ticketHome.create(I,"This is a test ticket"); }catch(CreateException e){ throw new EJBException("There was a problem creating a new ticket. Message: " +e); }catch(ObjectNotFoundException e){ throw new EJBException("The ticket number generator is lost. Message: " +e); } } /* * The next three methods are generic initialization and create methods. */ private TicketLocalHome getTicketBeanLocalHome() throws NamingException{ try{ Context context = new InitialContext(); return (TicketLocalHome) context.lookup(EJBNameFactory.TICKET_BEAN); }catch(NamingException e){ throw new EJBException("There was an error looking up the JNDI name of Ticket EJB. Message: " +e); } } private PKTicketLocalHome getPKTicketLocalHome(){ try{ Context context = new InitialContext(); return (PKTicketLocalHome) context.lookup(EJBNameFactory.PKTICKET_BEAN); }catch(NamingException e){ throw new EJBException("There was an error looking up the JNDI name of PKTicket EJB. Message: " +e); } } /** * @ejb.create-method * @throws CreateException */ public void ejbCreate() throws CreateException{ try{ ticketHome = getTicketBeanLocalHome(); pksHome = getPKTicketLocalHome(); }catch(NamingException e){ throw new EJBException("There was an error looking up the JNDI name of Ticket EJB. Message: " +e); } } public void ejbActivate() throws EJBException, RemoteException { try{ ticketHome = getTicketBeanLocalHome(); }catch(NamingException e){ throw new EJBException("There was an error looking up the JNDI name of Ticket EJB. Message: " +e); } } /* * Generic Stubs (non-Javadoc) * @see javax.ejb.SessionBean#ejbPassivate() */ public void ejbPassivate() throws EJBException, RemoteException { } public void ejbRemove() throws EJBException, RemoteException { } public void setSessionContext(SessionContext arg0) throws EJBException, RemoteException { } }
Finally, the next two code samples are the CMP EJB Ticket and the servlet that I'm using to test this setup.
/* * Created on Jun 21, 2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package org.jcallcenter.ejb.core; import java.rmi.RemoteException; import javax.ejb.EJBException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.RemoveException; import javax.ejb.CreateException; /** * @author janderson * * @ejb.bean * display-name = "Ticket EJB" * description = "Getters and setters for tickets" * name = "Ticket" * view-type = "local" * jndi-name = "ejb/CallCenter/Core/Ticket" * type = "CMP" * cmp-version = "2.x" * primkey-field = "ID" * schema = "TICKET" * @ejb.persistence * table-name = "TICKET" * @jboss.persistence * create-table = "true" * table-name = "TICKET" * post-table-create = "ALTER TABLE TICKET MODIFY ID INT UNSIGNED" * @ejb.finder * query = "Select Object(o) FROM TICKET o" * signature = "java.util.Collection findAll()" * unchecked = "true" * */ public abstract class TicketBean implements EntityBean { /** * This class will hold generic TicketBean information. */ public TicketBean() { super(); } /** * @ejb.persistence * column-name = "ID" * jdbc-type = "INTEGER" * sql-type = "INTEGER" * @jboss.persistence * not-null = "true" * @jboss.jdbc-type * type = "INTEGER" * @jboss.sql-type * type = "INTEGER" * * @ejb.interface-method * @return */ public abstract Integer getID(); public abstract void setID(Integer ID); /** * @ejb.persistence * column-name = "DESCRIPTION" * jdbc-type = "VARCHAR" * sql-type = "VARCHAR(100)" * @jboss.persistence * not-null = "true" * @jboss.jdbc-type * type = "VARCHAR" * @jboss.sql-type * type = "VARCHAR(100) * " * @ejb.interface-method * @return */ public abstract String getDesc(); /** * @ejb.interface-method * @param Desc */ public abstract void setDesc(String Desc); /** * @ejb.create-method * @param s * @throws CreateException */ public Integer ejbCreate(Integer I, String s) throws CreateException{ setDesc(s); setID(I); return null; } public void ejbPostCreate(Integer I, String s){} public void ejbActivate(String S) throws EJBException, RemoteException { } public void ejbLoad() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } public void ejbRemove() throws RemoveException, EJBException, RemoteException { } public void ejbStore() throws EJBException, RemoteException { } public void setEntityContext(EntityContext arg0) throws EJBException, RemoteException { } public void unsetEntityContext() throws EJBException, RemoteException { } }
servlet...
/* * Created on Jun 22, 2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package org.jcallcenter.web.core; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import java.io.PrintWriter; import org.jcallcenter.interfaces.core.TicketFacade; import org.jcallcenter.interfaces.core.TicketFacadeHome; /** * @author janderson * * *@web.servlet * name = "TicketTestServlet" * display-name = "Testing Auto-increment" * description = "None Available" * *@web.servlet-mapping * url-pattern = "/tickettest" *@web.ejb-ref * name = "ejb/TicketFacade" * type = "Session" * home = "TicketFacadeHome" * remote = "TicketFacade" * description = "The CMP Bean TicketFacade" *@jboss.ejb-ref-jndi * ref-name = "ejb/TicketFacade" * jndi-name = "ejb/CallCenter/Core/TicketFacade" * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class TicketTestServlet extends HttpServlet { TicketFacadeHome ticketHome = null; /** * */ public TicketTestServlet() { super(); } protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { arg1.setContentType("text/html"); PrintWriter out = arg1.getWriter(); out.println("<html><head><title>Ticket Test</title></head><body>"); try{ for(int i=0; i< 900000; i++){ TicketFacade facade = ticketHome.create(); facade.newTicket(); } }catch(Exception e){ System.out.println("didn't work" + e.getMessage()); e.printStackTrace(); } out.println("<h1>Success</h1>"); out.println("</body></html>"); } public void init() throws ServletException { try{ Context ctx = new InitialContext(); Object ref = ctx.lookup("java:/comp/env/ejb/TicketFacade"); ticketHome = (TicketFacadeHome) PortableRemoteObject.narrow(ref, TicketFacadeHome.class); }catch(NamingException e){ throw new ServletException("Could not resolve the JNDI name of TicketFacade. " + " Message: " +e); } } }
Now, this setup works great. I create tickets, all have incremented Primary Keys, then I can purge off some tickets, re-initialse PKTicket and recyle the ticket numbers from the PKs I purged off.
You'll notice the servlet loops to the maximum value I have set for available ticket numbers......well....that doesn't work so well.
When I reach ticket number 12820 I get the following error.
java.lang.OutOfMemoryError ; CausedByException is: Unexpected Error java.lang.OutOfMemoryError ; nested exception is: javax.ejb.EJBException: Unexpected Error java.lang.OutOfMemoryError ; - nested throwable: (javax.ejb.EJBException: Unexpected Error java.lang.OutOfMemoryError ) 15:09:55,622 ERROR [STDERR] org.jboss.tm.JBossTransactionRolledbackException: Unexpected Error java.lang.OutOfMemoryError ; CausedByException is: Unexpected Error java.lang.OutOfMemoryError ; nested exception is: javax.ejb.EJBException: Unexpected Error java.lang.OutOfMemoryError ; - nested throwable: (javax.ejb.EJBException: Unexpected Error java.lang.OutOfMemoryError ) 15:09:55,622 ERROR [STDERR] at org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:262) 15:09:55,622 ERROR [STDERR] at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195) 15:09:55,622 ERROR [STDERR] at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122) 15:09:55,622 ERROR [STDERR] at org.jboss.ejb.StatelessSessionContainer.internalInvoke(StatelessSessionContainer.java:331) 15:09:55,622 ERROR [STDERR] at org.jboss.ejb.Container.invoke(Container.java:700) 15:09:55,622 ERROR [STDERR] at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source) 15:09:55,632 ERROR [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 15:09:55,632 ERROR [STDERR] at java.lang.reflect.Method.invoke(Method.java:324) 15:09:55,632 ERROR [STDERR] at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284) 15:09:55,632 ERROR [STDERR] at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546) 15:09:55,632 ERROR [STDERR] at org.jboss.invocation.local.LocalInvoker.invoke(LocalInvoker.java:101) 15:09:55,632 ERROR [STDERR] at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:90) 15:09:55,632 ERROR [STDERR] at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46) 15:09:55,632 ERROR [STDERR] at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:45) 15:09:55,632 ERROR [STDERR] at org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:100) 15:09:55,632 ERROR [STDERR] at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:85) 15:09:55,632 ERROR [STDERR] at $Proxy106.newTicket(Unknown Source) 15:09:55,632 ERROR [STDERR] at org.jcallcenter.web.core.TicketTestServlet.doPost(TicketTestServlet.java:61) 15:09:55,632 ERROR [STDERR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) 15:09:55,632 ERROR [STDERR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) 15:09:55,632 ERROR [STDERR] at org.jboss.web.tomcat.security.JBossSecurityMgrRealm.invoke(JBossSecurityMgrRealm.java:220) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValve.java:246) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) 15:09:55,632 ERROR [STDERR] at org.jboss.web.tomcat.tc4.statistics.ContainerStatsValve.invoke(ContainerStatsValve.java:76) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2417) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) 15:09:55,632 ERROR [STDERR] at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) 15:09:56,202 ERROR [STDERR] at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:65) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:577) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) 15:09:56,202 ERROR [STDERR] at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) 15:09:56,202 ERROR [STDERR] at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:197) 15:09:56,202 ERROR [STDERR] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:781) 15:09:56,202 ERROR [STDERR] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:549) 15:09:56,202 ERROR [STDERR] at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:605) 15:09:56,202 ERROR [STDERR] at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:677) 15:09:56,202 ERROR [STDERR] at java.lang.Thread.run(Thread.java:534) 15:09:56,202 ERROR [STDERR] Caused by: javax.ejb.EJBException: Unexpected Error java.lang.OutOfMemoryError 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:182) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:98) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:92) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:120) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderInterceptor.java:93) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.EntityContainer.internalInvokeHome(EntityContainer.java:483) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.Container.invoke(Container.java:720) 15:09:56,202 ERROR [STDERR] at org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invokeHome(BaseLocalProxyFactory.java:293) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.plugins.local.LocalHomeProxy.invoke(LocalHomeProxy.java:110) 15:09:56,212 ERROR [STDERR] at $Proxy102.create(Unknown Source) 15:09:56,212 ERROR [STDERR] at org.jcallcenter.ejb.core.TicketFacadeBean.newTicket(TicketFacadeBean.java:76) 15:09:56,212 ERROR [STDERR] at sun.reflect.GeneratedMethodAccessor83.invoke(Unknown Source) 15:09:56,212 ERROR [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 15:09:56,212 ERROR [STDERR] at java.lang.reflect.Method.invoke(Method.java:324) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:683) 15:09:56,212 ERROR [STDERR] at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:72) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:84) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:128) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:118) 15:09:56,212 ERROR [STDERR] at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191) 15:09:56,212 ERROR [STDERR] ... 57 more
Well, when I run the servlet again, PKTicket re-initializes itself, pulls all the PKs from the datastore, and sets up it's TreeSet again. Then, the servlet starts creating tickets starting from 12821. When it reaches 25640, it throws another OutOfMemoryError.
Is this a limitation of TreeSet? Is there anyway to set the number of elements it should hold?
I don't see this being a problem in production, because PKTicket will most likely be re-initialized before the 12820 mark, but I'm just curious if anyone has seen this before?[/url]
*http://www.jboss.org/index.html?module=bb&op=viewtopic&t=50863