Skip to main content

timerpool on cluster

7 replies [Last post]
peppeme
Offline
Joined: 2007-05-30

I try to deploy an application in a cluster.

The application use the @Resource TimerService

So, when I start It by calling the servlet that calls the session bean with TimerService I get an exception..

"javax.ejb.EJBException: nested exception is: javax.ejb.CreateException: Could not create stateless EJB javax.ejb.EJBException"

Caused by: java.lang.IllegalStateException: EJB Timer Service not available at com.sun.ejb.containers.ContainerFactoryImpl.getEJBContextObject(ContainerFactoryImpl.java:445) at .."

I think the problem is on jdbc resource jdbc/__TimerPool.
I try to change the resource target in order to enable it in the cluster but it tell me:

"Creation or deletion of the system resource reference jdbc/__TimerPool is not allowed"

So I create a new jdbc/resource called jdbc/__TimerPool_CLUSTER that have __TimerPool connection pool. it make right!

How can I tell in my code that the session bean must use jdbc/__TimerPool_CLUSTER?

I try to add mappedBy in resource annotaion:

@Resource(mappedName="jdbc/__TimerPool_CLUSTER")
TimerService timerService;

but it doesn't work!
help please

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ksak
Offline
Joined: 2005-05-20

In the cluster case the entire cluster must share the same database so you can't use the default embedded one. You'll first need to create the timer table in the database of your choosing. You can find the appropriate .sql scripts for each database in $GLASSFISH_HOME/lib/install/databases.

Then create a connection pool that points to your timer database. Then create a jdbc resource that points to your connection pool. Finally, set the Timer Datasource attribute via the admin console to point to your jbdc resource. There's no need to set mappedName on @Resource itself.

http://docs.sun.com/source/819-0215/containers.html#wp1023179

peppeme
Offline
Joined: 2007-05-30

It works!

But I discover a problem:
I try to explain.

My EAR refers to a jdbc resoruce (for mysql connection pool to DB1) called RES1.

So, First, In order to resolve the timer problem I think to make a new jdbc resource calling it TIMER_RES (this resource is connected with a new connection pool(mysql connection pool to TIMER_DB (a new database with only the timer table: ejb__timer__tbl)

When I ran the application I got different exception:

1) Unexpected exception in resource pooling java.lang.IllegalStateException: Local transaction already has 1 non-XA Resource: cannot add more resources.

2) poolmgr.err_enlisting_res_in_getconn

3) Failed to obtain/create connection from connection pool [ mysqlPool ]. Reason : java.lang.IllegalStateException: Local transaction already has 1 non-XA Resource: cannot add more resources.

4) Error allocating connection : [Error in allocating a connection. Cause: java.lang.IllegalStateException: Local transaction already has 1 non-XA Resource: cannot add more resources. ]

I try to change the pool datasource in xa-datsource but it doesn't work.

I solve by use only the first jdbc resoruce (RES1) by put inside the database DB1 the timer table.

This solution in my opinion is not clean, how can I make 2 different resources ones for applications and one for timer?!

ksak
Offline
Joined: 2005-05-20

You'll need to use an XA-capable JDBC driver when configuring the connection pool for your timer database. Since you're performing timer operations and updating an application database within a single transaction, the underlying transaction manager needs to coordinate those pieces of work using the XA protocol to ensure ACID properties.

peppeme
Offline
Joined: 2007-05-30

So Is not sufficient to change connection pool Resource Type, I must change the Datasource classname by setting a value that represent a class that implement javax.sql.XADataSource.

I'm using Mysql Connector J 5.1 jdbc driver.
It seems XA capable but I can't find the class name to set in pool configuration.

Do you know about this?!

Thanks for support!

ksak
Offline
Joined: 2005-05-20

Here's the docs entry on the MySQL XA driver :

https://glassfish.dev.java.net/javaee5/docs/AG/ablih.html#gbsor

The datasource class name is listed as com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
You should use that and change the res-type to javax.sql.XADataSource

peppeme
Offline
Joined: 2007-05-30

the XA datasource work but I encounter new problem:

When I start the instance (the only one in the cluster), there's a problem in timer service initialization.
In server.log appear

INFO: Exception thrown from bean; nested exception is: java.lang.IllegalArgumentException: null source jav... (details)
WARNING Unable to initialize EJB Timer Service. The likely cause is the database has not been started or the... (details)
WARNING Unable to initialize EJB Timer Service. The likely cause is the database has not been started or the... (details)

details about last exception:

> Unable to initialize EJB Timer Service. The likely cause is the database has not been started or the timer database table has not been created.
> javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean; nested exception is: java.lang.IllegalArgumentException:
> null source java.lang.IllegalArgumentException:
> null source at java.util.EventObject.(EventObject.java:38) at javax.sql.StatementEvent.(StatementEvent.java:39)
> at com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper.close(JDBC4PreparedStatementWrapper.java:70)
> at com.sun.jdo.spi.persistence.support.sqlstore.sql.generator.DBStatement.close(DBStatement.java:185)
> at com.sun.jdo.spi.persistence.support.sqlstore.SQLStoreManager.close(SQLStoreManager.java:685)
> at com.sun.jdo.spi.persistence.support.sqlstore.SQLStoreManager.executeQuery(SQLStoreManager.java:482)
> at com.sun.jdo.spi.persistence.support.sqlstore.SQLStoreManager.retrieve(SQLStoreManager.java:376)
> at com.sun.jdo.spi.persistence.support.sqlstore.impl.PersistenceManagerImpl.retrieve(PersistenceManagerImpl.java:1118)
> at com.sun.jdo.spi.persistence.support.sqlstore.query.QueryImpl.doExecute(QueryImpl.java:689)
> at com.sun.jdo.spi.persistence.support.sqlstore.query.QueryImpl.executeWithArray(QueryImpl.java:607)
> at com.sun.ejb.containers.TimerBean_2100919770_ConcreteImpl.ejbSelectAllTimersByOwnerAndState(TimerBean_2100919770_ConcreteImpl.java:1700)
> at com.sun.ejb.containers.TimerBean.ejbHomeSelectAllActiveTimersOwnedByThisServer(TimerBean.java:709)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1067)
> at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:176)
> at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2895)
> at com.sun.ejb.containers.EJBLocalHomeInvocationHandler.invoke(EJBLocalHomeInvocationHandler.java:242)
> at $Proxy10.selectAllActiveTimersOwnedByThisServer(Unknown Source)
> at com.sun.ejb.containers.EJBTimerService.restoreTimers(EJBTimerService.java:491)
> at com.sun.ejb.containers.ContainerFactoryImpl.restoreEJBTimers(ContainerFactoryImpl.java:364)
> at com.sun.enterprise.server.ApplicationLifecycle.onReady(ApplicationLifecycle.java:348)
> at com.sun.enterprise.server.ApplicationServer.onReady(ApplicationServer.java:526)
> at com.sun.enterprise.server.PEMain.run(PEMain.java:413)
....

Timer database (mysql) was started and the table is created (but empty).

About restarting the timer I see in mysql query log that the follow query is launched:

select distinct t0.`TIMERID`, t0.`CREATIONTIMERAW`, t0.`LASTEXPIRATIONRAW`, t0.`CONTAINERID`, t0.`OWNERID`, t0.`STATE`, t0.`PKHASHCODE`, t0.`INTERVALDURATION`, t0.`INITIALEXPIRATIONRAW` from `EJB__TIMER__TBL` t0 where t0.`OWNERID` = 'instanceDAS' and t0.`STATE` = 0;

So, I think again about empty timer table problem.
Is there a way to reset it?

Maybe the timer restarting problem is due to empty table! (perhaps!)
If I undeploy and deploy the timer application exceptions arise:

Exception creating stateless session bean : [{0}] com.sun.enterprise.InjectionException:

> Exception attempting to inject Env-Prop: session.BillWsBean/timerService@Field-Injectable Resource.
> Class name = session.BillWsBean Field name=timerService@java.lang.String@session.BillWsBean/timerService@@
> into class session.BillWsBean at com.sun.enterprise.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:387)
> at com.sun.enterprise.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:206)
> at com.sun.enterprise.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
> at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:533)
> at com.sun.ejb.containers.StatelessSessionContainer.access$100(StatelessSessionContainer.java:111)
> at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:772)
> at com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:199)
> at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:486)
> at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:1675)
> at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1229)
> at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:195)
> at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:127)
> at $Proxy65.initBilling(Unknown Source) at servlet.billPop.processRequest(billPop.java:68)
> at servlet.billPop.doGet(billPop.java:238) at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
....
> Caused by: javax.naming.NameNotFoundException:
> No object bound for java:comp/env/session.BillWsBean/timerService
> [Root exception is java.lang.IllegalStateException: EJB Timer Service not available]
> at com.sun.enterprise.naming.java.javaURLContext.lookup(javaURLContext.java:224)
> at com.sun.enterprise.naming.SerialContext.lookup(SerialContext.java:396)
> at javax.naming.InitialContext.lookup(InitialContext.java:392)
> at com.sun.enterprise.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:287) ... 42
> more Caused by: java.lang.IllegalStateException: EJB Timer Service not available
> at com.sun.ejb.containers.ContainerFactoryImpl.getEJBContextObject(ContainerFactoryImpl.java:854)
> at com.sun.enterprise.naming.NamingManagerImpl.lookup(NamingManagerImpl.java:965)
> at com.sun.enterprise.naming.java.javaURLContext.lookup(javaURLContext.java:173) ... 45 more

Exception creating stateless session bean : [{0}] com.sun.enterprise.InjectionException:

> Exception attempting to inject Env-Prop: session.BillWsBean/timerService@Field-Injectable Resource.
> Class name = session.BillWsBean Field name=timerService@java.lang.String@session.BillWsBean/timerService@@
> into class session.BillWsBean at com.sun.enterprise.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:387)
..

peppeme
Offline
Joined: 2007-05-30

I solve the problem.
the problem is due to
http://bugs.mysql.com/bug.php?id=35489

In the last post, I report this exception:

INFO: Exception thrown from bean; nested exception is: java.lang.IllegalArgumentException: null source jav...

Caused by: java.lang.IllegalArgumentException: null source
at java.util.EventObject.(EventObject.java:38)
at javax.sql.StatementEvent.(StatementEvent.java:39)
at
com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper.close(JDBC4PreparedStatementWr
apper.java:70)
at com.caucho.sql.UserStatement.close(UserStatement.java:127)
at com.caucho.sql.UserPreparedStatement.close(UserPreparedStatement.java:450)
at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:534)

By using a nightly build of mysql connector j the problem is solved.