Announcement Announcement Module
Collapse
No announcement yet.
Getting Roo to play nice with MySQL and Maven Tomcat Plugin Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting Roo to play nice with MySQL and Maven Tomcat Plugin

    I spent some time trying to get Roo to work with both MySQL and the Maven Tomcat plugin in such a way that I could do integration tests from Eclipse and deploy to Tomcat and use JNDI from the maven tomcat plugin.

    This posting is really more about how to use the Maven Tomcat plugin, it just so happens that I ran across this whilst using Roo. It also has some information on how to use Spring 3 SPeL to help you out.

    The Roo tutorial seems a bit terse when it comes to these topics, which is a shame. I think Roo would be more useful if Roo helped setup the Maven Tomcat plugin and tried to configure the JDBC bits (like context.xml).

    Perhaps this will help document the problem and at least one possible solution. I really think Roo should configure the Maven plugin for you. (I know... It is open source, I looked into what this would take... It seems straight forward, Roo is a darn clean code base).

    I used Roo to setup MySQL (see guide) and then I tried to run mvn tomcat:run. It failed. Then I spent some time trying to figure out how to best configure the Maven Tomcat plugin and without breaking integration tests that I wrote.

    Along the way, I learned quite a bit about the maven tomcat plugin, Roo and Spring 3. I figured I would share this with like minded folks on my team and beyond.

    Here is what I came up for the pom.ml.

    Roo added the following to pom.xml:

    Code:
      
    		<dependency>
    			<groupId>com.mysql.jdbc</groupId>
    			<artifactId>com.springsource.com.mysql.jdbc</artifactId>
    			<version>5.1.6</version>
    		</dependency>

    Roo also added a tomcat plugin. The problem is that I need a context.xml file for tomcat so I can setup my JNDI datasource.

    I reconfigured the tomcat plugin as follows in pom.xml:
    Code:
    			<plugin>
    
    				<groupId>org.codehaus.mojo</groupId>
    
    				<artifactId>tomcat-maven-plugin</artifactId>
    
    				<version>1.0-beta-1</version>
    
    				<configuration>
    
    					<configurationDir>tomcat</configurationDir>
    
    
    				</configuration>
    
    				<dependencies>		
    
    					<dependency>
    
    						<groupId>com.mysql.jdbc</groupId>
    
    						<artifactId>com.springsource.com.mysql.jdbc</artifactId>
    
    						<version>5.1.6</version>
    
    					</dependency>
    
    				</dependencies>
    
    			</plugin>
    Notice that I add mysql jar file to the list of dependencies for the plugin so that Tomcat can find mysql and I can avoid the dreaded Class not found exception for the MySQL driver.

    By the way, I tried many things before getting to this point. This is just the first one that worked. I am sure there are other ways, and even possibly better ways. I got the above through trial and error and reading the maven tomcat plugin documents (sparse) and the tomcat manual.


    Also notice that I have a tomcat property set. This tomcat folder will be under the project root directory, ${project.dir}/tomcat. This was the key for adding the JNDI datasource to my database.

    In the ${project.dir}/tomcat dir I have a conf directory. The conf directory has the following files:

    Code:
    $ pwd
    /Users/rickhightower/proto/application-catalog/tomcat/conf
    
    $ ls
    context.xml  tomcat-users.xml web.xml
    The tomcat-users.xml and web.xml were generated by the tomcat plugin under /target/tomcat. I just copied them here.

    The context.xml is where I set up the JDBC as follows:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    
        <WatchedResource>WEB-INF/web.xml</WatchedResource>
    	
       <Resource name="jdbc/mydb" auth="Container"
              type="javax.sql.DataSource"
              driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/mydb?autoReconnect=true"
              username="mydb" password="mydb"
              maxActive="20" maxIdle="10" maxWait="-1" />
    
    </Context>
    (Now would be a good time to add the applicationContext.xml file to the watched resources (note to self)).

    Notice that I have configured the Resource for my database.

    In my application context file, I just add the following:

    Code:
     	<jee:jndi-lookup id="dataSourceJNDI" jndi-name="jdbc/mydb" 
    	   lookup-on-startup="false" proxy-interface="javax.sql.DataSource"/>
    The problem is that now my code is somewhat tied to running in a container which is exactly what I don't want. I want to be able to run this application context without change in my integration tests.

    I want to use this dataSource when I am testing and such.

    Code:
     	<bean id="dataSourceDBCP" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      		<property name="driverClassName" value="${database.driverClassName}" />
      		<property name="url" value="${database.url}" />
      		<property name="username" value="${database.username}" />
      		<property name="password" value="${database.password}" />
    	</bean>
    To achieve this in Spring 3, I can use SPeL (Spring Expression Language) as follows:

    Code:
        <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
            <property name="dataSource" 
              ref="#{ systemProperties['ac.testing']=='yes' or systemProperties['ac.development']=='yes' ? 'dataSourceDBCP' : 'dataSourceJNDI'}"/>
        </bean>
    The above basically states that if ac.testing or ac.development system properties are set to yes then use dataSourceDBCP otherwise use dataSourceJNDI.

    I like SPeL.

    Then to run with dataSourceDBCP instead of dataSourceJNDI (for whatever reason), you can pass a system environment variable as follows:

    Code:
    $ mvn tomcat:run -Dac.testing="yes"
    You could setup a maven profile or something some such so that you don't ever have to pass this whilst running this from maven.

    You can also pass it as a parameter to the maven surefire plugin (the one that does testing):

    Code:
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-surefire-plugin</artifactId>
    				<version>2.4.3</version>
    				<configuration>
    					<junitArtifactName>org.junit:com.springsource.org.junit</junitArtifactName>
    					<excludes>
    						<exclude>**/*_Roo_*</exclude>
    					</excludes>
    					<systemProperties>
    						<property>
    							<name>ac.testing</name>
    							<value>yes</value>
    						</property>
    					</systemProperties>
    				</configuration>
    			</plugin>

    --
    Rick Hightower
    http://www.google.com/profiles/RichardHightower
    Last edited by RickHigh; Mar 29th, 2010, 02:39 PM.

  • #2
    Thanks for sharing this, Rick.

    Cheers
    Ben

    Comment


    • #3
      Rick-

      Great information Rick. Thanks.

      Is it possible to use that same trick with the ternary operator and JNDI to build up a <contextroperty-placeholder/>? I've been struggling with that and posted a fairly complete description of the problem here, but have not been able to figure it out.

      http://forum.springsource.org/showth...cat&highlight=

      Thanks,
      Josh

      Comment

      Working...
      X