7 Replies Latest reply on Oct 8, 2015 7:06 AM by sridharthiyagarajan

    How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.

    sridharthiyagarajan

      Hello,

       

      I am migrating the EAR application from JBoss AS 6 to Wildfly AS 8.2.0. While doing, I am facing a concern on implementing EJB timer service in Wildfly AS for the datasource TestSybaseDB defined in standalone-full-ha.xml.

       

      FYI that below are the files related to JBoss AS 6 related to EJB3 timer service implementation for the datasource TestSybaseDB. In below files of JBoss 6 AS, datasource name is defined and I believe these changes are enough for implementation of EJB timer service in JBoss 6 AS for a database.

       

      persistence.xml

      path: ${JBOSS_HOME}\common\deploy\jboss-ejb3-timerservice-mk2.jar\META-INF\persistence.xml

      code: <jta-data-source>java:/TestSybaseDB</jta-data-source>

       

      ejb2-timer-service.xml

      path: ${JBOSS_HOME}\server\default\deploy\ejb2-timer-service.xml

      code: <depends>jboss.jdbc:datasource=TestSybaseDB,service=metadata</depends>

                <depends optional-attribute-name="DataSource">jboss.jca:service=DataSourceBinding,name=TestSybaseDB</depends>

       

      But to implement in Wildfly AS, I had converted the content of timer-sql.properties according to Sybase DB and it is attached in this discussion.

       

      timer-sql.properties

      path: ${JBOSS_HOME}\modules\system\layers\base\org\jboss\as\ejb3\main\timers\timer-sql.properties

      code: Available as attachment

       

      Timer service definition in standalone-full-ha.xml

      <timer-service thread-pool-name="timer" default-data-store="clustered-store">

          <data-stores>

              <database-data-store name="clustered-store" datasource-jndi-name="java:/TestSybaseDB" partition="timer"/>

          </data-stores>

      </timer-service>

       

      Below is the transaction isolation value defined in datasource definition.

      <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>

       

      I am getting the below error:

       

      Error

      ERROR [org.jboss.as.ejb3] (MSC service thread 1-2) JBAS014263: Cannot create table for timer persistence: com.sybase.jdbc4.jdbc.SybSQLException: There is already an object named 'JBOSS_EJB_TIMER' in the database.

      at com.sybase.jdbc4.tds.Tds.a(Unknown Source)

      at com.sybase.jdbc4.tds.Tds.nextResult(Unknown Source)

      at com.sybase.jdbc4.jdbc.ResultGetter.nextResult(Unknown Source)

      at com.sybase.jdbc4.jdbc.SybStatement.nextResult(Unknown Source)

      at com.sybase.jdbc4.jdbc.SybStatement.nextResult(Unknown Source)

      at com.sybase.jdbc4.jdbc.SybStatement.updateLoop(Unknown Source)

      at com.sybase.jdbc4.jdbc.SybStatement.executeUpdate(Unknown Source)

      at com.sybase.jdbc4.jdbc.SybStatement.executeUpdate(Unknown Source)

      at org.jboss.jca.adapters.jdbc.WrappedStatement.executeUpdate(WrappedStatement.java:375)

      at org.jboss.as.ejb3.timerservice.persistence.database.DatabaseTimerPersistence.runCreateTable(DatabaseTimerPersistence.java:150) [wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]

      at org.jboss.as.ejb3.timerservice.persistence.database.DatabaseTimerPersistence.start(DatabaseTimerPersistence.java:117) [wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]

      at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]

      at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]

      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_67]

      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_67]

      at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_67]

       

      From the above error, I thought create-table in timer-sql.properties is causing the problem and hence, I tried removing it but getting the below error.

       

      ERROR [org.jboss.msc.service.fail] (MSC service thread 1-8) MSC000001: Failed to start service jboss.ejb3.timerService.timerPersistence.clustered-store: org.jboss.msc.service.StartException in service jboss.ejb3.timerService.timerPersistence.clustered-store: Failed to start service

      at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]

      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_67]

      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_67]

      at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_67]

      Caused by: java.lang.NullPointerException

      at org.jboss.as.ejb3.timerservice.persistence.database.DatabaseTimerPersistence.runCreateTable(DatabaseTimerPersistence.java:146)

      at org.jboss.as.ejb3.timerservice.persistence.database.DatabaseTimerPersistence.start(DatabaseTimerPersistence.java:117)

      at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]

      at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]

      ... 3 more

       

      Could anyone please help me in resolving the error and configure EJB timer service for the datasource defined in Wildfly AS.

        • 1. Re: How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.
          lafr

          Took a look at https://github.com/wildfly/wildfly/blob/8.x/ejb3/src/main/java/org/jboss/as/ejb3/timerservice/persistence/database/DatabaseTimerPersistence.java.

          First the load-timer statement it executed. In case of any failure it's assumed, that the table does not exist. Then the create-table is executed.

          Does this table exist or not in your database? Is it visible to the user accessing the database and does this user have write access for database / table?

          I have no experience with Sybase. Does it use something like schemas / users, meaning the database table name should be prefixed by something?

          1 of 1 people found this helpful
          • 2. Re: How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.
            sridharthiyagarajan

            Many thanks for the response .. Frank. It could use see it is not loading the load-timer and hence, it is trying to create table again and as the table is already available, it is failing with the exception saying table already exixts.

             

            load-timer=SELECT ID, TIMED_OBJECT_ID, INITIAL_DATE, REPEAT_INTERVAL, NEXT_DATE, PREVIOUS_RUN, PRIMARY_KEY, INFO, TIMER_STATE, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE, SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_OF_WEEK, SCHEDULE_EXPR_DAY_OF_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_YEAR, SCHEDULE_EXPR_START_DATE, SCHEDULE_EXPR_END_DATE, SCHEDULE_EXPR_TIMEZONE, AUTO_TIMER, TIMEOUT_METHOD_NAME, TIMEOUT_METHOD_DECLARING_CLASS, TIMEOUT_METHOD_DESCRIPTOR, CALENDAR_TIMER FROM JBOSS_EJB_TIMER WHERE TIMED_OBJECT_ID=? and ID=? AND PARTITION_NAME=?;


            I don't know why it is failing when loading the timer. I ran a test main program to test the above query and it did not throw any exception with the same database credentials that is used in Wildfly. Database user all the permissions. I don't know the root cause for not loading the load timer I am stuck here.

            • 3. Re: How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.
              sridharthiyagarajan

              Adding more.. In the below method of DatabaseTimerPersistence you shared, the load-timer sql looks for a row with NON-EXISTENT but the table is empty.

               

              void runCreateTable() {

                      String loadTimer = sql(LOAD_TIMER);

                      Connection connection = null;

                      Statement statement = null;

                      PreparedStatement preparedStatement = null;

                      ResultSet resultSet = null;

                      try {

                          //test for the existence of the table by running the load timer query

                          connection = dataSource.getConnection();

                          preparedStatement = connection.prepareStatement(loadTimer);

                          preparedStatement.setString(1, "NON-EXISTENT");

                          preparedStatement.setString(2, "NON-EXISTENT");

                          preparedStatement.setString(3, "NON-EXISTENT");

                          resultSet = preparedStatement.executeQuery();

                      } catch (SQLException e) {

              • 4. Re: How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.
                lafr

                That's just for executing the SQL statement. It's not expected that a row will be found.

                A not found does not create an SQLException, I guess that's the same for Sybase.

                Can you pick these code lines exactly as they are there into a test program? Do you get an Exception or just an empty resultSet as expected?

                1 of 1 people found this helpful
                • 5. Re: How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.
                  sridharthiyagarajan

                  Many thanks for the response .. Frank. I am not getting any exception and found fetch size of resultset to be zero when I run the "load timer" sql in a separate test program. Only case for a failure is that table does not exist but it is existing and it tries to create a table. When I run the below query in sql client tool, it executes fine. This is a strange behavior and I dont know where I am missed.

                   

                  SELECT ID, TIMED_OBJECT_ID, INITIAL_DATE, REPEAT_INTERVAL, NEXT_DATE, PREVIOUS_RUN, PRIMARY_KEY, INFO, TIMER_STATE, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE, SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_OF_WEEK, SCHEDULE_EXPR_DAY_OF_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_YEAR, SCHEDULE_EXPR_START_DATE, SCHEDULE_EXPR_END_DATE, SCHEDULE_EXPR_TIMEZONE, AUTO_TIMER, TIMEOUT_METHOD_NAME, TIMEOUT_METHOD_DECLARING_CLASS, TIMEOUT_METHOD_DESCRIPTOR, CALENDAR_TIMER FROM JBOSS_EJB_TIMER WHERE TIMED_OBJECT_ID=? and ID=? AND PARTITION_NAME=?

                  • 6. Re: How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.
                    vsilvav

                    Your configuration seems good...

                    Consider that if you apply a patch to wildfly, the timer-sql.properties used changes the path;

                    Example, for wildfly 8.2.1 the right place of these properties is:

                    {wildfly}/modules/system/layers/base/.overlays/base-8.2.1.Final-patch/org/jboss/as/ejb3/main/timers

                     

                    Also, don't forget to set persistent in your @schedule configuration to true:

                    @Schedule (dayOfWeek = "*", hour = "*", minute = "*", second = "*/5", year="*", persistent = true)

                    1 of 1 people found this helpful
                    • 7. Re: How to implement EJB 3 timer service for datasource in Wildfly AS 8.2.0.
                      sridharthiyagarajan

                      many thanks for the response ..  vsilvav.