5

I am trying to connect my Grails application to a Firebird database.

I am using:

  • Grails 2.2.1
  • JDK 1.7
  • Firebird 2.5.2
  • Jaybird 2.2.2

So far, this is what I have done:

  • I downloaded Jaybird-2.2.2JDK_1.7.zip from http://www.firebirdsql.org/en/jdbc-driver/
  • I unzipped this file and copied jaybird-2.2.2.jar into my application's lib folder.
  • In BuildConfig.groovy, I added runtime "org.firebirdsql.jdbc:jaybird:2.2.2" to the dependencies section.
  • I edited DataSource.groovy as detailed below.

The dataSource section:

dataSource {
    pooled = false
    driverClassName = "org.firebirdsql.jdbc.FBDriver"
    dialect = "org.hibernate.dialect.FirebirdDialect"
    username = "SYSDBA"
    password = "masterkey"
}

The hibernate section:

hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = true
    cache.provider_class = 'org.firebirdsql.pool.FBSimpleDataSource'
}

(I have also had cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory and cache.provider_class = 'com.opensymphony.oscache.hibernate.OSCacheProvider' in the above section on separate occasions, but neither made any difference.)

When running my Grails app, startup fails with a huge error that boils down to the following message:

java.lang.IllegalStateException: Could not load JDBC driver class [org.firebirdsql.jdbc.FBDriver]

I have searched the web far and wide, but I cannot find an example of a working Grails/Firebird configuration anywhere. There is a fix floating around that involves copying minij2ee.jar, but that is for a different error message. Also, people have suggested emptying the .grails folder – I have tried this, to no avail.

Could someone please advise, how can I get Grails to work with Firebird?


Here is the whole exception, though it seems to repeat a couple of times during startup:

->> 303 | innerRun in java.util.concurrent.FutureTask$Sync
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   138 | run      in java.util.concurrent.FutureTask
|   886 | runTask  in java.util.concurrent.ThreadPoolExecutor$Worker
|   908 | run      in     ''
^   662 | run . .  in java.lang.Thread

Caused by BeanCreationException: Error creating bean with name 'sessionFactory':
 Cannot resolve reference to bean 'dataSource' while setting bean property 'data
Source'; nested exception is org.springframework.beans.factory.BeanCreationExcep
tion: Error creating bean with name 'dataSource': Cannot resolve reference to be
an 'dataSourceUnproxied' while setting constructor argument; nested exception is
 org.springframework.beans.factory.BeanCreationException: Error creating bean wi
th name 'dataSourceUnproxied': Error setting property values; nested exception i
s org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessE
xceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException:
Property 'driverClassName' threw exception; nested exception is java.lang.Illega
lStateException: Could not load JDBC driver class [org.firebirdsql.jdbc.FBDriver
]

Running --stacktrace with --verbose:

| Error Error running script --stacktrace --verbose: Cannot invoke method findAl
l() on null object
java.lang.NullPointerException: Cannot invoke method findAll() on null object
        at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:7
7)
        at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaC
lassSite.java:45)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSi
teArray.java:45)
        at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.j
ava:32)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSi
teArray.java:45)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMeta
MethodSite.java:55)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCa
llSite.java:116)
        at org.codehaus.groovy.grails.cli.ScriptNameResolver.resolvesTo(ScriptNa
meResolver.groovy:30)
        at org.codehaus.groovy.grails.cli.GrailsScriptRunner.getPotentialScripts
(GrailsScriptRunner.java:489)
        at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeScriptWithCa
ching(GrailsScriptRunner.java:429)
        at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeScriptWithCa
ching(GrailsScriptRunner.java:416)
        at org.codehaus.groovy.grails.cli.GrailsScriptRunner$executeScriptWithCa
ching.call(Unknown Source)
        at org.codehaus.groovy.grails.cli.interactive.InteractiveMode.parseAndEx
ecute(InteractiveMode.groovy:280)
        at org.codehaus.groovy.grails.cli.interactive.InteractiveMode$parseAndEx
ecute.callCurrent(Unknown Source)
        at org.codehaus.groovy.grails.cli.interactive.InteractiveMode.run(Intera
ctiveMode.groovy:133)
        at org.codehaus.groovy.grails.cli.interactive.InteractiveMode$run.call(U
nknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSi
teArray.java:45)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCa
llSite.java:108)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCa
llSite.java:112)
        at RunApp$_run_closure7_closure11.doCall(RunApp:127)
        at RunApp$_run_closure7_closure11.doCall(RunApp)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(Refl
ectiveInterceptor.java:1243)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:
90)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1082)
        at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1106)

        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:906)
        at groovy.lang.Closure.call(Closure.java:412)
        at groovy.lang.Closure.call(Closure.java:406)
        at groovy.lang.Closure.run(Closure.java:490)
        at java.lang.Thread.run(Thread.java:662)
| Error Error running script --stacktrace --verbose: Cannot invoke method findAl
l() on null object

Here is the repositories block from my BuildConfig.groovy file:

repositories {
    inherits true // Whether to inherit repository definitions from plugins

    grailsPlugins()
    grailsHome()
    grailsCentral()

    mavenLocal()
    mavenCentral()

    // uncomment these (or add new ones) to enable remote dependency resolution from public Maven repositories
    mavenRepo "http://snapshots.repository.codehaus.org"
    mavenRepo "http://repository.codehaus.org"
    mavenRepo "http://download.java.net/maven/2/"
    mavenRepo "http://repository.jboss.com/maven2/"
}
Stephan B
  • 837
  • 1
  • 16
  • 41
  • `cache.provider_class = 'org.firebirdsql.pool.FBSimpleDataSource'` is probably wrong as well, `FBSimpleDataSource` is not a cache provider. – Mark Rotteveel Mar 06 '13 at 12:46
  • Thanks. Any idea what the provider class should be instead? The other value I saw online is `com.opensymphony.oscache.hibernate.OSCacheProvider`, but I honestly have no idea if that is valid either. – Stephan B Mar 06 '13 at 12:54
  • Re cache provider, check the hibernate documentation; I believe it uses a default if you don't specify it. – Mark Rotteveel Mar 06 '13 at 12:59
  • Sorry about the FBDrive typo, that happened because I'm copying from the Windows console and I messed up (fixed it in my question body now). The driver string is definitely correct. As for the stacktrace, I'm afraid this is all I have... I am not sure how to tell if Jaybird is on the classpath, but I do see it in the `ivy-cache`, which suggests that it has been detected. – Stephan B Mar 06 '13 at 13:08
  • I don't know enough of grails to help you troubleshoot this, but given the error my guess is a classpath problem (either Jaybird isn't included at all, or you are missing the dependency in my answer) – Mark Rotteveel Mar 06 '13 at 13:31

1 Answers1

5

You are probably missing a required dependency of Jaybird. You need to include the connector-api-1.5.jar (in the lib folder of the Jaybird distribution) on the classpath. The alternative is to use jaybird-full-2.2.2.jar (which includes the classes of connector-api-1.5.jar).

EDIT

Out of some curiosity, I installed grails and gave it a go. I initially also got a similar error (using grails console) and the stacktrace showed me java.lang.NoClassDefFoundError: javax/resource/ResourceException. It looks like grails - contrary to the documentation - does not retrieve transitive dependencies (this was a wong, see EDIT 2).

After I explicitly added a runtime dependency on 'javax.resource:connector-api:1.5', eg:

dependencies {
    // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes e.g.

    // runtime 'mysql:mysql-connector-java:5.1.22'
    runtime 'org.firebirdsql.jdbc:jaybird-jdk17:2.2.2',
            'javax.resource:connector-api:1.5'
}

With this additional dependency it worked. As the connector-api is normally provided by an application server, it might be better to specify this one as provided instead (you might want to check with your actual deployment environment).

If you need support for retrieval of generated keys (or Gorm might need it), then I'd suggest you also add 'org.antlr:antlr-runtime:3.4' (as a runtime dependency).

EDIT 2

After some additional testing, it looks like first installing the downloaded jaybird libraries into lib, and then declaring a dependency will make ivy create a dependency on that local library instead of retrieving it from maven. After removing the jaybird library from the lib folder and removing the org.firebirdsql.jdbc folder from my Ivy cache it correctly downloaded it from Maven, including the connector-api dependency.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 1
    I just tried putting `connector-api-1.5.jar` in the lib folder along with `jaybird-2.2.2.jar`, but this didn't seem to make any difference. I also tried using `jaybird-full-2.2.2.jar` instead of the normal one, still no success. I will update my question with the full error... – Stephan B Mar 06 '13 at 12:44
  • I changed my dependencies to match yours, and deleted the jaybird stuff from my ivy-cache. I got a bunch of errors like `Server access Error: Connection reset url=http://grails.org/plugins/grails-jaybird-jdk17/tags/RELEASE_2_2_2/grails-jaybird-jdk17-2.2.2.jar`, so I manually copied `connector-api-1.5.jar` and `jaybird-jdk17-2.2.2.jar` into the lib folder. After clean, I still get original FBDriver error. – Stephan B Mar 08 '13 at 08:57
  • Is your project configured to also retrieve dependencies from Maven Central? – Mark Rotteveel Mar 08 '13 at 08:58
  • Yes. If I clear the ivy-cache directory and run, I get `Server access Error` for a couple of things, but in the end it says `Error Failed to resolve dependencies` and only lists `org.firebirdsql.jdbc:jaybird-jdk17:2.2.2` and `javax.resource:connector-api:1.5`. I have to copy the .jar files into lib to get past this step. – Stephan B Mar 08 '13 at 11:31
  • Make sure that the `repositories` block in `buildConfig.groovy` contains `mavenCentral()`. Have you tried `grails refresh-dependencies`? – Mark Rotteveel Mar 08 '13 at 11:34
  • I added my repositories block in the body of the question. As for refreshing dependencies, it seems I cannot execute _any_ Grails scripts without copying those jars. It fails while `Configuring classpath`. – Stephan B Mar 08 '13 at 12:04
  • Weird. Could you try removing the `runtime` dependencies, refreshing (and removing them from lib and the ivy cache) and then adding them back in? – Mark Rotteveel Mar 08 '13 at 12:06
  • All right, I did this, and now I am able to compile with the `runtime` dependencies added and an empty `lib` folder. Successfully executed `refresh-dependencies`, `clean` and `compile`, but when I `run-app` I'm still getting the same `Could not load JDBC driver class [org.firebirdsql.jdbc.FBDriver]` error. – Stephan B Mar 08 '13 at 12:32
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/25843/discussion-between-mark-rotteveel-and-stephan) – Mark Rotteveel Mar 08 '13 at 12:35
  • 1
    Solved. For some reason, `java -version` says I am running JDK 1.7 but my `JAVA_HOME` has been pointing to 1.6 all this time – I was using the wrong .jar for Jaybird all along. I still have issues with Maven, but those are a separate concern. Your guidance in getting the right configuration for my project was critical. _Baie dankie_! – Stephan B Mar 11 '13 at 11:36
  • @Stephan Good to hear; too bad that it didn't report an `UnsupportedClassVersionError` instead, that would have made it easier to identify the cause. – Mark Rotteveel Mar 12 '13 at 09:18