Announcement Announcement Module
Collapse
No announcement yet.
Quartz unit testing quandary Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Quartz unit testing quandary

    I am using Spring 1.1.3 and Quartz 1.4.5.

    I've gotten into quite a pickle.

    I run automated integration tests that, upon setup, create an empty database from scratch and populate it with some default data, and then upon teardown delete the database.

    I have recently added persistent Quartz scheduling to the mix, and as part of the test setup I create the empty Quartz tables.

    However, the database creation and setup happens AFTER the application context is loaded, (b/c the application context contains the DataSource information) but the org.springframework.scheduling.QuartzSchedulerFact oryBean tries to access the tables from within afterPropertiesSet(), which happens during application context creation, BEFORE I get a chance to create them! So I get this error:

    org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: Table 'db_test.qrtz_locks' doesn't exist [See nested exception: java.sql.SQLException: Table 'db_test.qrtz_locks' doesn't exist]]

    The applicable lines from the stack trace:

    at org.quartz.impl.StdSchedulerFactory.instantiate(St dSchedulerFactory.java:915)
    at org.quartz.impl.StdSchedulerFactory.getScheduler(S tdSchedulerFactory.java:1047)
    at org.springframework.scheduling.quartz.SchedulerFac toryBean.createScheduler(SchedulerFactoryBean.java :467)
    at org.springframework.scheduling.quartz.SchedulerFac toryBean.afterPropertiesSet(SchedulerFactoryBean.j ava:419)

    What I'd really like to do is be able to wire everything up before any JDBC calls are attempted, but the fact that they are embedded in afterPropertiesSet() seems to make that impossible.

    Is my only option to create my own copy of the SchedulerFactoryBean that behaves the way I want? I started to go down that path but it started to get hairy and I'm wondering if I'm missing somethign simple.

    Thanks much,
    Kevin

  • #2
    Kevin,

    Where in the tests do you create the ApplicationContext? Are you using Spring's integration test classes? I would guess the easiest solution it to simply start the ApplicationContext after creating your database tables - this may be difficult if you are using Spring's test classes.

    Rob

    Comment


    • #3
      Can you just use 3 tests, 1 to setup db, 1 to do Spring stuff, then 1 more to tear down db.

      You could run it as a suite so it runs in the correct order.

      Comment


      • #4
        Originally posted by robh
        Kevin,

        Where in the tests do you create the ApplicationContext? Are you using Spring's integration test classes? I would guess the easiest solution it to simply start the ApplicationContext after creating your database tables - this may be difficult if you are using Spring's test classes.

        Rob
        Rob,

        Thanks for the response.

        Creating the ApplicationContext is the very first thing done, it is done in the constructor of the abstract TestCase class that is the superclass of all the integration test cases.

        I am not using Spring's integration test classes, just JUnit. I didn't know Spring had such a thing; do you think it would help in this case?

        I agree that creating the database tables before loading the ApplicationContext would work, but, being a good Spring user, all my DataSource info (jdbc url, username, password) that I would need to create the tables is defined in the context files themselves!

        A couple more ideas occurred to me today that I plan to try.

        One is creating a basic AppContext with the DataSource only, that lets me create the quartz tables, then loading another AppContext that has the whole thing wired together including the quartz scheduler. I'm assuming Spring will let me create two AppContexts in succession.

        The other idea is to create my own InitializingBean that gets invoked BEFORE the SchedulerFactoryBean, which creates the Quartz tables in its afterPropertiesSet() method, which would hopefully happen before the SchedulerFactoryBean attempts to access them.

        I'll post back if either of these strategies works.

        Comment


        • #5
          Found a solution

          My first idea worked nicely. Creating a small AppContext first, with just the DataSource defined, so that I can generate the Quartz tables, then proceeding with the full AppContext, that includes the Quartz SchedulerFactoryBean. Thanks to all.

          Comment


          • #6
            Originally posted by gmatthews
            Can you just use 3 tests, 1 to setup db, 1 to do Spring stuff, then 1 more to tear down db.

            You could run it as a suite so it runs in the correct order.
            NOOOOOooooo JUnit makes no guarantees that tests will run in a sensible order. Each test *must* be isolated from each other

            Comment

            Working...
            X