Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

Entries in chariot-news (45)

Saturday
Sep042010

Living on the Roo "edge" w/git

Yep, I'm officially a writer - look I even have over 40 reading glasses on!Writing a book against a moving target is, well, moving.  Sometimes I just need to work with the latest Roo from git, to see where it's going.  For a while, there were incompatibilities in the STS Roo shell support that kept me from doing this, but with a little fudging around, I figured out how to do it for the unreleased 1.1.0.M4 line.

These instructions assume you have a working roo-dev shell, and are able to mvn install and use GIT.  Once you follow the instructions, you'll potentially have a working STS install that works against the GIT build of Roo, so you can watch progress between builds.

Do you need this? Well, no, maybe not.  

I do, since what I'm writing a book on depends on a somewhat rapidly evolving framework.  Speaking of the book, we are releasing another MEAP soon that will add another chapter, and also fix a lot of the wording, typos and other issues from the first four chapters.  Look for that soon, and thanks to everyone who is reading those MEAPs and participating in the review process.  We truly value you!.

Steps

  • First, get the latest code by using git pull
  • Make sure it builds, using mvn install
  • Make an assembly of Roo - this creates a zip install that you can unzip so STS can see it.  Do it this way:  mvn assembly:assembly
  • Take the file it creates in ./target/org.springframework.roo.root-1.1.0.M4.zip and move it somewhere, unzip it.  You now have a spring-roo-1.1.0.M4 directory with a distribution of the GIT code head.  YAY!
  • Decide whether you want to use this version on the command line as your regular roo.  I don't, I still use roo-dev.  
  • In STS, make sure you're using an external maven build - go to STS -> Preferences, search for Maven, add an external installation for 2.2.1 (which you've downloaded by now, I hope)
  • Also in STS, go to STS -> Preferences, search for Roo, and add this new 1.1.0.M4 roo installation, making it the default (don't forget to switch back if you don't like what you see).
  • Open your 1.1.0.M4 project, and if it doesn't automatically configure as a Roo project, just add Roo project nature and if you're still getting trouble, add the AspectJ Tooling feature too (from the Spring right-click project menu).

Sorry this is jotted down so hastily.  This is more of a note for me than everyone else, but I figured others could benefit.

One other note - if you somehow had a custom maven repo that you configured, check your Maven settings carefully.  I had to make sure my Maven install was correct.  Also, if you forget to mvn install the Roo dev build, it won't install the JAR files into your repository and you won't be able to build your projects.  

Enjoy!

 

Sunday
Aug292010

Spring JUnit Tests not Rolling Back? It may not be you...

Plug/Disclaimer! I'm teaching a Hibernate with Spring course in September, and while preparing for the course I came up with this tidbit. I hope you enjoy it.

Here's a little tip for you Spring users who are using MySQL.  If you just installed MySQL with the defaults, you may find that Spring's @ContextConfiguration and @RunWith(SpringJUnit4Runner.class) annotations might not work for you.

import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.
       transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

@ContextConfiguration(locations=
   {"classpath:/META-INF/spring/applicationContext.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback=true)
public class CourseIntegrationTest {

  @Autowired
  private SessionFactory sessionFactory;
  
  
  @Test
  @Transactional
  public void testCreateCourse() {
    Session session = sessionFactory.getCurrentSession();
    Course course = new Course();
    course.setCost(new BigDecimal("1000.00"));
    course.setDescription("Basketweaving");
    course.setStartDate(new Date());
    
    session.save(course);
    
    // now, we get and check
    session.flush();
    
    Assert.assertNotNull(course.getId());   
    
  }
  
}

The Problem...

The default behavior of Spring when running integration tests like this is to roll back the transaction. So, you go ahead and execute the test, and hope that it rolls back the row. But, in fact, it might not - you might see the row in the database. Why?

The answer lies in whether you've installed and configured the InnoDB engine in MySQL. What is InnoDB? It's a transactional storage engine that ships with MySQL binaries as of 5.1 and higher. Here is a good wikipedia article on InnoDB for further reading. You can tell whether it is installed by executing the following SQL as the 'root' MySQL user: (I've removed the "comment" field so it fits on my blog page)


mysql> show engines;
+------------+---------+--------------+------+------------+
| Engine     | Support | Transactions | XA   | Savepoints |
+------------+---------+----------------------------------+
| CSV        | YES     | NO           | NO   | NO         |
| MRG_MYISAM | YES     | NO           | NO   | NO         |
| MEMORY     | YES     | NO           | NO   | NO         |
| MyISAM     | DEFAULT | NO           | NO   | NO         |
+------------+---------+--------------+------+------------+

In the case above, I haven't yet configured InnoDB - MyISAM is the default engine, which is also non-transactional. Since MySQL can have several installed engines, and one is the default, setting the wrong default (as well as not installing a transactional engine) can be a problem!

When you create tables, you can specify the engine they use, otherwise they get the default. I found a GREAT article about verifying your Spring JPA MySQL tables to make sure they use a transactional (InnoDB) data store. Since we're geeking out, you can also run this command in MySQL against your table to see what settings it has (many more columns come back than the ones I'm showing):

mysql> show table status;
+--------+--------+---------+------------+------+----------------+
| Name   | Engine | Version | Row_format | Rows | Avg_row_length |
+--------+--------+---------+------------+------+----------------+
| Course | MyISAM |      10 | Compact    |    1 |          16384 |
+--------+--------+---------+------------+------+----------------+

Run your JUnit Spring integration tests against a table with this engine, and you'll see that rollbacks are ignored, even though Spring shows that they are sent. Here is what Spring shows us when we run the test, which would lead you to believe that everything is ok, until you look at the data in the table:

Fetching JDBC Connection from DataSource
Returning JDBC Connection to DataSource
Creating new transaction with name [testCreateCourse]: 
  PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
Opened new Session ... for Hibernate transaction
Preparing JDBC Connection of Hibernate Session ...
Exposing Hibernate transaction as JDBC transaction 
   [jdbc:mysql://localhost:3306/hibernate_sandbox, 
   UserName=root@localhost, MySQL-AB JDBC Driver]
Hibernate: 
    insert 
    into
        Course
        (cost, description, startDate) 
    values
        (?, ?, ?)
binding '1000.00' to parameter: 1
binding 'Basketweaving' to parameter: 2
binding '29 August 2010' to parameter: 3
Triggering beforeCompletion synchronization
Initiating transaction rollback
Rolling back Hibernate transaction on Session ...
Triggering afterCompletion synchronization
Closing Hibernate Session ... after transaction
Closing Hibernate Session
Closing Hibernate SessionFactory

Incidentally, here is my log4j.properties file for getting all of that nice log output:

# suppress everything else
log4j.logger.org.springframework=error
log4j.logger.org.hibernate=error

# log field bindings
log4j.logger.org.hibernate.type=trace

# log transactions
log4j.logger.org.springframework.jdbc.datasource=trace
log4j.logger.org.springframework.orm.hibernate3=trace 

... and my Hibernate settings from within my AnnotationSessionFactoryBean...

<property name="hibernateProperties">
  <value>
    hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
    hibernate.hbm2ddl.auto=update
    hibernate.show_sql=true
    hibernate.format_sql=true
  </value>
</property>

Ok, so obviously for a serious application involving more than one SQL statement at a time, this is seriously inadequate. So, let's fix it!

Installing InnoDB

I'm using a Mac, so your mileage for these instructions will vary, and you'll have to have a passing familiarity with the command line. First, create a my.cnf file (or edit the existing one). Mine is located in /etc/my.cnf, but yours may live in /usr/local/mysql/data or in another place. I have added the following settings to my file, taken from a few blog entries:

[mysqld]
default-storage-engine=InnoDB
innodb_data_home_dir=/usr/local/mysql/data
innodb_data_file_path=ibdata-new:10M:autoextend
innodb_buffer_pool_size=256M
innodb_additional_mem_pool_size=20M
innodb_log_file_size=64M
innodb_log_buffer_size=8M
innodb_flush_log_at_trx_commit=1

Now, to install this file, you need to shutdown and start up MySQL. I use the following commands from OS X:

sudo mysqladmin shutdown
sudo mysqld_safe --console & 
sudo cat /usr/local/mysql/data/yourservername.err

Verifying the Installation

Now, to verify that everything is configured correctly, check the same

show engines
command again as the MySQL root user:

mysql> show engines;
+------------+---------+--------------+------+------------+
| Engine     | Support | Transactions | XA   | Savepoints |
+------------+---------+--------------+------+------------+
| CSV        | YES     | NO           | NO   | NO         |
| MRG_MYISAM | YES     | NO           | NO   | NO         |
| MEMORY     | YES     | NO           | NO   | NO         |
| InnoDB     | DEFAULT | YES          | YES  | YES        |
| MyISAM     | YES     | NO           | NO   | NO         |
+------------+---------+--------------+------+------------+
5 rows in set (0.01 sec)

If all is well, you now have InnoDB, and it's the default engine. Try the test, and see if the rows are rolled back. Important: you may have to drop or modify the table to make it use InnoDB. There is a simple SQL command to modify it:


mysql> alter table Course engine=InnoDB;
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0

If you get any warnings, just type

show warnings
and you'll get a message.

That's it. I hope this helps someone who is wrestling with MySQL databases and Hibernate transactions. I know I have had trouble with this when preparing the Hibernate section of my book, Roo in Action.

Friday
Mar262010

Calling PostgreSQL Stored Procedures from Grails - Optimized Service class

Here is a more-fully optimized Grails Service that creates and re-uses the thread-safe SqlFunction, StoredProcedure and JdbcTemplate classes. Note - I'm using a @PostConstruct annotation on an init() method. Yes, you can do that in Grails - it's just a Spring application. This makes it possible to pick up the automatically injected dataSource and wire it into the various objects that require it.

Enjoy.

package org.playball.service

import org.springframework.jdbc.object.SqlFunction
import org.springframework.jdbc.core.JdbcTemplate
import org.playball.db.StoredProcSubclass
import javax.annotation.PostConstruct
import java.sql.Types


class StoredProcedureRunnerService {

  boolean transactional = true
    
  def dataSource
  def template
  def spcaller
  def sqlFunction


  @PostConstruct 
  def init() {
      int [] params = new int[1];
      params[0]=java.sql.Types.INTEGER;

      template = new JdbcTemplate(dataSource)
      spcaller = new StoredProcSubclass(dataSource)
      sqlFunction = new SqlFunction(dataSource,
                      "select salesByBookId(?)", params)
      sqlFunction.compile()

  }

  // automatically set up by name (Spring injected) on startup
  def sumBookSalesByBookIdWithJdbcTemplate(def bookId) {
      template.queryForInt("select salesByBookId(?)", bookId)
  }

  // use Spring JDBC's StoredProcedure class (see bottom of this class for definition)
  def sumBookSalesByBookIdWithSPSubclass(int bookId) {
      def map = spcaller.execute(bookId, bookId)
      map['#result-set-1']['result'][0]
  }

  def sumBookSalesByBookIdSqlFunction(int bookId) {

      def result
      try {
        result = sqlFunction.run(bookId)
      } catch (org.springframework.dao.TypeMismatchDataAccessException e) {
        log.error "Result type cannot be inferred - no result so returning 0"
        0
      }
      result
  }

  def sumBookSalesByBookIdGSQL(int bookId) {
      def gsql = new groovy.sql.Sql(dataSource)
      def results = gsql.rows("select salesByBookId(${bookId})")
      results["salesbybookid"][0]
  }
}
Friday
Mar262010

Calling PostgreSQL Stored Procedures from Grails - Part 4 - Groovy SQL

Every time I say "Groovy SQL" I feel there should be an implied comma. Like, "Groovy, SQL!"

Groovy SQL is a simple API for calling SQL Statements in the vein of JdbcTemplate, but it's totally, um... Groovy. Here is the very tiny snippet of code to call our Stored Procedure with Groovy SQL:

  def sumBookSalesByBookIdGSQL(int bookId) {
    def gsql = new groovy.sql.Sql(dataSource)
    def results = gsql.rows("select salesByBookId(${bookId})")
    results["salesbybookid"][0]
  }

There. Isn't that, just, Groovy, SQL? The results returned seem to be a map of results, with each one having a list of values. I think for simple Stored Functions such as the one in Part 1, I say it's Groovy SQL FTW...

Friday
Mar262010

Calling PostgreSQL Stored Procedures from Grails - Part 3, SqlFunction

SqlFunction is another class that takes a stored function (which is our sample procedure in Part 1), and runs it. I've done a rather inefficient sample below. In reality, you should be using the constructor passing the input types, and using the version of run which allows you to pass parameters.

The SqlFunction section of our service

def sqlFunction = new SqlFunction(dataSource, "select salesByBookId(${bookId})")
    sqlFunction.compile()
    def result
    try {
      result = sqlFunction.run()
    } catch (org.springframework.dao.DataAccessException e) {
      log.error "Result type cannot be inferred - " +
                 " no result so returning 0"
      0
    }
    result

I should explain a few things about the code snippet:

  • The dataSource I auto-inject using def dataSource in the Grails Service
  • I return 0 if the key is wrong
  • The SqlFunction throws subclasses of DataAccessException when the call fails (if the row doesn't come back, for example. You could use TypeMismatchDataAccesException, which is a subclass of DataAccessException but I chose the wider exception in the hierarchy.
  • I'm using the nifty Grails log variable, which is wired into every Grails object automatically. You can control logging via the Config.groovy file in your grails-app directory.
  • Ideally, you should set up the SqlFunction instance and re-use it over and over again, as it is compiled. Again, this is more showing you the features, not best practices, as I'm just blogging this to put a little more information out there. I'll refactor this a bit later, if I get the chance...
Page 1 ... 4 5 6 7 8 ... 9 Next 5 Entries ยป