1

I'm trying to deploy my Spring MVC webapp (Hibernate and JPA) to a Tomcat 7 ClickStack in Cloudbees, but cannot seem to configure the database connection properly. I've tried following multiple tutorials (which offer many solutions), none of which have worked. If someone could take a look at my config files below and let me know if they see anything wrong it would be greatly appreciated.

The error:

java.lang.NullPointerException
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null' 

First, I bound my database to my app using the cloudbees cli so that I don't have to declare it in cloudbees-web.xml:

bees app:bind -a myapp/app -db mydatabase
    application - myapp/app bound to cb-db:myapp/mydatabase as mydatabase

(I have also tried unbinding the database and defining it in cloudbees-web.xml and also in context.xml without success)

spring-data.xml:

<jee:jndi-lookup id="datasource" jndi-name="jdbc/mydatabase"
                 lookup-on-startup="false" proxy-interface="javax.sql.DataSource"
                 cache="true" resource-ref="true"  />

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="hibernate-jpa"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
            <property name="showSql" value="false"/>
            <property name="generateDdl" value="true"/>
        </bean>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    </property>
</bean>

web.xml:

<resource-ref>
    <res-ref-name>jdbc/mydatabase</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

I have removed all references to connectors from my Maven files and all jars from the lib folder. Searching for the error message shows that it usually has to do with the driver not being found... but since the database is supplied by the container, why do I have to worry about that?

-- EDIT: Working META-INF/context.xml file --

Note that the com.cloudbees.jdbc.Driver referenced in a lot of the docs didn't work (threw a classnotfound exception), so I had to package the mysql-connector-java.jar file in the lib folder. Also, for now I just hardcoded the url, username, and password instead of setting it up to use the system properties.

<Context>
<Loader delegate="true"/>
<Resource
        name="jdbc/mydatabase"
        auth="Container"
        type="javax.sql.DataSource"
        maxActive="5"
        maxIdle="2"
        username="USERNAME"
        maxWait="5000"
        driverClassName="com.mysql.jdbc.Driver"
        password="PASSWORD"
        url="jdbc:mysql://MY_EC2_DB_URL:3306/mydatabase"/>
</Context>
Andy Miller
  • 849
  • 1
  • 9
  • 21

2 Answers2

1

I was facing the same issue and finally managed to "properly" configure the datasource !

I'm using a PropertyPlaceholderConfigurer as follows :

<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
   <property name="showSql" value="false" />
   <property name="database" value="MYSQL" />
   <property name="generateDdl" value="false" />
</bean>

<context:property-placeholder system-properties-mode="FALLBACK" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName" value="${dt4j.driver}" />
   <property name="url" value="${dt4j.url}" />
   <property name="username" value="${dt4j.username}" />
   <property name="password" value="${dt4j.password}" />
</bean>

"FALLBACK" indicates placeholders should be resolved against any local properties and then against system properties.

Finally, I just need to add system properties (-Dprop=value) or add them in the Cloudbees deployer plugin to make it work. There must be a better way but the main goal is achieved : the data source configuration is not hardcoded in the project !

tduchateau
  • 4,351
  • 2
  • 29
  • 40
0

Unfortunately at this point in time, the JNDI DB setup is not done for you in the tomcat7 stack.

When you bind the database to your app - it injects some system properties:

MYSQL_PASSWORD_MYDB 
MYSQL_URL_MYDB
MYSQL_USERNAME_MYDB

(MYDB as it is the name of your db resource). You can then refer to them in your code/config. For tomcat 7, you can put in /META-INF/context.xml into your app which will set up the JNDI data source (see http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html)

Michael Neale
  • 19,248
  • 19
  • 77
  • 109
  • Thanks, setting it up in the context.xml worked (although I couldn't find a reference to how to put system properties into the file). For anyone reading this in the future, I added my context.xml resource configuration to the ticket. – Andy Miller Nov 29 '12 at 01:14
  • great andy - I am not sure if tomcat supports system properties in the context - I suspect they do (http://stackoverflow.com/questions/372686/how-can-i-specify-system-properties-in-tomcat-configuration-on-startup - does that make any sense). – Michael Neale Nov 30 '12 at 00:35
  • Hi ! Is there any news about the JNDI DB setup for the Tomcat7 stack ? Thanks ! – tduchateau Jan 30 '13 at 16:01