<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;A0ENSHo7eSp7ImA9WhBaEUU.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670</id><updated>2013-05-21T21:28:19.401-05:00</updated><category term="jnlp code signing certificates zipfile" /><category term="pci pa/dss hints tips audit" /><category term="scala" /><category term="Book review SQL Antipatterns" /><category term="shutterfly holiday cards" /><category term="java7 jar signing" /><category term="java" /><category term="clojure" /><category term="grails groovy databinding" /><category term="Groovy HTTPBuilder RESTClient" /><category term="Groovy html MarkupBuilder" /><category term="JMS ExceptionListener Java" /><category term="Book review Gradle Groovy" /><category term="concurrency" /><category term="GDK Groovy" /><category term="Groovy" /><category term="Grails Groovy Spring databinding" /><category term="MongoDB" /><category term="Gradle groovy nonversioned jars" /><category term="Groovy sockets serversocket client" /><category term="Grails AJAX groovy" /><category term="Groovy CliBuilder ConfigSlurper" /><category term="book review" /><category term="webstart web start jnlp javaws_vm_args" /><category term="java swing auto-completion jtextfield" /><category term="blogger template" /><category term="Groovy gotcha databasemetadata array initialization" /><category term="JBoss AS7 JNDI EJB3.1" /><category term="Groovy GString SQL" /><category term="Groovy Binding script" /><category term="Ant" /><category term="initial" /><category term="Web Start JNLP code signing certificates Groovy" /><category term="Groovy Java Ant Validator" /><category term="Groovy grails upgrade" /><title>Scratching my programming itch</title><subtitle type="html">Hints and tips learned while scratching my programming itch.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://programmingitch.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ScratchingMyProgrammingItch" /><feedburner:info uri="scratchingmyprogrammingitch" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUQGQnwzfCp7ImA9WhBUE0o.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-8637119116303141735</id><published>2013-04-30T22:02:00.000-05:00</published><updated>2013-04-30T22:02:03.284-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T22:02:03.284-05:00</app:edited><title>Book Review: Gradle Effective Implementation Guide</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-RL0TbYu8xME/UYBqjVQGOlI/AAAAAAAAAjQ/_k7iWcqUkVM/s1600/gradlebook.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/-RL0TbYu8xME/UYBqjVQGOlI/AAAAAAAAAjQ/_k7iWcqUkVM/s320/gradlebook.jpg" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;Overview&lt;/b&gt;&lt;br /&gt;
The choice of build tools in the Java space has basically been Ant or Maven since the early days of Java. &amp;nbsp; Ant was the first tool to arrive and then Maven was created to help provide standardization, assuming you drank the Maven Kool-Aid, meaning that you could live with the standards set out by Maven.&lt;br /&gt;
&lt;br /&gt;
Now a new build tool has arrived, &lt;a href="http://www.gradle.org/" target="_blank"&gt;Gradle&lt;/a&gt;. &amp;nbsp;Gradle adoption started slowly at first, but has definitely been picking up momentum as &lt;a href="http://java.dzone.com/hibernate-users-learn-gradle" target="_blank"&gt;more&lt;/a&gt; and &lt;a href="http://java.dzone.com/hibernate-users-learn-gradle" target="_blank"&gt;more&lt;/a&gt; projects migrate from either Ant or Maven over to Gradle. Gradle can't be ignored!&lt;br /&gt;
&lt;br /&gt;
Gradle is built on top of the Groovy. &amp;nbsp;The tool provides a rich Domain Specific Language (DSL) based on Groovy. The DSL is the key component of Gradle.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Contents&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Starting with Gradle, creating and working with build scripts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Gradle for Java projects&lt;/li&gt;
&lt;li&gt;Dependency management&lt;/li&gt;
&lt;li&gt;Testing building and publishing artifacts&lt;/li&gt;
&lt;li&gt;Multi-project builds&lt;/li&gt;
&lt;li&gt;Gradle with Groovy and Scala&lt;/li&gt;
&lt;li&gt;Maintaining code quality with tools like Checkstyle, PMD, FindBugs, JDepend, CodeNarc and the Sonar plugin - one of my favorite chapters since I recommend using code static analysis tools for improving code quality&lt;/li&gt;
&lt;li&gt;Using Gradle with Continuous Integration - covers Jenkins, TeamCity and Bamboo&lt;/li&gt;
&lt;li&gt;IDE support - provides excellent coverage of Eclipse and IntelliJ IDEA support&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Pros&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Very good reference guide&lt;/li&gt;
&lt;li&gt;Sample source filled with a lot of complete examples&lt;/li&gt;
&lt;li&gt;It's by &lt;a href="http://mrhaki.blogspot.com/" target="_blank"&gt;Mr. Haki,&lt;/a&gt; creator of &lt;b&gt;Groovy Goodness,&lt;/b&gt; &lt;b&gt;Grails Goodness&lt;/b&gt; and of course, &lt;b&gt;Gradle Goodness&lt;/b&gt; blog postings!&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Cons&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;I started out running and verifying every example, but after submitting 6-7 errata for just the first chapter, I stopped running all of the examples and dropped back to just executing examples that peaked my interest.&lt;/li&gt;
&lt;li&gt;The book contains only a single reference to Ant and no discussion on Gradle's integration with Ant. &amp;nbsp;In all fairness, Ant integration is not listed in the bullet points on the back of the book that shows "What you will learn", but I think that is a mistake. &amp;nbsp;Readers are going to be coming from either Ant or Maven and will be looking for help in migrating to Gradle or for help on how to do things in Gradle that they are already doing in Ant or Maven.&lt;/li&gt;
&lt;li&gt;The book is 356 pages but a lot of pages are 'eaten up' by showing the output of all the example build scripts, &amp;nbsp;and screen shots from Chapter 11, Using Gradle with Continuous Integration and Chapter 12 IDE support.&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
The book is a very good reference for using Gradle and I would definitely recommend it for anyone interested in learning more about Gradle. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Gradle thoughts (not specific to the book)&lt;/b&gt;&lt;br /&gt;
This the &lt;a href="http://programmingitch.blogspot.com/2011/07/book-review-building-and-testing-with.html" target="_blank"&gt;second book&lt;/a&gt; I have read on Gradle. &amp;nbsp;I have read the User's Guide a couple times over the last two years in an attempt to get a firm grip on Gradle. &amp;nbsp;One of my challenges is that I don't get to use Gradle in my day job, just at night and on weekends. &amp;nbsp; This limited use seems to extend the learning curve, which I think for Gradle is larger/longer than other tools. &lt;br /&gt;
&lt;br /&gt;
"Convention over configuration" is great for reducing the amount of code in projects, BUT somewhere the user needs to know where the conventions are defined. &amp;nbsp; I think one of the keys to learning Gradle is to get a firm grasp on the &lt;a href="http://www.gradle.org/docs/current/dsl/index.html" target="_blank"&gt;Gradle DSL&lt;/a&gt;. &amp;nbsp;Without a grasp on the DSL, &amp;nbsp;a new Gradle user just keeps wondering "Where are these properties/methods coming from?"&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/UxAfcyT8b-M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/8637119116303141735/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2013/04/book-review-gradle-effective.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/8637119116303141735?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/8637119116303141735?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/UxAfcyT8b-M/book-review-gradle-effective.html" title="Book Review: Gradle Effective Implementation Guide" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-RL0TbYu8xME/UYBqjVQGOlI/AAAAAAAAAjQ/_k7iWcqUkVM/s72-c/gradlebook.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2013/04/book-review-gradle-effective.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUHRnkyeip7ImA9WhBSEk4.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-1271843004646586601</id><published>2013-02-18T19:43:00.003-06:00</published><updated>2013-02-18T19:43:57.792-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-18T19:43:57.792-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java7 jar signing" /><title>Minor Gotchas from migration to Java 7</title><content type="html">After several years of pushing, we are finally starting to pull our application out of the dark ages &amp;nbsp;in terms of software levels and one of those steps is upgrading our Java version to Java 7.  For the most part, this has been fairly painless, but there have been a couple surprises:
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Test cases that had been running successfully for years started failing when we switched to Java 7. &amp;nbsp;It turns out that we had some test cases that depended on previous test cases within the same class. &amp;nbsp;This is bad on two fronts, 1) the test cases should each be independent and 2) the execution order of test cases within a test class is not&amp;nbsp;guaranteed, although, up to now(before Java 7), the order was the order found in the source code. &lt;a href="http://intellijava.blogspot.com/2012/05/junit-and-java-7.html" target="_blank"&gt;&amp;nbsp;I found this link&lt;/a&gt; that helped explain the inconsistent ordering I was seeing within Eclipse. &amp;nbsp;This is not a problem with Java 7 but rather with our test cases. &amp;nbsp; Just &amp;nbsp;something that cropped up when we started running with Java 7&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Our Swing clients began throwing &lt;b&gt;ClassCastExceptions&lt;/b&gt;, and this is code that has been in place for over 10 years, dating back to Java 1.4 &amp;nbsp; Reading the javadocs helped explain the problem, but I decided to research a bit more to find out exactly why this was happening now. &amp;nbsp; We were &lt;a href="http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html#add(E)" target="_blank"&gt;adding entries to a TreeSet&lt;/a&gt;&amp;nbsp;to hold forward and backward traversal keys for the FocusManager, putting KeyStroke objects into the TreeSet. &amp;nbsp; The &lt;a href="http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html#add(E)" target="_blank"&gt;javadoc &lt;/a&gt;clearly states that the objects put in the TreeSet (or TreeMap underneath) must be Comparable or you need to create the TreeSet with a Comparator for ordering the objects. We were doing neither, &amp;nbsp;and not getting exceptions. &amp;nbsp;Digging into the java source code, &amp;nbsp;I found that starting in Java 7, the TreeMap class has starting enforcing this 'requirement', where the earlier versions of the class had that code commented out, thus not really requiring the comparator. &amp;nbsp; &amp;nbsp;The fix was easy, I created a KeyStrokeComparator and passed that to the TreeSet constructor.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;I also noticed that our java jar signing had started logging a warning about the certificate not being valid. &amp;nbsp; Wanting to keep the build clean and not have these warnings, I did some searches and found several postings related to Java 7 and the&lt;a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6948803" target="_blank"&gt; removal of the MD2withRSA&lt;/a&gt; algorithm from the code signing certificates. &amp;nbsp; I worked with support from Verisign to help with the removal of that algorithm from our certificate chain and the warning went away! &amp;nbsp;Unfortunately, that was not the end of the code signing problems. &amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Next, our web start clients would no longer start successfully, instead throwing an exception with the all-too-familiar &amp;nbsp;'&lt;b&gt;not all jars signed with the same certificate&lt;/b&gt;' error message frequently encountered by web start programs, at least during development! &amp;nbsp;I've written another &lt;a href="http://programmingitch.blogspot.com/2012/08/resolving-not-all-jars-signed-with-same.html" target="_blank"&gt;blog post&lt;/a&gt;&amp;nbsp;about how to help debug through this and figured it was just 'one of the usual suspect jars' that we have problems with, but nope, that wasn't it. &amp;nbsp; Knowing that all this happened since the certificate was updated caused me to review all of our signed jars to look for clues. &amp;nbsp; All the jars had been signed with the same certificate, but the 3rd party jars were signed BEFORE the chain entry was remove, whereas our application code was signed as part of the build process, AFTER the certificate was changed. &amp;nbsp; This led me to believe that even though the jars were signed with the same certificate, that there must be some difference between the jars signed before and after the change to the certificate. &amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;br /&gt;When jars are signed, &amp;nbsp;entries are generated in the MANIFEST.MF file inside the jar, one entry for each class in the jar. &amp;nbsp;These entries contain the name of the class along with some signing algorithm information and after reviewing the MANIFEST.MF files, &amp;nbsp;I found the difference. &amp;nbsp;The 3rd party jars signed before the change included a&lt;b&gt; SHA1-Digest&lt;/b&gt; entry for each class but our jars signed from the current build contained entries with &lt;b&gt;SHA-256-Digest.&lt;/b&gt; &amp;nbsp; Re-signing all of our 3rd party jars with the updated certificate resolved most of the problems. &amp;nbsp; We had a minor problem in our re-signing process, where we over-wrote the existing MANIFEST.MF with our own generated version and this caused problems for a couple of jars that contained additional service provider information in the manifest file.&lt;/ul&gt;
&lt;div&gt;
All in a days work! &amp;nbsp;Just Happy to be current on the Java level. &amp;nbsp;Next up, migrating to EJB3 and Hibernate 3 or 4.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Hope this helps!&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/tvHB931HdmQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/1271843004646586601/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2013/02/minor-gotchas-from-migration-to-java-7.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1271843004646586601?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1271843004646586601?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/tvHB931HdmQ/minor-gotchas-from-migration-to-java-7.html" title="Minor Gotchas from migration to Java 7" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2013/02/minor-gotchas-from-migration-to-java-7.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYGSX47fip7ImA9WhNXEkQ.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-245088340123600680</id><published>2012-11-29T23:19:00.000-06:00</published><updated>2012-11-30T11:55:28.006-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-30T11:55:28.006-06:00</app:edited><title>Grails &amp; EJB2, my stumbling points</title><content type="html">I have been 'playing' with Grails for a couple years now. &amp;nbsp;I say 'playing' because I don't get to use Grails for my day job. &amp;nbsp; My day job revolves around a Point-of-Sale (POS) and Back Office system with Web Start clients written using Swing and the server back-end uses EJB2.1 with Hibernate handling the persistence-layer. &amp;nbsp;Yeah, I know, nobody still uses EJB 2.1! &amp;nbsp;I have been pushing for some technical upgrades and hopefully that will happen this year, but that not want I want to talk about.&lt;br /&gt;
&lt;br /&gt;
In the past, when I wanted to create a small work-related Grails project, I took what I saw as the easier way out. &amp;nbsp;I used the static mappings in the domain object to map tables and columns to fields in the domain object, and this works fine. &amp;nbsp;Recently, I decided to re-visit one of my small projects with the intention of using Grails as the front-end and using the existing EJBs to get access to server data. &amp;nbsp;Below is a list of my stumbling points along the way to getting this project working. &amp;nbsp; Only one of the points is EJB2 related but the others are all valid for a lot of current projects.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;My stumbling points:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;resources.groovy bean definition&lt;/b&gt;: JndiObjectFactoryBean vs SimpleRemoteStatelessProxyFactoryBean&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LinkageError&lt;/b&gt;&amp;nbsp;- referencing javax.management.MBeanServer&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Compile errors after removing Hibernate&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;ol&gt;
&lt;/ol&gt;
&lt;li&gt;&lt;b&gt;BuildConfig.groovy&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;b&gt;resources.groovy bean definitions:&lt;/b&gt;&lt;br /&gt;
When I decided to use the existing EJBs within Grails, I did some google searches to find the correct format for defining these beans within the resources.groovy file. &amp;nbsp;I found some examples that worked great if you were using EJB 3.x. &amp;nbsp;If you are using EJB 3.x, you reference the &lt;b&gt;JndiObjectFactoryBean&lt;/b&gt; and this returns the remote service interface. &amp;nbsp;If your beans are actually EJB 2.1 and you use the JndiObjectFactory, you get back the 'home' interface, which has no business interface methods included. &amp;nbsp;Again, the problem is that I am using EJB 2.1. &amp;nbsp; Another couple google searches turned up Dave Klein's "&lt;a href="http://www.slideshare.net/daveklein/grails-integration-strategies#btnNext" target="_blank"&gt;Grails Integration Strategies"&lt;/a&gt; presentation and the answer was there on page 15. &amp;nbsp;For EJB 2.x, you need to use the &lt;b&gt;SimpleRemoteStatelessProxyFactoryBean&lt;/b&gt; in order to get the remote service interface. &amp;nbsp; Spring's SimpleRemoteStatelessProxyFactoryBean&amp;nbsp;handles retrieving the home interface, calling &amp;nbsp;PortableRemoteObject.narrow() and then calling create() in order to return a remote service interface for EJB 2.1.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;resources.groovy for EJB 2.x&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:plain"&gt;beans = {
    ejbJndi(org.springframework.jndi.JndiTemplate) {
        environment = [
            "java.naming.factory.initial" : "org.jnp.interfaces.NamingInitialContextFactory",
            "java.naming.provider.url" : "jnp://localhost:1099",
            "java.naming.security.principal" : "root",
            "java.naming.security.credentials" : "root"
        ]
    }
    environmentSvc(org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean) {
        jndiName = "ejb/EnvironmentService"
        businessInterface = "com.xxx.server.service.environment.EnvironmentService"
        jndiTemplate = ref("ejbJndi")
    }
    
}
&lt;/pre&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;b&gt;resources.groovy for EJB 3.x&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:plain"&gt;beans = {
    ejbJndi(org.springframework.jndi.JndiTemplate) {
        environment = [
            "java.naming.factory.initial" : "org.jnp.interfaces.NamingInitialContextFactory",
            "java.naming.provider.url" : "jnp://localhost:1099",
            "java.naming.security.principal" : "root",
            "java.naming.security.credentials" : "root"
        ]
    }
    processService(org.springframework.jndi.JndiObjectFactoryBean) {
    jndiName = "ejb/ProcessService"
    jndiTemplate = ref("ejbJndi")
    
}
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Linkage Error:&lt;/b&gt;&lt;br /&gt;
The next step was to compile and run the application, but I kept getting these 'Linkage Errors' shown below. Again, after sufficient google searches, I found a couple different postings with the same issue. &amp;nbsp; I am using JBoss as my application server and using the JBoss jars within Grails. &amp;nbsp;This problem appears to be a duplication of classes on the classpath between Tomcat and JBoss in the JMX area. According to the postings, there are (at least) two options:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;delete Tomcat and install Jetty, which I did and it worked great!&lt;/li&gt;
&lt;li&gt;deploy a war to Tomcat. &amp;nbsp;Apparently this problem only happens in the development environment and deploying your application as a war side steps this problem.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
Below is an example of the LinkageError&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:plain"&gt;c:\dev\groovy\hv&amp;gt;grails run-app
| Compiling 113 source files
Note: C:\Users\mmiller\.grails\2.1.0\projects\hv\plugins\cache-1.0.0\src\java\grails\plugin\cache\web\GenericResponseWrapper.java uses or oerrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
| Running Grails application
| Error Failed to initialize component [StandardServer[-1]] (NOTE: Stack trace has been filtered. Use --verbose to see entire trace.)
org.apache.catalina.LifecycleException: Failed to initialize component [StandardServer[-1]]
        at org.grails.plugins.tomcat.InlineExplodedTomcatServer.doStart(InlineExplodedTomcatServer.groovy:137)
        at org.grails.plugins.tomcat.TomcatServer.start(TomcatServer.groovy:102)
        at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:176)
        at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:153)
        at _GrailsRun_groovy.runInline(_GrailsRun_groovy:121)
        at _GrailsRun_groovy$_run_closure1.doCall(_GrailsRun_groovy:67)
        at RunApp$_run_closure1.doCall(RunApp.groovy:33)
Caused by: java.lang.LinkageError: loader constraint violation: loader (instance of &lt;bootloader&gt;) previously initiated loading for a differnt type with name "javax/management/MBeanServer"
        ... 7 more
| Error Server failed to start: org.apache.catalina.LifecycleException: Failed to initialize component [StandardServer[-1]]
&lt;/bootloader&gt;&lt;/pre&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Compile errors after removing Hibernate:&lt;/b&gt;&lt;br /&gt;
After getting Jetty installed, I was ready to run the app and get things going. Nope, more errors - now I can't compile because something can not find org.hibernate.cfg.Configuration! &amp;nbsp; I am working on Grails 2.1.0 and starting in that release, the database migration plugin depends on Hibernate, so if you are going to remove Hibernate, you also need to remove the database migration plugin. &amp;nbsp; Easy fix - edit BuildConfig.groovy to remove the database migration plugin and re-run. &amp;nbsp;Below is a copy of both the short error version and the longer version, which used --stacktrace to get a full stacktrace.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;pre class="brush:plain"&gt;c:\dev\groovy\hv&amp;gt;grails run-app
| Uninstalled plugin [tomcat]
| Uninstalled plugin [hibernate]
| Compiling 113 source files.
| Error Fatal error during compilation org.apache.tools.ant.BuildException: java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration
(Use --stacktrace to see the full trace)


c:\dev\groovy\hv&amp;gt;grails --stacktrace run-app
| Compiling 113 source files.
| Error Fatal error during compilation org.apache.tools.ant.BuildException: java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration
(NOTE: Stack trace has been filtered. Use --verbose to see entire trace.)
java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.codehaus.gant.GantBuilder.invokeMethod(GantBuilder.java:99)
        at _GrailsCompile_groovy$_run_closure3_closure8_closure9.doCall(_GrailsCompile_groovy:62)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at _GrailsCompile_groovy$_run_closure3_closure8_closure9.doCall(_GrailsCompile_groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at java_util_concurrent_Callable$call.call(Unknown Source)
        at _GrailsCompile_groovy.withCompilationErrorHandling(_GrailsCompile_groovy:69)
        at _GrailsCompile_groovy.this$4$withCompilationErrorHandling(_GrailsCompile_groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:168)
        at _GrailsCompile_groovy$_run_closure3_closure8.doCall(_GrailsCompile_groovy:61)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at _GrailsCompile_groovy$_run_closure3_closure8.doCall(_GrailsCompile_groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at _GrailsCompile_groovy$_run_closure3.doCall(_GrailsCompile_groovy:58)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at java_util_concurrent_Callable$call.call(Unknown Source)
        at org.codehaus.gant.GantBinding.withTargetEvent(GantBinding.groovy:90)
        at org.codehaus.gant.GantBinding.this$4$withTargetEvent(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.processClosure(GantMetaClass.java:81)
        at org.codehaus.gant.GantMetaClass.processArgument(GantMetaClass.java:95)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:128)
        at _GrailsCompile_groovy$_run_closure2.doCall(_GrailsCompile_groovy:45)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at java_util_concurrent_Callable$call.call(Unknown Source)
        at org.codehaus.gant.GantBinding.withTargetEvent(GantBinding.groovy:90)
        at org.codehaus.gant.GantBinding.this$4$withTargetEvent(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:168)
        at _GrailsPackage_groovy$_run_closure2_closure9.doCall(_GrailsPackage_groovy:45)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at _GrailsPackage_groovy$_run_closure2_closure9.doCall(_GrailsPackage_groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at _GrailsPackage_groovy$_run_closure2.doCall(_GrailsPackage_groovy:44)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at java_util_concurrent_Callable$call.call(Unknown Source)
        at org.codehaus.gant.GantBinding.withTargetEvent(GantBinding.groovy:90)
        at org.codehaus.gant.GantBinding.this$4$withTargetEvent(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.processClosure(GantMetaClass.java:81)
        at org.codehaus.gant.GantMetaClass.processArgument(GantMetaClass.java:95)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:128)
        at RunApp$_run_closure1.doCall(RunApp.groovy:28)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at java_util_concurrent_Callable$call.call(Unknown Source)
        at org.codehaus.gant.GantBinding.withTargetEvent(GantBinding.groovy:90)
        at org.codehaus.gant.GantBinding.this$4$withTargetEvent(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy:185)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at java_util_concurrent_Callable$call.call(Unknown Source)
        at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at java_util_concurrent_Callable$call.call(Unknown Source)
        at gant.Gant.withBuildListeners(Gant.groovy:427)
        at gant.Gant.this$2$withBuildListeners(Gant.groovy)
        at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
        at gant.Gant.dispatch(Gant.groovy:415)
        at gant.Gant.this$2$dispatch(Gant.groovy)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at gant.Gant.invokeMethod(Gant.groovy)
        at gant.Gant.executeTargets(Gant.groovy:591)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at gant.Gant.executeTargets(Gant.groovy:590)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
        at com.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1231)
Caused by: java.lang.ClassNotFoundException: org.hibernate.cfg.Configuration
        ... 123 more
| Error Fatal error during compilation org.apache.tools.ant.BuildException: java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration


&lt;/pre&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Minor mention:&lt;/b&gt;&lt;br /&gt;
Starting in Grails 2.x, &amp;nbsp;BuildConfig.groovy plays a bigger role in dependency resolution. &amp;nbsp;I read in some forum postings that modifying BuildConfig.groovy was now the preferred way of handling plugins rather than using the command line 'grails install-plugin &lt;plugin&gt;' or 'grails uninstall-plugin &lt;plugin&gt;'. &amp;nbsp; My problem was that I was starting with a Grails project that was originally created with Grails 1.3.7 and BuildConfig.groovy had not been updated with all the plugins. &amp;nbsp;I had to use a combination of the command line (grails uninstall-plugin) &amp;nbsp;plus edits to BuildConfig.groovy to resolve my problems. &amp;nbsp;&lt;/plugin&gt;&lt;/plugin&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Final Thoughts:&lt;/b&gt;&lt;br /&gt;
The problems documented above were mainly my fault and not that of Grails! &amp;nbsp;I am just documenting them to possibly help anyone trying the same type of integration. &amp;nbsp;Maybe this will save them some time and frustration!&lt;br /&gt;
&lt;br /&gt;
Hope this helps!&lt;br /&gt;
&lt;ol&gt;&lt;ol&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/hJJLLrY4XpM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/245088340123600680/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/11/grails-ejb2-my-stumbling-points.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/245088340123600680?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/245088340123600680?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/hJJLLrY4XpM/grails-ejb2-my-stumbling-points.html" title="Grails &amp; EJB2, my stumbling points" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/11/grails-ejb2-my-stumbling-points.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QGR3k7cCp7ImA9WhJVEkw.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-4702333037896462042</id><published>2012-08-28T22:32:00.001-05:00</published><updated>2012-08-28T22:35:26.708-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-28T22:35:26.708-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jnlp code signing certificates zipfile" /><title>Resolving the "Not all jars signed with same certificate" issue</title><content type="html">Almost a year ago I wrote&lt;a href="http://programmingitch.blogspot.com/2011/10/jars-signed-with-mutliple-code-signing.html" target="_blank"&gt; posting &lt;/a&gt;on how to resolve the "Not all jars signed with the same certificate" problem encountered from time to time with signed Web Start applications. &amp;nbsp; My solution at that time was to use a short Groovy script to show each jar and a list of the certificates the jar was signed with. &amp;nbsp;For those familiar with Groovy, that's still my suggestion.&lt;br /&gt;
&lt;br /&gt;
Recently one of our customer service folks was fighting this same problem at a customer site. &amp;nbsp;To make matters worse, they were not familiar with Groovy, so using my previous script was not an option. &amp;nbsp; I decided to bite the bullet and write the Java equivalent. &lt;br /&gt;
&lt;br /&gt;
Below is my Java-equivalent of the Groovy script. &amp;nbsp;The code is saved as the &lt;a href="https://github.com/mikemil/JarSigners" target="_blank"&gt;JarSigners project at GitHub&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;package util;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

/**
 *  Show which jars are signed with which code signing certificates
 */
public class JarSigners {

 private String folderName;
 private Map&lt;string list="list" tring="tring"&gt;&amp;gt; map;
 private Set&lt;string&gt; certs;
 
 public JarSigners(String folderName) {
  this.folderName = folderName;
  map = new HashMap&lt;string list="list" tring="tring"&gt;&amp;gt;();
  certs = new HashSet&lt;string&gt;();
 }
 
 public void listJarSigners() throws ZipException, IOException {
  File dir = new File(folderName);
  FilenameFilter filter = new FilenameFilter() {
      public boolean accept(File dir, String name) {
          return name.endsWith(".jar");
      }
  };
  String[] files = dir.list(filter);
  System.out.println("Found "+files.length+" files in folder: "+folderName);
  for (String fileName : files) {
   checkJarForCertificate(fileName);
  }
  System.out.println("Certificates used to sign the jars: "+certs);
  if (certs.size() &amp;gt; 1) {
   System.out.println("WARNING: More that one certificate shows up in the jars!");
  }
  System.out.println("Details jar-&amp;gt;certificate: "+map);
 }
 
 private void checkJarForCertificate(String fileName) throws ZipException, IOException {
  File jar = new File(folderName, fileName);
  ZipFile zip = new ZipFile(jar);
  //System.out.println("Processing "+fileName);
  for (Enumeration entries = zip.entries(); entries.hasMoreElements();) {
         // Get the entry name
         String zipEntryName = ((ZipEntry)entries.nextElement()).getName();
         if (zipEntryName.endsWith(".RSA")) {
          if (!certs.contains(zipEntryName)) {
           certs.add(zipEntryName);
          }
          if (map.containsKey(fileName)) {
           List&lt;string&gt; list = map.get(zipEntryName);
           list.add(zipEntryName);
          } else {
           List&lt;string&gt; list = new ArrayList&lt;string&gt;();
           list.add(zipEntryName);
           map.put(fileName, list);
          }
         }
     }
  zip.close();
  
 }

 /**
  * @param args
  * @throws IOException 
  * @throws ZipException 
  */
 public static void main(String[] args) throws ZipException, IOException {
  if (args.length != 1) {
   System.out.println("Invalid invocation: you must pass a folder name");
   return;
  }
  JarSigners js = new JarSigners(args[0]);
  js.listJarSigners();
  System.out.println("Done!");
 }

}
&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Hope this helps!&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/9vpPkZpc-rU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/4702333037896462042/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/08/resolving-not-all-jars-signed-with-same.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/4702333037896462042?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/4702333037896462042?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/9vpPkZpc-rU/resolving-not-all-jars-signed-with-same.html" title="Resolving the &quot;Not all jars signed with same certificate&quot; issue" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/08/resolving-not-all-jars-signed-with-same.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEEQn0yfCp7ImA9WhJWF0U.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-6166287436973657145</id><published>2012-08-23T22:56:00.001-05:00</published><updated>2012-08-23T22:56:43.394-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-23T22:56:43.394-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java swing auto-completion jtextfield" /><title>Auto-completion for email addresses in Swing</title><content type="html">&lt;br /&gt;
Recently we added the ability to send Electronic Receipts from our Point-of-Sale product at work. &amp;nbsp; One of the requirements was to enhance the user interface around the capture of email addresses. &amp;nbsp; We were just using a standard JTextField to capture the value. &amp;nbsp;Specifically, we were looking to make the entry of the email address easier by way of auto-completion, much like a lot of ajax-enabled fields in web applications.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-5Wo11ZakuMo/UDakTqbWCNI/AAAAAAAAAi0/12XcOIWOhLs/s1600/addressCompletion.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-5Wo11ZakuMo/UDakTqbWCNI/AAAAAAAAAi0/12XcOIWOhLs/s1600/addressCompletion.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I didn't want to re-invent the wheel and felt certain that I could something to get me started with the help of Google! &amp;nbsp; After a couple searches, I found a&lt;a href="http://samuelsjoberg.com/archive/2009/10/autocompletion-in-swing" target="_blank"&gt; great starting point&lt;/a&gt; for the new code. &amp;nbsp;Samuel Sjöberg's auto-completion was extremely close to what I wanted. &amp;nbsp; Rather than auto-completing a person's name, I wanted to provide auto-completion for the part of the email address after the "@". &amp;nbsp; &amp;nbsp;I also modified the code a bit to read the auto-completion candidates from a properties file. &amp;nbsp;This allows you to provide a properties file containing some of the most common email addresses. &amp;nbsp; Below is a copy of a sample properties file.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:plain"&gt;#################################################################################
# Commonly used Email Addresses                            
#                                                          
# This file will be read when the component starts up      
# and used to create an ArrayList of names to be used 
# for auto-completion of email addresses entered into 
# fields that assign the EmailAddressAutoCompletionDocument                      # to the field.  
#
# For better performance, put the most commonly used/encountered
# email addresses at the top of the list.
#
#################################################################################

 hotmail=hotmail.com
 gmail=gmail.com
 yahoo=yahoo.com
 verizon=verizon.net
 comcast=comcast.net
 aol=aol.com
 outlook=outlook.com
 mail=mail.com
 bigstring=bigstring.com
 shortmail=shortmail.com
 lycos=lycos.com
 excite=excite.com
 zoho=zohomail.com
 zzn=zzn.com
&lt;/pre&gt;
&lt;br /&gt;
Below is the interesting part of the auto-completion of the email address field. First, I included a check for a max length of 255 to prevent too much data for our database columns. Next, we check for an "@" sign entered. &amp;nbsp;If no @ sign, add the text. &amp;nbsp;There is also a check to prevent a second @ from being added to the field. &amp;nbsp;Once we get past that, its time to call the completion service looking for a match on the email address. If a match is found, we add the rest of the string to the text box and select the part of the address that wasn't actually entered by the user.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt; public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        if (str == null || str.length() == 0) {
            return;
        }

        // check for max length first
        if (str == null || ((str.length() + getLength() &amp;gt; maxLength) &amp;amp;&amp;amp; maxLength &amp;gt; 0))
   return;
        
        String text = getText(0, offs);        // Current text.
        int atSignIdx = text.indexOf(AT_SIGN); // 1st @ sign
        if (atSignIdx != -1 &amp;amp;&amp;amp; offs &amp;gt; atSignIdx) {
         String fullText = text+str;
         //prevent entry of 2nd @ sign
         if (fullText.indexOf(AT_SIGN, atSignIdx+1) != -1) {
          return;
         }
         String address = fullText.substring(fullText.indexOf(AT_SIGN)+1);
         String completion = complete(address);
         int length = offs + str.length();
         if (completion != null &amp;amp;&amp;amp; text.length() &amp;gt; 0) {
                super.insertString(offs, completion.substring(address.length()-1), a);
                documentOwner.select(length, getLength());
         } else {
          super.insertString(offs, str, a);
         }
        } else {
            super.insertString(offs, str, a);
        }
    }
&lt;/pre&gt;
&lt;br /&gt;
I also added automatic validation of the full address by providing a regular expression to match against and then assigned a KeyListener to help implement the validation with color coding. &amp;nbsp; As the user types an email address, the foreground color is red and then when the email address is complete, either through auto-completion of the address portion or just typing, the foreground color is changed to green for a valid address.&lt;br /&gt;
&lt;br /&gt;
Thanks to Samuel for posting his code. &amp;nbsp;My updated version can be found at&lt;a href="git://github.com/mikemil/emailAutoCompletion.git" target="_blank"&gt; GitHub&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Hope this helps!&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/xp3Jk0Ok-GA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/6166287436973657145/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/08/auto-completion-for-email-addresses-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/6166287436973657145?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/6166287436973657145?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/xp3Jk0Ok-GA/auto-completion-for-email-addresses-in.html" title="Auto-completion for email addresses in Swing" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-5Wo11ZakuMo/UDakTqbWCNI/AAAAAAAAAi0/12XcOIWOhLs/s72-c/addressCompletion.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/08/auto-completion-for-email-addresses-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAGSHYyfCp7ImA9WhJXGUw.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-101233157480925938</id><published>2012-08-13T21:18:00.000-05:00</published><updated>2012-08-13T21:18:49.894-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-13T21:18:49.894-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MongoDB" /><category scheme="http://www.blogger.com/atom/ns#" term="book review" /><title>Book Review: MongoDB in Action</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-86slpuRUzLU/UCmqEqZOPkI/AAAAAAAAAiU/hTwMRrci9Wk/s1600/mongdb_in_action.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/-86slpuRUzLU/UCmqEqZOPkI/AAAAAAAAAiU/hTwMRrci9Wk/s320/mongdb_in_action.jpg" width="255" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Overview&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&amp;nbsp;I am a big fan of Manning Publications books and so when it came time to do some personal research on NoSQL, I started with the Manning website to what books they had that covered the topic. &amp;nbsp;I didn't really have any specific requirements, like document model vs key value pairs vs graph database. &amp;nbsp;I just wanted something fairly current and covering one of the main players in the area.&lt;br /&gt;
&lt;br /&gt;
I found this book on the website and the publication date (2012) helped ensure that I was getting was something current and not a couple years old. &amp;nbsp;The other nice surprise was the size of the book. &amp;nbsp;For anyone that's read an 'In Action' book from Manning, you know they generally tend to be fairly large, on the scale of 300-400 page or more. &amp;nbsp; This book weighs in at 278 pages and that includes 5 appendices!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Contents&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
The book is broken down into 3 parts:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Getting Started,&lt;/b&gt; which covers about 50 pages talking about MongoDB at a high-level, the core server, tools, replication, the JavaScript shell and writing programs and using drivers to interact with the database.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Application Development in MongoDB&lt;/b&gt; covers principles of schema design, MongoDB databases, collections, Mongo's query language, updates atomic operations and deletes.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MongoDB Mastery&lt;/b&gt; covers index and query optimization, replication, sharding and deployment.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
An excellent book by Kyle Banker and yet another excellent book from the folks at Manning Publications. &amp;nbsp;I blew through the first two parts of the book, eager to learn more about NoSQL and MongoDB. &amp;nbsp;The author does an excellent job explaining concepts within MongoDB and backs up his statements with the reasons why things are done the way they are. &lt;br /&gt;
&lt;br /&gt;
It took a bit longer for me to get through part 3 of the book, no fault of the author or book. &amp;nbsp;Since this was really my own personal research and there is no way I will be implementing MongoDB or NoSQL at my day job, other than maybe some small personal tools/utilities, the topics of replication and sharding just didn't have the same appeal as learning about the core server, the query language and schema design!&lt;br /&gt;
&lt;br /&gt;
Overall, I would recommend this book to anyone interested in learning about MongoDB.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/RzX7Zpu2kr8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/101233157480925938/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/08/book-review-mongodb-in-action.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/101233157480925938?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/101233157480925938?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/RzX7Zpu2kr8/book-review-mongodb-in-action.html" title="Book Review: MongoDB in Action" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-86slpuRUzLU/UCmqEqZOPkI/AAAAAAAAAiU/hTwMRrci9Wk/s72-c/mongdb_in_action.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/08/book-review-mongodb-in-action.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8CRn4-fCp7ImA9WhJRFkk.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-2661554655355465724</id><published>2012-07-16T21:22:00.002-05:00</published><updated>2012-07-18T15:54:27.054-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-18T15:54:27.054-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GDK Groovy" /><title>GDK vs JDK</title><content type="html">A lot of folks new to Groovy quickly ask the question, "What's is the GDK?" or "What's the difference between the &lt;a href="http://groovy.codehaus.org/groovy-jdk/" target="_blank"&gt;GDK &lt;/a&gt;and the JDK?" &lt;br /&gt;
&lt;br /&gt;
If you take a look thru the GDK documentation, you will see that the GDK acts like an extension to the Java JDK. &amp;nbsp;New methods are added to the GDK help remove the ceremony and allow Groovy code to be short and concise. &amp;nbsp;Think of it as a big decorator pattern! &amp;nbsp; Slight clarification: the JDK is used to build the GDK and referenced by the GDK but it is NOT part of the GDK and not shipped with the GDK.&lt;br /&gt;
&lt;br /&gt;
Maybe a picture will help. &amp;nbsp;You can see some of the new GDK methods added to the Java classes below.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-PEi9M-W13pU/UATLydBn_dI/AAAAAAAAAiI/Fuy5FXhNLoo/s1600/GDKvsJDK.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="480" src="http://3.bp.blogspot.com/-PEi9M-W13pU/UATLydBn_dI/AAAAAAAAAiI/Fuy5FXhNLoo/s640/GDKvsJDK.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Hope this helps!&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/1Xrbeu6ktbU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/2661554655355465724/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/07/gdk-vs-jdk.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/2661554655355465724?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/2661554655355465724?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/1Xrbeu6ktbU/gdk-vs-jdk.html" title="GDK vs JDK" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-PEi9M-W13pU/UATLydBn_dI/AAAAAAAAAiI/Fuy5FXhNLoo/s72-c/GDKvsJDK.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/07/gdk-vs-jdk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8EQXs_fSp7ImA9WhJRFEU.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-4997500910135003279</id><published>2012-07-14T20:48:00.000-05:00</published><updated>2012-07-16T20:33:20.545-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-16T20:33:20.545-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JBoss AS7 JNDI EJB3.1" /><title>JBoss AS7 JNDI &amp; EJB 3.1 Naming changes</title><content type="html">&lt;span style="background-color: white;"&gt;As a result of the "feature train" continuing to march on and us not keeping our software stack up-to-date, our team finds ourselves in the un-enviable position of having to migrate:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;JBoss 4.2.3 to AS 7.1.x (currently looking at 7.1.1)&lt;/li&gt;
&lt;li&gt;EJB 2.1 to EJB 3.1&lt;/li&gt;
&lt;li&gt;Hibernate 2 to Hibernate 3 or 4&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
in quick fashion. &amp;nbsp;I mean, who wants to ship a new release with 8-10 year old software, not me!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white;"&gt;The following is the result of some research I did while looking at upgrading from JBoss 4.2.3 with EJB 2.1 to AS 7.1.x with EJB 3.1. &amp;nbsp;I am sure there will be more posts related to this migration in the near future, but this one is related to changes in the JNDI naming area.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white;"&gt;&lt;b&gt;In the past/current&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
In our current code, the JNDI naming has been very simple:&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style="background-color: white;"&gt;We &lt;/span&gt;&lt;span style="background-color: white;"&gt;concatenated&lt;/span&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;"ejb/" with the name of the remote Session Bean interface in the deployment descriptor to indicate the name that the service should be bound to.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="background-color: white;"&gt;In the code, we use the following code to handle the JNDI lookup. &amp;nbsp;The really nice part was that the same code could be used by remote clients AND on the server, within the container.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;b&gt;Current Code&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush:java"&gt;Hashtable properties = new Hashtable();
properties.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
properties.put("java.naming.provider.url", "jnp://localhost:1099");
Context ctx = new InitialContext(properties);
Object ref = ctx.lookup(jndiName);
&lt;/pre&gt;
&lt;span style="font-family: 'Times New Roman';"&gt;&lt;span style="white-space: normal;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;b style="background-color: white;"&gt;AS7 and EJB 3.1&lt;/b&gt;&lt;br /&gt;
The EJB 3.1 spec has made some changes to mandate portable JNDI names for EJBs and you inherit this in AS 7.1.1. &amp;nbsp; The other tricky thing I found was that I could no longer use the exact same lookup code from our remote clients and the server. 
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="white-space: normal;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;span style="font-family: 'Times New Roman';"&gt;AS 7 now has two &lt;a href="https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project" target="_blank"&gt;options for remote EJB invocation&lt;/a&gt;. &amp;nbsp;The information you need can be found in the JBoss docs, it just didn't hit me over the head! &amp;nbsp;After struggling with this issue for a couple days, I decided to create a small program to help make the differences (hopefully) very clear. &amp;nbsp;Below is the program that I created to invoke a stateless session bean from a remote client. &amp;nbsp; I deployed the "&lt;b&gt;ejb-remote"&lt;/b&gt; sample from the 7.1 Quick Start samples. &amp;nbsp;The code attempts to load the remote service using both remote methods. &amp;nbsp;The expectation is that for the first set of lookups, the first lookup is successful and the second, using the "ejb:/" naming format fails. &amp;nbsp;Then I add the Context.URL_PKG_PREFIXES property with a value of "org.jboss.ejb.client.naming" to the jndi properties passed to the InitialContext constructor and repeat the lookups. &amp;nbsp;Now, both lookups should be successful. &amp;nbsp;I have included all the JNDI properties in the code rather than relying on a copy of "&lt;b&gt;jboss-ejb-client.properties&lt;/b&gt;" or "&lt;b&gt;jndi.properties&lt;/b&gt;" being picked up from the classpath.&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import java.util.Hashtable;

public class EJBClient {

     private static String[] JNDINAME = {
          "jboss-as-ejb-remote-app/CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator", 
          "ejb:/jboss-as-ejb-remote-app/CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator" 
     };
     
     private Hashtable jndiProps;
     
     public EJBClient() {
       // setup 'base' jndi properties - no jboss-ejb-client.properties being picked up from classpath!
       jndiProps = new Hashtable();
          jndiProps.put("java.naming.factory.initial","org.jboss.naming.remote.client.InitialContextFactory");
          jndiProps.put(InitialContext.PROVIDER_URL, "remote://localhost:4447");
          jndiProps.put("jboss.naming.client.ejb.context", true);
        
          // needed for remote access - remember to run add-user.bat
          jndiProps.put(Context.SECURITY_PRINCIPAL, "client");
          jndiProps.put(Context.SECURITY_CREDENTIALS, "password");
     }
     
    public void doLookups() {
         // the 'exported' namespace
         for (int i = 0; i &amp;lt; JNDINAME.length; i++) {
               lookup(JNDINAME[i]);
          }
         
        
         // This is an important property to set if you want to do EJB invocations via the remote-naming project
        jndiProps.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        
        // now with the ejb
        for (int i = 0; i &amp;lt; JNDINAME.length; i++) {
               lookup(JNDINAME[i]);
          }
    }
    
    private void lookup(String name) {
         System.out.println("Lookup name="+name);
         
         Context ctx = null;
        try {
               ctx = new InitialContext(jndiProps);
               Object ref = ctx.lookup(name);
               System.out.println("...Successful");
          } catch (NamingException e) {
               System.out.println("...Failed");
               //System.out.println(e.getMessage());
               e.printStackTrace();
          } finally {
               if (ctx != null) {
                    try {
                         ctx.close();
                    } catch (NamingException e) {}
               }
          }
    }
    
    public static void main(String[] args) throws Exception {
         EJBClient client = new EJBClient();
         client.doLookups();
         
         System.out.println("Done!");
    }
    
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;AS7 on the server-side&lt;/b&gt;&lt;br /&gt;
Now the easy part, doing the JNDI lookups on the server are very similar to the old way, except that you still need to format the JNDI name according to the new specs and the naming factory is no longer the jnp version!&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;Hashtable jndiProps = new Hashtable();
    jndiProps.put("java.naming.factory.initial", "org.jboss.as.naming.InitialContextFactory");
    ctx = new InitialContext(jndiProps);
    Object ref = ctx.lookup(jndiName);
&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
As I said earlier, the information was/is in the JBoss documentation, but I probably read past it several times. &amp;nbsp;What I was looking for was an example showing loading the EJBs from both the client and the server. &lt;br /&gt;
&lt;br /&gt;
Hope this helps!&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/llQKfWe036Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/4997500910135003279/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/07/jboss-as7-jndi-ejb-31-naming-changes.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/4997500910135003279?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/4997500910135003279?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/llQKfWe036Y/jboss-as7-jndi-ejb-31-naming-changes.html" title="JBoss AS7 JNDI &amp; EJB 3.1 Naming changes" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/07/jboss-as7-jndi-ejb-31-naming-changes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkADQH4-fCp7ImA9WhVRF04.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-7459395874319104980</id><published>2012-03-25T21:59:00.000-05:00</published><updated>2012-03-25T21:59:31.054-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-25T21:59:31.054-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy grails upgrade" /><title>Ajax Examples upgraded to Grails 2.0.0</title><content type="html">&lt;b&gt;Overview&lt;/b&gt;&lt;br /&gt;
A little over a year ago, I wrote a blog posting providing a complete set of working code showing &lt;a href="http://programmingitch.blogspot.com/2011/01/grails-ajax-examples.html"&gt;ajax examples&lt;/a&gt; for each of the Grails tags that supports Ajax. &amp;nbsp; Now, I finally found time to upgrade that code to Grails 2.0.0 (from Grails 1.3.7). &amp;nbsp; There are plenty of article out there helping point users in the right direction when upgrading to Grails 2.0.0 and most of them are helpful. &amp;nbsp;Seems like no one wants to &lt;a href="http://en.wikipedia.org/wiki/RTFM"&gt;RTFM&lt;/a&gt;, we just want to get at it! &amp;nbsp;My recommendation is RTFM, and checkout some of the helpful postings out there, especially when the upgrade includes as many changes and new features as Grails 2.0.0.&lt;br /&gt;
&lt;br /&gt;
I have to confess, I tried to just "get at it" with my ajax application and Grails 2.0.0 and it got me part of the way there. &amp;nbsp;To finish the job, I needed to read the excellent documentation produced by the Grails team and also the documentation accompanying some of the plugins.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Steps for my upgrade&lt;/b&gt;&lt;br /&gt;
In order to get my application running under Grails 2.0, I needed 5 basic steps:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Run the '&lt;b&gt;grails upgrade'&lt;/b&gt; against my project.&lt;/li&gt;
&lt;li&gt;Upgrade database to use H2 - &lt;a href="http://pledbrook.github.com/grails-howtos/en/upgradeToGrails2.html#s2"&gt;instructions under Persistence here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install plugins: &lt;b&gt;prototype &lt;/b&gt;and &lt;b&gt;resources&amp;nbsp;&lt;/b&gt;plugin.&lt;/li&gt;
&lt;li&gt;Modify the main.gsp layout to&amp;nbsp;accommodate the plugins (resource, prototype).&lt;/li&gt;
&lt;li&gt;Modify &lt;b&gt;Config.groovy&lt;/b&gt; to set the java script library to prototype.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;b&gt;Step 1&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
This step is required for any application being upgraded from an earlier version of Grails. &amp;nbsp;I am not going to say anything else about this step.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;b&gt;Step 2&lt;/b&gt;&lt;br /&gt;
Follow &lt;a href="http://pledbrook.github.com/grails-howtos/en/upgradeToGrails2.html#s2"&gt;Peter Ledbrook's instructions&lt;/a&gt; on upgrading the persistence layer to use H2 database instead of the HSQLDB. &amp;nbsp;If you want to continue to use HSQLDB, there are instructions for that too!&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Step 3&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
I consider myself 'javascript-challenged', so I decided to stick with the prototype library for javascript for this upgrade rather than attempting to use jQuery, which is the new default library. &amp;nbsp;If all goes well and I get some free time, maybe I will upgrade the application to use jQuery too, but for now, I am sticking with prototype - less changes too!&lt;br /&gt;
&lt;br /&gt;
Make sure the plugins are installed, and then verify that they all got installed successfully (last statement).&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush:plain"&gt;grails install-plugin resources
grails install-plugin prototype
grails list-plugins -installed
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Step 4&lt;/b&gt;&lt;br /&gt;
One of the tricky parts here was including &lt;b&gt;plugin="prototype" &lt;/b&gt;on the javascript tag in the header section of this page. &amp;nbsp;Below is a copy of my layout\main.gsp. &amp;nbsp;(Be careful using cut/paste on the page below, I had problems with the syntax highligher or blogger (not sure which) adjusting my &amp;nbsp;html tags as it sees fit). &amp;nbsp;Best option, grab the code from &lt;a href="git://github.com/mikemil/AjaxExamples.git" target="_blank"&gt;GitHub&lt;/a&gt;. Also be sure to understand the &lt;a href="http://grails-plugins.github.com/grails-resources/guide/1.%20Overview.html#1.1.3%20Edit%20your%20Sitemesh%20layout" target="_blank"&gt;changes needed for the Resources Plugin.&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;
&lt;pre class="brush:xml"&gt;  
 
        &lt;title&gt;&amp;lt;g:layoutTitle default="Grails" /&amp;gt;&lt;/title&gt;
        &lt;link href="${resource(dir:'css',file:'main.css')}" rel="stylesheet"&gt;&lt;/link&gt;
        &lt;link href="${resource(dir:'images',file:'favicon.ico')}" rel="shortcut icon" type="image/x-icon"&gt;&lt;/link&gt;
        &lt;g:layouthead&gt;
        &lt;g:javascript library="prototype" plugin="prototype"&gt;
        &lt;g:javascript&gt;
           function showSpinner(visible) {
              $('spinner').style.display = visible ? "inline" : "none";
           }
           Ajax.Responders.register({
           onLoading: function() {
                 showSpinner(true);
           },
           onComplete: function() {
             if(!Ajax.activeRequestCount) showSpinner(false);
           }
           });
        &lt;/g:javascript&gt;
        &lt;r:layoutresources&gt;
    
     
        &lt;div class="spinner" id="spinner" style="display: none;"&gt;
&lt;img alt="${message(code:'spinner.alt',default:'Loading...')}" src="${resource(dir:'images',file:'spinner.gif')}" /&gt;
        &lt;/div&gt;
&lt;div id="grailsLogo"&gt;
&lt;a href="http://grails.org/"&gt;&lt;img alt="Grails" border="0" src="${resource(dir:'images',file:'grails_logo.png')}" /&gt;&lt;/a&gt;
        &lt;/div&gt;
&lt;div id="menu"&gt;
&lt;g:render template="/common/menu"&gt;
        &lt;/g:render&gt;&lt;/div&gt;
&lt;g:layoutbody&gt;
        &lt;div id="footer"&gt;
&lt;g:render template="/common/footer"&gt;
        &lt;/g:render&gt;&lt;/div&gt;
&lt;r:layoutresources&gt;
      
&lt;/r:layoutresources&gt;&lt;/g:layoutbody&gt;&lt;/r:layoutresources&gt;&lt;/g:javascript&gt;&lt;/g:layouthead&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Step 5&lt;/b&gt;&lt;br /&gt;
Update Config.groovy to define prototype as the javascript library to use.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;pre class="brush:groovy"&gt;... 
grails.views.javascript.library = "prototype"
...
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
The project has been updated &amp;nbsp;and now available on &lt;a href="git://github.com/mikemil/AjaxExamples.git" target="_blank"&gt;GitHub.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Hope this helps!&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/iTm7xOyd2dI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/7459395874319104980/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/03/ajax-examples-upgraded-to-grails-200.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/7459395874319104980?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/7459395874319104980?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/iTm7xOyd2dI/ajax-examples-upgraded-to-grails-200.html" title="Ajax Examples upgraded to Grails 2.0.0" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>8</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/03/ajax-examples-upgraded-to-grails-200.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4BR309cCp7ImA9WhRUGUo.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-8435450208431433389</id><published>2012-01-30T21:02:00.002-06:00</published><updated>2012-01-30T21:02:36.368-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T21:02:36.368-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="book review" /><category scheme="http://www.blogger.com/atom/ns#" term="clojure" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="scala" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title>Book Review: Programming Concurrency on the JVM</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-V999R5VE8d0/TxOoIcBwgQI/AAAAAAAAAac/sxOUDJM2T6c/s1600/concurrency.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/-V999R5VE8d0/TxOoIcBwgQI/AAAAAAAAAac/sxOUDJM2T6c/s320/concurrency.jpg" width="260" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;Overview&lt;/b&gt;&lt;br /&gt;
Programming concurrency is a tough task to get right, just ask Venkat, he'll tell you so! &amp;nbsp;I attended a presentation by Dr. Venkat Subramaniam on this very subject, Concurrency on the JVM, at my local Java user group a couple months ago and he really caught my attention. &amp;nbsp;The presentation was a condensed version of the book, and needless to say, I bought the book to help fill in all the details. &lt;br /&gt;
&lt;br /&gt;
Not only is Venkat a 'subject matter expert', &amp;nbsp;but his presentation kept everyone engaged and laughing!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Contents:&lt;/b&gt;&lt;br /&gt;
The book is broken down in 5 parts, with 10 chapters total, at just over 250 pages. &amp;nbsp;The main sections of the book are:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;Strategies for Concurrency&lt;/i&gt; - this discusses the impact of multi-core machines and the three design approaches that are discussed throughout the rest of the book, &lt;i&gt;Shared Mutability&lt;/i&gt;, &lt;i&gt;Isolated Mutability&lt;/i&gt; and &lt;i&gt;Pure Immutability.&lt;/i&gt;&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;&lt;i&gt;Modern Java/JDK Concurrency - &lt;/i&gt;covers the Java 1.5+ concurrency features and talks about how to use the newer concurrency classes, like ExecutorService, CountDownLatch, Locks and Fork/Join to solve concurrency problems.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;&lt;i&gt;Software Transactional Memory - &lt;/i&gt;covers Software Transactional Memory (STM), popularized by Clojure, which places access to memory within transactions. &amp;nbsp;STM is one option for getting away from the 'Synchronize and Suffer' model as Venkat call it. &amp;nbsp;The intention is to make threaded code more deterministic. &amp;nbsp; Using the JDK concurrency tools, there is no way to be sure you code is correct because it doesn't always fail when/where you need it to. &amp;nbsp; By putting the memory access inside transactions, the transaction manager helps resolve the conflicts without explicit locking.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;&lt;i&gt;Actor-based Concurrency - &lt;/i&gt;covers actor design approaches as another option for concurrency design without using synchronization. &amp;nbsp;This section exercises actors from the Akka library from Scala, Actors from the Groovy library GPars, and mixing Actors and STM as a possible solution.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;&lt;i&gt;Epilogue - &lt;/i&gt;is a short recap of the topics presented previously and points out the scenarios when each of the solutions would be appropriate.&lt;/li&gt;
&lt;/ul&gt;
The book lays out a couple example problems and then develops solutions for these problems across a range of JVM languages (Java, Groovy, Scala, Clojure and JRuby). &amp;nbsp; The examples are short and concise, &amp;nbsp;&amp;nbsp;enough to help you to get started prototyping against your own concurrency issues.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
This is a good book to get you started on some of these &lt;b&gt;newer&lt;/b&gt;&amp;nbsp;concurrency concepts and libraries. &amp;nbsp;It was&amp;nbsp;an easy read, and I completed the reading fairly quickly, as opposed to the&amp;nbsp;"Java Concurrency in Practice" book, which I started and stopped twice and still have not completed yet! &lt;br /&gt;
&lt;br /&gt;
I would recommend this book to anyone looking to improve their programming skills in the concurrency area. &amp;nbsp;The book provides you with some alternatives to the old standby of '
Synchronize&amp;nbsp;and Suffer' model.&lt;br /&gt;
My last recommendation, if you get the opportunity, attend one of Venkat's presentations, you won't be sorry!&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/LHN9ug-vR1E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/8435450208431433389/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/01/book-review-programming-concurrency-on.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/8435450208431433389?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/8435450208431433389?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/LHN9ug-vR1E/book-review-programming-concurrency-on.html" title="Book Review: Programming Concurrency on the JVM" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-V999R5VE8d0/TxOoIcBwgQI/AAAAAAAAAac/sxOUDJM2T6c/s72-c/concurrency.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/01/book-review-programming-concurrency-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUAR38yeyp7ImA9WhRUEE4.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-1223999122839282905</id><published>2012-01-19T22:03:00.001-06:00</published><updated>2012-01-19T22:04:06.193-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-19T22:04:06.193-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy Binding script" /><title>Passing parameters into Groovy script using Binding class</title><content type="html">I recently saw a question posted on the Groovy/Grails group on LinkedIn asking about ways to pass in parameters to a Groovy script. &amp;nbsp;There were several responses pointing to the &lt;a href="http://groovy.codehaus.org/gapi/groovy/util/CliBuilder.html"&gt;CliBuilder&lt;/a&gt; class which is certainly one way to handle the problem. &amp;nbsp; I had just finished reading an article by &lt;a href="http://kousenit.wordpress.com/"&gt;Ken Kousen&lt;/a&gt; in the November issue of &lt;a href="http://groovymag.com/"&gt;GroovyMag&amp;nbsp;&lt;/a&gt;&amp;nbsp;where Ken mentioned another option: using the Binding class.&lt;br /&gt;
&lt;br /&gt;
The example below shows a couple ways of setting variables in the binding, getting the variable values from the binding and how to capture standard output from the script. &amp;nbsp;The one tricky part is the question "&lt;a href="http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22"&gt;When is something in the Binding and when not?&lt;/a&gt;" &amp;nbsp;The answer is: when it's not defined, it is in the binding! &amp;nbsp;In the example below, variable &lt;b&gt;c&lt;/b&gt; is placed in the binding, but since it is def'd in the script, the value for that variable comes from the local variable rather than the binding.&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;// setup binding
def binding = new Binding()
binding.a = 1
binding.setVariable('b', 2)
binding.c = 3
println binding.variables

// setup to capture standard out
def content = new StringWriter()
binding.out = new PrintWriter(content)

// evaluate the script
def ret = new GroovyShell(binding).evaluate('''
def c = 9
println 'a='+a
println 'b='+b
println 'c='+c 
retVal = a+b+c
a=3
b=2
c=1
''')

// validate the values
assert binding.a == 3
assert binding.getVariable('b') == 2
assert binding.c == 3 // binding does NOT apply to def'd variable
assert binding.retVal == 12 // local def of c applied NOT the binding!

println 'retVal='+binding.retVal
println binding.variables
println content.toString()
&lt;/pre&gt;
Output
&lt;br /&gt;
&lt;pre class="brush:plain"&gt;[a:1, b:2, c:3]
retVal=12
[a:3, b:2, c:3, out:java.io.PrintWriter@1e0799a, retVal:12]
a=1
b=2
c=9
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Hope this helps!
&lt;/b&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/GJqTkHU4Hyc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/1223999122839282905/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/01/passing-parameters-into-groovy-script.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1223999122839282905?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1223999122839282905?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/GJqTkHU4Hyc/passing-parameters-into-groovy-script.html" title="Passing parameters into Groovy script using Binding class" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/01/passing-parameters-into-groovy-script.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cHQ3c5fSp7ImA9WhRVGEs.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-3243788947347655605</id><published>2012-01-17T22:30:00.001-06:00</published><updated>2012-01-17T22:30:32.925-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-17T22:30:32.925-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Book review SQL Antipatterns" /><title>Book Review: SQL Antipatterns Avoiding the Pitfalls of Database Programming</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-pmIBBDZjDAA/TxOYhn1iqjI/AAAAAAAAAaU/0W_1Oi9kPtU/s1600/sql_antipatterns.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-pmIBBDZjDAA/TxOYhn1iqjI/AAAAAAAAAaU/0W_1Oi9kPtU/s200/sql_antipatterns.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;Overview&lt;/b&gt;&lt;br /&gt;
This is book for software developers that are either new to database programming (SQL) or those that may not have had any formal database education and may have learned &lt;i&gt;'on-the-job&lt;/i&gt;'. &lt;br /&gt;
&lt;br /&gt;
The book is bit longer, approximately 300 pages, than some of the other titles I've read from &lt;i&gt;The Pragmatic Programmers&lt;/i&gt; shelf, but it is a very easy read. &amp;nbsp;The chapters all follow a similar format: &lt;i&gt;Object&lt;/i&gt;, &lt;i&gt;Antipattern&lt;/i&gt;, &lt;i&gt;How to Recognize the Antipattern, Legitimate Uses of the Antipattern &lt;/i&gt;and &lt;i&gt;Solution.&lt;/i&gt;&amp;nbsp; Each chapter the author leads you through a problem that needs correcting within the scope of the database. &amp;nbsp; Next the antipattern is laid out for you and the author shows the disadvantages of using the antipattern. &amp;nbsp; Tips are provided to help identify the antipattern and he also suggests some possible legitimate uses of the antipattern. &amp;nbsp;Finally, the author describes better solutions to the problem presented; ones without the disadvantages discussed previously and solutions that are considered 'best practices' and that will provide better database performance.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Contents&lt;/b&gt;&lt;br /&gt;
The book is broken down into 4 main sections:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Logical Database Design Antipatterns - planning database tables, columns and relationships&lt;/li&gt;
&lt;li&gt;Physical Database Design Antipatterns - defining tables, indexes and choosing &amp;nbsp;datatypes&lt;/li&gt;
&lt;li&gt;Query Antipatterns - SQL command usage, for example, &lt;i&gt;SELECT&lt;/i&gt;, &lt;i&gt;UPDATE &lt;/i&gt;and &lt;i&gt;DELETE&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Application Development Antipatterns - correct usage within the scope of a language&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Some of that antipatterns described may make you laugh and wonder, "Who the heck would do something like that?" while others you may have run into previously and some might even hit very close to home from your work or personal projects.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
There is also an appendix that covers the &lt;i&gt;Rules of Normalization. &amp;nbsp;&lt;/i&gt;I&amp;nbsp;had heard of terms like&amp;nbsp;&lt;i&gt;Normalization, First Normal Form,&amp;nbsp;&lt;/i&gt;and&amp;nbsp;&lt;i&gt;Second&amp;nbsp;Normal Form &lt;/i&gt;before, but never actually read any explanations. The appendix includes discussions on normalization and first normal form through fifth normal form with examples to help clarify the topics.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
This is a very good book for software developers just starting to 'cut their teeth' with databases and SQL. &amp;nbsp;It also serves as a good refresher for those with a bit more database experience. &amp;nbsp;In my case, I fall into the later scenario. &amp;nbsp;You can view it as a book of short stories, showing what &lt;b&gt;not &lt;/b&gt;to do in these cases.&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/Y4vZJRJdw0Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/3243788947347655605/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2012/01/book-review-sql-antipatterns-avoiding.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/3243788947347655605?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/3243788947347655605?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/Y4vZJRJdw0Y/book-review-sql-antipatterns-avoiding.html" title="Book Review: SQL Antipatterns Avoiding the Pitfalls of Database Programming" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-pmIBBDZjDAA/TxOYhn1iqjI/AAAAAAAAAaU/0W_1Oi9kPtU/s72-c/sql_antipatterns.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2012/01/book-review-sql-antipatterns-avoiding.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEHQ3s7fyp7ImA9WhdaFkg.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-7910933935640915590</id><published>2011-10-26T13:27:00.001-05:00</published><updated>2011-10-26T13:27:12.507-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-26T13:27:12.507-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web Start JNLP code signing certificates Groovy" /><title>Jars signed with mutliple code signing certificates?</title><content type="html">&lt;span class="Apple-style-span"&gt;For anyone that has built and maintained &lt;a href="http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136112.html"&gt;Web Start&lt;/a&gt; applications, you have probably been through this issue before. &amp;nbsp; Your QA group or worse yet, a customer, calls to tell you that they cannot start your application because the download failed because "&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px;"&gt;jar resources in jnlp are not signed by the same certificate&lt;/span&gt;&lt;span class="Apple-style-span"&gt;".&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
If want your Web Start application to have full access permissions, then you need to sign all the jars that get downloaded. &amp;nbsp;This generally presents the opportunity to encounter one of the following errors:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;None of the jars are signed. &amp;nbsp;Most likely a build issue and generally only happens once, (I hope!)&lt;/li&gt;
&lt;li&gt;Single jar &lt;x&gt; is not signed. &amp;nbsp;Again, most likely either a build or process error.&lt;/x&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/430755/jar-resources-in-jnlp-are-not-signed-by-the-same-certificate"&gt;Not all jars signed with the same certificate&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
The first two are easy to resolve. &amp;nbsp;The last is a bit of a pain because Web Start doesn't bother to tell you exactly which jars where signed with different code signing certificates. &amp;nbsp;Now, it's time to make some educated guesses as to what changed recently and look at the most likely/usual suspects. &amp;nbsp; Another option is to get the list of download jars from the JNLP document and figure out which certificates(s) each jar has been signed with.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
We have been through this at work once or twice and so I finally decided to make it easier for the next time this happens. &amp;nbsp; The approach I took was to read all the jars in a deployment folder, open them and look for the signature files inside the jar file. &amp;nbsp; For the results, I created a map keyed by the jar name and the value being a list of the signature file names (*.RSA, where the * represents our code signing certificate alias). &amp;nbsp;Keeping a list in the map allows for cases where a jar may have multiple signature files, which was encountered when we switched over code signing certificates. &amp;nbsp;Writing this in Java would be possible, &lt;b&gt;but why write so much code&lt;/b&gt;? &lt;b&gt;Why not write a script in Groovy&lt;/b&gt;, it would be some much shorter and concise.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;b&gt;Groovy Script&lt;/b&gt;&lt;/div&gt;
&lt;pre class="brush:groovy"&gt;def dir = new File("C:\\MyDeployment\\jboss\\myserver\\deploy\\myserver.ear")
def jars = dir.list( { d, f-&amp;gt; f ==~ /.*.jar/ } as FilenameFilter)
def map = [:]
jars.each() {
   def zipFile = new java.util.zip.ZipFile(new File(dir, it)) 
   zipFile.entries().each { zipEntry -&amp;gt;
      if (zipEntry.name.endsWith('.RSA')) {
          if (map.containsKey(it)) {
             def list = map[it]
             list &amp;lt;&amp;lt; zipEntry.name
          } else {
             map[it] = [zipEntry.name]
          }
      }
   }  
}
map.each{ println it}
&lt;/pre&gt;
&lt;pre class="brush:groovy"&gt;
&lt;/pre&gt;
&lt;b&gt;&lt;i&gt;Hope this helps!
&lt;/i&gt;&lt;/b&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/IUyJq1m2yaw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/7910933935640915590/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2011/10/jars-signed-with-mutliple-code-signing.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/7910933935640915590?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/7910933935640915590?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/IUyJq1m2yaw/jars-signed-with-mutliple-code-signing.html" title="Jars signed with mutliple code signing certificates?" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2011/10/jars-signed-with-mutliple-code-signing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEDRnY7cCp7ImA9WhdUE04.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-1474717991318796275</id><published>2011-09-29T16:11:00.000-05:00</published><updated>2011-09-29T16:11:17.808-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-29T16:11:17.808-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="pci pa/dss hints tips audit" /><title>Lessons learned from recent PA/DSS audit</title><content type="html">The following are some tips/hints and lessons learned during our recent PA/DSS audit. &amp;nbsp; Everyone's mileage will vary.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Our application runs on both Windows and Linux.&amp;nbsp;&amp;nbsp; We support JBoss and Weblogic for the application server.&amp;nbsp; We support Oracle, SQL Server and&amp;nbsp; MySQL for the database.&amp;nbsp; We have three client applications which are all WebStart clients, so this is NOT a web application.&amp;nbsp; Our EJBs are EJB 2.1 Session Beans.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Hints&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Determine exact software stacks needed including all software levels, build levels and whatever else you need.&amp;nbsp; Collect all of this in one safe place.&lt;/li&gt;
&lt;li&gt;Get the hardware ready and any scripts that may be needed to use those devices.&amp;nbsp; Our application is a POS, so we had a collection of pin pads that we were required to test with during the audit.&lt;/li&gt;
&lt;li&gt;Get any utility software needed&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Ghost for Win* images (or Win 7 provides a Backup/Restore feature)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;We ran into some problems with Windows Server 2008 and had to use one of the&amp;nbsp; &lt;a href="http://www.acronis.com/"&gt;Acronis &lt;/a&gt;tools to create the backup image.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;PartImage for Linux images&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.dban.org/"&gt;Darik's Boot and Nuke &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;anything else you might need&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Wipe the hard drives before loading any software, including the OS, using Darik's Boot and Nuke to be absolutely sure that the drive does contain anything that might match a credit/debit card number.&lt;/li&gt;
&lt;li&gt;Install the OS and any 'base' software, which isn't the software to be verified by the audit&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Keep the partition sizes as small as possible without causing disk output problems.&amp;nbsp; The larger the disk, the longer the forensic scans will take to run.&lt;/li&gt;
&lt;li&gt;On Windows - you can have a page file, just don't allow it to grow and shrink.&amp;nbsp;&amp;nbsp; Set the min and max file size to the same value.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Problem here is that if card holder data is written to the page file then later the page file size is shrunk, some of that card holder data MAY be inside freespace, which is NOT cleaned up by the OS.&amp;nbsp;&amp;nbsp; This can cause some instances of card holder data to be found during a forensic scan and NO ONE wants card holder data found during the scans.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;On Window - you should also set the Windows Update setting to be Notification because you don't want Windows Updates being applied to a machine during the audit.&lt;/li&gt;
&lt;li&gt; Our auditor also recommended we turn off the Windows Restore points.&amp;nbsp; Again, you don't want Windows doing any extra work that could impact the audit results.&lt;/li&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;li&gt;Take images of all boxes.&amp;nbsp; These may be needed to reset a machine back to a 'clean' state for ad additional set of tests.&lt;/li&gt;
&lt;li&gt;Talk to each of your authorization providers&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;let them know when your audit is scheduled and ensure you will have connectivity to their test servers&lt;/li&gt;
&lt;li&gt;Verify that each provider can supply 'magic authorization values' that will help your trigger the following responses:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;approvals&lt;/li&gt;
&lt;li&gt;declines&lt;/li&gt;
&lt;li&gt;referrals&lt;/li&gt;
&lt;li&gt;timeouts&lt;/li&gt;
&lt;li&gt;void&lt;/li&gt;
&lt;li&gt;split tenders&lt;/li&gt;
&lt;li&gt;partial auths&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;If any of the authorization providers encrypt their communications, then you may need to ensure you have whatever is needed for that. &amp;nbsp; We needed to download and install the&lt;a href="http://download.oracle.com/javase/1,5.0/docs/guide/security/jce/JCERefGuide.html"&gt; JCE &lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you support multiple authorization providers, you will have to run tests against each provider so be ready to do whatever it takes to switch your application from one provider to the next.&lt;/li&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;li&gt;Practice taking images and restoring images on all boxes&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;The Linux tools are not as user friendly as the Windows tools, so you need to be ready and able to make and restore your images in a timely manner.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Now you can install your software and you should be ready for the audit.&lt;/li&gt;
&lt;li&gt;If you do any testing before the auditor arrives, be ready to restore the machines back to a 'clean' state because you don't want to take a chance that your early testing wrote any card holder data somewhere on the hard drive.&lt;/li&gt;
&lt;li&gt;Our auditor previously used &lt;a href="http://x-ways.net/winhex/"&gt;WinHex &lt;/a&gt;to do the forensic scans.&amp;nbsp; We used the evaluation version to try and double-check ourselves.&amp;nbsp; The problem with that version is that it is slow and can only scan for one card number at a time.&amp;nbsp; This time the auditor had a new set of software for the scans and unfortunately I didn't get the name of the package, although I know it was a purchased product.&lt;/li&gt;
&lt;/ul&gt;
Good luck - hope this helps! &lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/UsWzNMBiMSo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/1474717991318796275/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2011/09/lessons-learned-from-recent-padss-audit.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1474717991318796275?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1474717991318796275?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/UsWzNMBiMSo/lessons-learned-from-recent-padss-audit.html" title="Lessons learned from recent PA/DSS audit" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2011/09/lessons-learned-from-recent-padss-audit.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMBSHc5fyp7ImA9WhdSEUQ.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-3108571967228729039</id><published>2011-07-20T12:56:00.002-05:00</published><updated>2011-07-20T14:34:19.927-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-20T14:34:19.927-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Book review Gradle Groovy" /><title>Book Review: Building and Testing with Gradle</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-hEzief4kBQo/TicVdM50t7I/AAAAAAAAAZU/Y0Y2NOdJiXM/s1600/gradlebook.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-hEzief4kBQo/TicVdM50t7I/AAAAAAAAAZU/Y0Y2NOdJiXM/s1600/gradlebook.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Overview&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Gradle is one of the new "cool kids on the block". &amp;nbsp;It &amp;nbsp;is quickly gaining momentum as projects like Hibernate and Spring migrate their build processes over to Gradle. &amp;nbsp; Gradle can be considered the 3rd generation of Java build tools, with Ant and Maven representing the earlier generations.&lt;br /&gt;
&lt;br /&gt;
Gradle is built on top of Groovy, which provides the ability to define a Domain Specific Language (DSL). &amp;nbsp;In this case, the Gradle DSL provides a language tailored to the task of building code. &amp;nbsp;If the DSL does not provide exactly what you need, then you can extend the DSL using plug-ins. &amp;nbsp;It is possible to learn Gradle without knowing Groovy, but some initial knowledge of Groovy is beneficial.&lt;br /&gt;
&lt;br /&gt;
This &lt;a href="http://oreilly.com/catalog/0636920019909/"&gt;book &lt;/a&gt;is short (89 pages) . &amp;nbsp;It brings back memories of the O'Reilly "A Developer's Notebook" series.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Contents&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;Chapter 1, Hello Gradle&lt;/b&gt;&amp;nbsp; This chapter leads the reader thru the installation and configuration of Gradle and demonstrates the ubiquitous Hello World (build file) example.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Chapter 2, Gradle Tasks&lt;/b&gt;&amp;nbsp; This is the &amp;nbsp;best chapter in the book. &amp;nbsp;It drives home the concepts associated with a 'task' and how the tasks can be configured and customized. &amp;nbsp; &amp;nbsp;The most helpful &amp;nbsp;suggestion in the book is found in this chapter. &amp;nbsp;The &amp;nbsp;recommendation is that you read the &lt;a href="http://www.gradle.org/current/docs/dsl/index.html"&gt;Gradle DSL documentation&lt;/a&gt;. &amp;nbsp;I had previously read the Gradle Users Guide but was still a bit fuzzy on what &amp;nbsp;the properties and methods were and how they were used. . &amp;nbsp; Reading the DSL documentation provides the full picture. &amp;nbsp;It also &amp;nbsp;helps drive home &amp;nbsp;that you are working with a programming language/DSL and not a set of XML tags like Ant and Maven.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Chapter 3, Ant and Gradle&amp;nbsp;&lt;/b&gt;&amp;nbsp;This chapter compares and contrasts Ant and Gradle. &amp;nbsp;It also demonstrates that Gradle can run Ant tasks by importing an Ant build.xml or by using the Ant Builder that is part of the Groovy distribution.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Chapter 4, Maven and Gradle&lt;/b&gt;&amp;nbsp; This &amp;nbsp;is the longest chapter in the book comprising &amp;nbsp;about 25% of the book. &amp;nbsp;Like all of the Gradle documentation, this book re-assures the reader that any previous investment in Maven or Ivy will not be lost in a move to Gradle. &amp;nbsp; Gradle provides support for Ivy, Maven's Central repository and a local repository.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Chapter 5, Testing with Gradle&lt;/b&gt;&amp;nbsp; This chapter is a &amp;nbsp;good overview of using &amp;nbsp;JUnit , TestNG, Spock, Geb and EasyB. &amp;nbsp;Coverage of testing is a bit light given the title of this book.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Chapter 6, &amp;nbsp;Multiproject Builds&lt;/b&gt;&amp;nbsp; This chapter &amp;nbsp;does a nice job of taking a sample project and showing three different approaches to creating the project build structure. &amp;nbsp;The approaches shown are one master build file, project-specific build files and a hybrid approach. &amp;nbsp;While the sample projects are very small, they provide the reader a starting point to converting their own multiproject builds.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;This is an excellent book for getting started with Gradle. &amp;nbsp; There are plenty of working examples provided in the source code download package. &amp;nbsp; The authors do a very good job of explaining the concepts and presenting alternative ways of expressing the same options within the DSL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;One minor issue is that matching up the downloaded source examples to the examples in the printed chapters is a bit of an exercise because they are not organized in a folder structure by chapter like many other books.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;Initially the slim size of the book worried me as to it's ability to provide a depth of coverage of Gradle, but the authors stated in the Preface that "Future volumes will cover the Gradle plug-in ecosystem, how to extend Gradle with your own business logic and even more advanced topics." &amp;nbsp; &amp;nbsp;Sounds good to me, bring it on Tim and Matthew!&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="font-weight: bold;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/uVbJcLKW-Oo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/3108571967228729039/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2011/07/book-review-building-and-testing-with.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/3108571967228729039?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/3108571967228729039?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/uVbJcLKW-Oo/book-review-building-and-testing-with.html" title="Book Review: Building and Testing with Gradle" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-hEzief4kBQo/TicVdM50t7I/AAAAAAAAAZU/Y0Y2NOdJiXM/s72-c/gradlebook.gif" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2011/07/book-review-building-and-testing-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEDQnk_fip7ImA9WhdTFkw.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-5976834143520873704</id><published>2011-07-13T23:44:00.000-05:00</published><updated>2011-07-13T23:44:33.746-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-13T23:44:33.746-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Gradle groovy nonversioned jars" /><title>Gradle dependencies with jars that have no version number</title><content type="html">I have seen presentations and read blogs and articles on &lt;a href="http://www.gradle.org/"&gt;Gradle&lt;/a&gt;.  It sounds pretty good. &amp;nbsp;Gradle is gathering momentum as some of the major players in the open source community (&lt;a href="http://java.dzone.com/polls/switch-gradle-good-move"&gt;Hibernate&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="http://forum.springsource.org/showthread.php?94976-Spring-Security-now-built-with-Gradle"&gt;Spring Security&lt;/a&gt;&amp;nbsp;to name a few) have switched their builds over to using Gradle. &amp;nbsp;I figured it is time to give it a try.&lt;br /&gt;
&lt;br /&gt;
The project I work on is fairly old, pre-Maven I suspect. &amp;nbsp;The project is a multi-layer, multi-component Java project built using Ant. &amp;nbsp;The project does not use Maven or Ivy. &amp;nbsp;The project includes a folder that contains all of our dependent jars. These jars are committed to SVN and included as part of the project when it is checked out. This way we have all the dependencies we need to build the project. &amp;nbsp;We have quite a few dependent jars that do &lt;b&gt;not &lt;/b&gt;have version numbers in the jar name. &amp;nbsp;Examples include a copy of junit.jar and log4j.jar. &amp;nbsp;This all existed before I started working on the project, so I have no idea how it got that way - it just is. &amp;nbsp;And since it's not really broken, we haven't attempted to fix it!&lt;br /&gt;
&lt;br /&gt;
Not having version numbers in the jars is a minor inconvienence. &amp;nbsp;If you read the Gradle User Guide chapter on &lt;a href="http://www.gradle.org/current/docs/userguide/userguide_single.html#dependency_management"&gt;Dependency Management&lt;/a&gt;, they seems to push dependency management for jars with version numbers. &amp;nbsp;Most of the examples shown in the documentation and elsewhere declare the dependencies as seen in Example 34.1 in Dependency Management chapter. &amp;nbsp;Great, but what do I do if I don't have version numbered jars in my dependencies? &amp;nbsp;I did not believe the Gradle guys would leave me hanging... &amp;nbsp;And they didn't! &lt;br /&gt;
&lt;br /&gt;
I really wanted to figure out how to setup my classpath to include these jars without version numbers. &amp;nbsp;I figured out how to do this and started writing this blog. &amp;nbsp; Then as I re-read the Dependency Management chapter, I saw a clue that I must have blown right by the first time I read it. &amp;nbsp;The clue is in &lt;a href="http://www.gradle.org/current/docs/userguide/userguide_single.html#sec:how_to_declare_your_dependencies"&gt;Section 34.3.5 File dependencies&lt;/a&gt;. &amp;nbsp;You can use the &lt;a href="http://www.gradle.org/current/docs/javadoc/org/gradle/api/file/FileTree.html"&gt;FileTree&amp;nbsp;&lt;/a&gt;&amp;nbsp;to help define the classpath to include these non-versioned jars.&lt;br /&gt;
&lt;br /&gt;
I created a small project called GradleTest that did not use the standard Java plugin conventions for the source and resource files and has dependencies in the "libs" folder, none of which have version numbers in the jar names.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-AxYLiYeASZ4/Th5r_YDoJKI/AAAAAAAAAZE/kn1FMXimo0I/s1600/gradle_project_structure.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/-AxYLiYeASZ4/Th5r_YDoJKI/AAAAAAAAAZE/kn1FMXimo0I/s400/gradle_project_structure.PNG" width="367" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;I created two different options, which both seem to work. &amp;nbsp;The first is shown below. &amp;nbsp;This option handles the dependencies more specifically, assigning just the jars that are needed for either compile or runtime.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;apply plugin: 'java'

sourceCompatibility = 1.6
version = '1.0'

sourceSets {
    main {
        java {
            srcDir 'src'
        }
        resources {
            srcDir 'resources'
        }
        compileClasspath += fileTree(dir: './libs', includes: ['**/log4j.jar'])
        runtimeClasspath = classes + sourceSets.main.classes + fileTree(dir: './libs', includes: ['**/log4j.jar'])
        
    }
    test {
        java {
            srcDir 'test'
        }
        resources {
            srcDir 'testresources'
        }
        compileClasspath += fileTree(dir: './libs', includes: ['**/junit.jar'])
        runtimeClasspath += classes + fileTree(dir: './libs', includes: ['**/junit.jar', '**/log4j.jar']) 
        
    }
}

sourceSets.main.classesDir = new File("./build/classes")
sourceSets.test.classesDir = new File("./build/classes")
&lt;/pre&gt;&lt;br /&gt;
The second option looks very similiar to the first option, &amp;nbsp;but uses the &lt;b&gt;dependencies &lt;/b&gt;definition and it cheats by assigning all the jars in the "libs" folder to both the compile and runtime classpath, rather than just exactly what is needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;apply plugin: 'java'

sourceCompatibility = 1.6
version = '1.0'

sourceSets {
    main {
        java {
            srcDir 'src'
        }
        resources {
            srcDir 'resources'
        }
        
    }
    test {
        java {
            srcDir 'test'
        }
        resources {
            srcDir 'testresources'
        }
        
    }
}

sourceSets.main.classesDir = new File("./build/classes")
sourceSets.test.classesDir = new File("./build/classes")

configurations {
    compile {
        description = 'compile classpath'
        transitive = true
    }
    runtime {
        extendsFrom compile
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    runtime fileTree(dir: 'libs', include: '*.jar')

}

&lt;/pre&gt;I am sure there are other, &amp;nbsp;possibly better or cleaner alternatives. &amp;nbsp;Please feel free to share improvements or other alternatives. &amp;nbsp; Hope this helps....&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/A5stZETgDMg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/5976834143520873704/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2011/07/gradle-dependencies-with-jars-that-have.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/5976834143520873704?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/5976834143520873704?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/A5stZETgDMg/gradle-dependencies-with-jars-that-have.html" title="Gradle dependencies with jars that have no version number" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-AxYLiYeASZ4/Th5r_YDoJKI/AAAAAAAAAZE/kn1FMXimo0I/s72-c/gradle_project_structure.PNG" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2011/07/gradle-dependencies-with-jars-that-have.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUCQXo4eyp7ImA9WhZWGU0.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-5858472154336806623</id><published>2011-05-19T22:06:00.001-05:00</published><updated>2011-05-20T09:04:20.433-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-20T09:04:20.433-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy gotcha databasemetadata array initialization" /><title>Groovy vs Java difference provides a WTF moment</title><content type="html">We all (should) know that not ALL Java is valid Groovy, but if you don't spend you day working in Groovy, then sometimes you forget these differences.&amp;nbsp;&amp;nbsp; These 'gotchas' are &lt;a href="http://groovy.codehaus.org/Differences+from+Java"&gt;documented here&lt;/a&gt; but who reads this stuff, right?&amp;nbsp; :-)&lt;br /&gt;
&lt;br /&gt;
I wanted to get &lt;a href="http://download.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html"&gt;DatabaseMetadata &lt;/a&gt;for a database, specifically a list of table names, so I started with a copy of Java code that already did the same thing.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;Class.forName(jdbcDriver);
Connection con = DriverManager.getConnection(jdbcURL, "root", "root");
DatabaseMetaData dbmd = con.getMetaData();
String[] tableTypes = { "TABLE" };
ResultSet allTables = dbmd.getTables(null, null, null, tableTypes);
System.out.println("processing tables...");
while (allTables.next()) {
    String table_name = allTables.getString("TABLE_NAME");
    System.out.println("processing table"+table_name);
}
&lt;/pre&gt;&lt;br /&gt;
Should be simple, right - drop the semi-colons and look for other opportunities to shorten the code using Groovy. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;def db = Sql.newInstance('jdbc:mysql://127.0.0.1:3306/mydb', 'root', 'root', 'com.mysql.jdbc.Driver')
def metaData = db.getConnection().getMetaData()
println("Driver Name: " + metaData.getDriverName())
println("Database Product: " + metaData.getDatabaseProductName())
println("Driver Name: "+ metaData.getDriverName())
println("Driver Version: "+ metaData.getDriverVersion())
String[] tableTypes = { "TABLE" }
ResultSet allTables = metaData.getTables(null, null, null, tableTypes)
while (allTables.next()) {
    String table_name = allTables.getString("TABLE_NAME")
    println "processing table "+table_name
}
&lt;/pre&gt;&lt;br /&gt;
And it &lt;b&gt;almost &lt;/b&gt;worked! &amp;nbsp; The thing that threw me was that not only does the code compile, but it also returns correct values for some of the methods in the DatabaseMetadata, but when it came time to iterate across the table names, there were none. &amp;nbsp;Come on, I just ran almost the exact code in Java and it spit out all the table names in my database. &amp;nbsp;What the heck did I mess up this time?&lt;br /&gt;
&lt;br /&gt;
My error was the 3rd bullet on the list of gotchas from above - how NOT to initialize an array in Groovy...&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;String[] tableTypesJava = { "TABLE" }
String[] tableTypesGroovy = [ "TABLE" ]
println tableTypesJava.class
println tableTypesGroovy.class
assertEquals(tableTypesGroovy, tableTypesJava)  // this will fail!
&lt;/pre&gt;&lt;br /&gt;
Both variables say they are String[] but tableTypesJava is really closure when compiled in Groovy!  The fix to the Groovy code is to use the brackets when initializing the array and not the braces - basically the &lt;b&gt;tableTypesGroovy &lt;/b&gt;from above.  Guess it's time to RTFM...&lt;br /&gt;
&lt;br /&gt;
Hope this helps!&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/Jdri0bcc1NU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/5858472154336806623/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2011/05/groovy-vs-java-difference-provides-wtf.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/5858472154336806623?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/5858472154336806623?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/Jdri0bcc1NU/groovy-vs-java-difference-provides-wtf.html" title="Groovy vs Java difference provides a WTF moment" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2011/05/groovy-vs-java-difference-provides-wtf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IFRXs8cSp7ImA9Wx9VFU8.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-8296285648114948943</id><published>2011-01-31T21:02:00.001-06:00</published><updated>2011-01-31T21:05:14.579-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-31T21:05:14.579-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grails AJAX groovy" /><title>Grails AJAX Examples</title><content type="html">Early on, newcomers to Grails encounter a lack of working samples accompanying the framework.&amp;nbsp; Good places for examples and documentation include the &lt;a href="http://www.grails.org/doc/latest/"&gt;Grails documentation&lt;/a&gt; and bloggers.&lt;br /&gt;
&lt;br /&gt;
Ajax is one of the features with built-in support by Grails. &amp;nbsp; Once people get their "head around" the Grails basics, they generally want to move onto more interesting features like Ajax.&amp;nbsp; This usually requires scouring the web, looking for examples and/or reading the documentation fairly closely.&amp;nbsp;&amp;nbsp; I went through this process and figured that others might benefit from a set of short working ajax examples in Grails.&amp;nbsp; I have created a small application that demonstrates some of the Ajax features and provide the application for download to anyone interested. (see bottom for download information)&lt;br /&gt;
&lt;br /&gt;
The example application uses each of the following:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;FormRemote&lt;/li&gt;
&lt;li&gt;RemoteLink&lt;/li&gt;
&lt;li&gt;SubmitToRemote&lt;/li&gt;
&lt;li&gt;RemoteFunction&lt;/li&gt;
&lt;li&gt;RemoteField&lt;/li&gt;
&lt;/ul&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&amp;nbsp;General Steps&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Pick your javascript library - prototype used in my example. Also shown is some Ajax event registration.&lt;/li&gt;
&lt;/ul&gt;&lt;pre class="brush:xml"&gt;&lt;g:javascript library="prototype"&gt;&lt;/g:javascript&gt;
&lt;g:javascript&gt;
     function showSpinner(visible) {
         $('spinner').style.display = visible ? "inline" : "none";
     }
     Ajax.Responders.register({
     onLoading: function() {
           showSpinner(true);
     },
     onComplete: function() {
     if(!Ajax.activeRequestCount) showSpinner(false);
     }
   });
&lt;/g:javascript&gt;
&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Update your controller with any code needed - below is my entire BookController&lt;/li&gt;
&lt;pre class="brush:groovy"&gt;package ajax

class BookController {

     def scaffold = true
  
  def showEditAjax = {
   render (view:'editAjax', model:[bookInstance:Book.get(params.id)])
  }
  
  def showListSelect = {
   render (view:'listSelect', model:[bookInstanceList:Book.list()])
  }
  
  def showTitleSearch = {
   render (view:'titleSearchAjax')
  }
  
  def showRemoteLink = {
   render (view:'remoteLink', model:[bookInstanceList:Book.list()])
  }
  
  def showDetails = {
   render(template:'bookDetails', model:[bookInstance:Book.get(params.id)])
  }
  
  def showSearch = {
   render (view:'searchAjax')
  }
  
  def String wrapSearchParm(value) {
   '%'+value+'%'
  }
  
  def searchTitle = {
   def list = Book.findAllByTitleIlike(wrapSearchParm(params.searchvalue))
   render(template:'searchResults', model:[searchresults:list])
  }
  
  def search = {
   def list
   if (params.publisher &amp;amp;&amp;amp; params.title)
    list = Book.findAllByTitleIlikeAndPublisherIlike(wrapSearchParm(params.title), wrapSearchParm(params.publisher))
   else if (params.publisher)
    list = Book.findAllByPublisherIlike(wrapSearchParm(params.publisher))
      else if (params.title)
       list = Book.findAllByTitleIlike(wrapSearchParm(params.title))
   
   render(template:'searchResults', model:[searchresults:list])
  }
  
  def listByPublisher = {
   def list
   if (params.filter.equals("All"))
    list = Book.list()
    else
      list = Book.findAllByPublisher(params.filter)
   
   render(template:'searchResults', model:[searchresults:list])
  }
  
 def update = {
  def bookInstance = Book.get( params.id )
  if(bookInstance) {
   bookInstance.properties = params
   if(!bookInstance.hasErrors() &amp;amp;&amp;amp; bookInstance.save()) {
    render "
&lt;h3&gt;Book ${params.title} updated with Ajax using FormRemote&lt;/h3&gt;"
   }
   else {
    render(view:'edit',model:[bookInstance:bookInstance])
   }
  }
  else {
   flash.message = "Book not found with id ${params.id}"
   redirect(action:edit,id:params.id)
  }
   
  }
  
}

&lt;/pre&gt;&lt;li&gt;Create/update view(s) - See screen shots below and/or download the application&lt;/li&gt;
&lt;/ul&gt;&lt;ol&gt;&lt;/ol&gt;Most of the examples are fairly straight forward and should not need a lot of explanation. &amp;nbsp;They may not be great 'real world' examples but the intention is to provide a working example for someone to start from.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;FormRemote&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;The &lt;a href="http://grails.org/doc/latest/ref/Tags/formRemote.html"&gt;formRemote&lt;/a&gt; taglib creates a form tag that uses a remote uri to execute an ajax call.&amp;nbsp; In this case, I have slightly modified the default generated edit.gsp to change the form tag to a formRemote tag and added a div to show the edit results.&amp;nbsp;&amp;nbsp; The screen shot below shows the result of first clicking the Form Remote navigation menu button, changing the number of pages in the 'Grails in Action' book and pressing the Update button at the bottom of the screen.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_JAJdxIvTyzE/TUY9fUG8qKI/AAAAAAAAAXs/jJhmoCqCYdE/s1600/formremote.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="402" src="http://3.bp.blogspot.com/_JAJdxIvTyzE/TUY9fUG8qKI/AAAAAAAAAXs/jJhmoCqCYdE/s640/formremote.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;RemoteLink&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;The &lt;a href="http://grails.org/doc/latest/ref/Tags/remoteLink.html"&gt;RemoteLink&lt;/a&gt; tag creates a link that calls a remote function when clicked.&amp;nbsp; In the example application,&amp;nbsp; I display a list of book titles and the title is a link.&amp;nbsp; Clicking on the title shows the book details at the bottom of the screen.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&lt;g:each in="${bookInstanceList}" status="i" var="bookInstance"&gt;
    &lt;g:remotelink action="showDetails" id="${bookInstance.id}" oncomplete="showSpinner(false);" onloading="showSpinner(true);" update="bookDetails"&gt;${fieldValue(bean: bookInstance, field: "title")}&lt;/g:remotelink&gt;    
&lt;/g:each&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_JAJdxIvTyzE/TUD1M_zCTII/AAAAAAAAAXo/96Y7CWtW9qE/s1600/remoteLink.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="428" src="http://2.bp.blogspot.com/_JAJdxIvTyzE/TUD1M_zCTII/AAAAAAAAAXo/96Y7CWtW9qE/s640/remoteLink.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;SubmitToRemote&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="border-collapse: separate; color: black; font-family: 'Times New Roman'; font-size: small; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: Tahoma,Verdana,Arial; font-size: 15px;"&gt;The &lt;a href="http://grails.org/doc/latest/ref/Tags/submitToRemote.html"&gt;submitToRemote&lt;/a&gt; tag creates a button that submits the surrounding form as a remote Ajax call serializing the fields into parameters.&amp;nbsp; In the example application, I created search fields for Title and Publisher.&amp;nbsp; The search button was created using the SubmitToRemote taglib to submit the search parameters using Ajax. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: monospace; white-space: pre;"&gt;    &lt;/span&gt;&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&lt;g:form action="search"&gt;&lt;table&gt;&lt;tbody&gt;
&lt;tr class="prop"&gt;             &lt;td class="name" valign="top"&gt;Title:&lt;/td&gt;             &lt;td class="value" valign="top"&gt;&lt;input name="title" type="text" value="${title}" /&gt;&lt;/td&gt;          &lt;/tr&gt;
&lt;tr class="prop"&gt;             &lt;td class="name" valign="top"&gt;Publisher:&lt;/td&gt;             &lt;td class="value" valign="top"&gt;&lt;input name="publisher" type="text" value="${publisher}" /&gt;&lt;/td&gt;          &lt;/tr&gt;
&lt;/tbody&gt;      &lt;/table&gt;&lt;g:submittoremote oncomplete="showSpinner(false)" onloading="showSpinner(true)" update="searchresults" url="[controller:'book', action:'search']" value="Search"&gt;
&lt;/g:submittoremote&gt;&lt;/g:form&gt;&lt;/pre&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_JAJdxIvTyzE/TUD1LwFWoDI/AAAAAAAAAXc/NysUGX8J5iI/s1600/submitToRemote.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="428" src="http://2.bp.blogspot.com/_JAJdxIvTyzE/TUD1LwFWoDI/AAAAAAAAAXc/NysUGX8J5iI/s640/submitToRemote.PNG" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;RemoteFunction&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;The example application uses the &lt;a href="http://grails.org/doc/latest/ref/Tags/remoteFunction.html"&gt;RemoteFunction&lt;/a&gt; taglib to create a remote javascript function that is assigned to the onChange DOM event.&amp;nbsp; When the user selects or changes the value in the Publisher dropdown list, the remote function is called and the bottom half of the screen displays books published by the selected Publisher.&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_JAJdxIvTyzE/TUD1Mrp-kHI/AAAAAAAAAXk/yV4e2_0DGUQ/s1600/remoteFunction.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="428" src="http://1.bp.blogspot.com/_JAJdxIvTyzE/TUD1Mrp-kHI/AAAAAAAAAXk/yV4e2_0DGUQ/s640/remoteFunction.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;RemoteField&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;The example application uses the &lt;a href="http://grails.org/doc/latest/ref/Tags/remoteField.html"&gt;RemoteField&lt;/a&gt; taglib to create a dynamic search for Book titles, similar to Google Instant.&amp;nbsp; Search results are returned the screen as you type values in the Title Search field.&amp;nbsp;&amp;nbsp; The controller code in this case,&amp;nbsp; wraps the search parameter with the wild card character (%) to search the database and returns all matches to be displayed.&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&lt;div id="searchbox"&gt;Title Search: 
&lt;g:remotefield name="search" oncomplete="showSpinner(false);" onloading="showSpinner(true);" paramname="searchvalue" update="searchresults" url="[controller:'book', action:'searchTitle']"&gt;
&lt;/g:remotefield&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_JAJdxIvTyzE/TUD1MUvRXQI/AAAAAAAAAXg/RA5gKvflA34/s1600/remoteField.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="428" src="http://1.bp.blogspot.com/_JAJdxIvTyzE/TUD1MUvRXQI/AAAAAAAAAXg/RA5gKvflA34/s640/remoteField.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Problems Encountered&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;I ran into problems trying to get the spinner to show correctly until I found this&amp;nbsp;&lt;a href="http://stackoverflow.com/questions/759049/how-to-use-onloading-event-in-grails-remotefunction"&gt;entry on StackOverflow&lt;/a&gt;&amp;nbsp;that showed how to register the Ajax events. &amp;nbsp;When running locally on the same box, this happens very fast so you really need to keep and eye on the upper right corner of the screen if you want to see the spinner.&lt;/li&gt;
&lt;li&gt;I also ran into problems with the RemoteFunction due to syntax problems. &amp;nbsp;Being used to the taglibs, &amp;nbsp;I was setting the update parameter using update="mydiv" when the syntax should have been update:"mydiv". &amp;nbsp;This did not flag as an error. &amp;nbsp;The controller was called, it just never updated the target div!&lt;/li&gt;
&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Downloads&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;a href="http://sites.google.com/site/mikesgroovystuff/home/downloads"&gt;Download a zip from here&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="git://github.com/mikemil/AjaxExamples.git"&gt;Get a copy from Github &lt;/a&gt;- this is my first crack at creating&amp;nbsp; a repo at Github, so if I did it wrong, please let me know.&lt;/li&gt;
&lt;/ul&gt;It was fun putting this together. &amp;nbsp; Hope it helps some of you!&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/p8fyXoaiVBo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/8296285648114948943/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2011/01/grails-ajax-examples.html#comment-form" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/8296285648114948943?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/8296285648114948943?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/p8fyXoaiVBo/grails-ajax-examples.html" title="Grails AJAX Examples" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_JAJdxIvTyzE/TUY9fUG8qKI/AAAAAAAAAXs/jJhmoCqCYdE/s72-c/formremote.PNG" height="72" width="72" /><thr:total>12</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2011/01/grails-ajax-examples.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcMR346fip7ImA9Wx9TE0w.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-4649220514750253376</id><published>2010-11-20T22:18:00.000-06:00</published><updated>2010-11-20T22:18:06.016-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-20T22:18:06.016-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="shutterfly holiday cards" /><title>Shutterfly Holiday Collection</title><content type="html">&lt;div class="ecxMsoNormal"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;We have used  Shutterfly to create family albums and mouse pads in the past.&amp;nbsp; I  have found the quality of the albums from Shutterfly is great.&amp;nbsp; The  album pictures are clear and sharp.&amp;nbsp; Based on our past experiences  and quality of products that we’ve received, we’re excited about using&amp;nbsp;Shutterfly for our Christmas cards this year.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;I  have found the Shutterfly Christmas card &lt;a href="http://www.shutterfly.com/cards-stationery/christmas-cards"&gt;selection &lt;/a&gt;is tremendous.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;&amp;nbsp;In particular, my  family was pleased at the number of religious photo cards that are  available.&amp;nbsp; We particularly like the following photo  cards: &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;&lt;a href="http://www.shutterfly.com/cards-stationery/cards-stationery/rejoice-lord-king-religious-christmas-5x7-folded-card?sortType=1&amp;amp;fa=8&amp;amp;storeNode=60217"&gt;&amp;nbsp;&lt;/a&gt;&lt;a href="http://www.shutterfly.com/cards-stationery/cards-stationery/rejoice-lord-king-religious-christmas-5x7-folded-card?sortType=1&amp;amp;fa=8&amp;amp;storeNode=60217"&gt;here&amp;nbsp;&lt;/a&gt;and &amp;nbsp;&lt;a href="http://www.shutterfly.com/cards-stationery/cards-stationery/faith-hope-family-religious-christmas-card-5x7-flat?sortType=1&amp;amp;fa=8&amp;amp;storeNode=60217"&gt;here&amp;nbsp;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;.&amp;nbsp;&amp;nbsp; The cards in the links  above allow us to include four to five pictures of our family so that we don’t  have to agonize of picking the one best picture!&amp;nbsp; Our plan is to  use one of these photo cards for the dual purpose of spreading the message of  the season, as we believe it, and to share pictures of our family with loved  ones and friends.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;Enjoy the selection from Shutterfly and Happy Holidays!!!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Times New Roman';"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/Abb4ZiFjxOc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/4649220514750253376/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2010/11/shutterfly-holiday-collection.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/4649220514750253376?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/4649220514750253376?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/Abb4ZiFjxOc/shutterfly-holiday-collection.html" title="Shutterfly Holiday Collection" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2010/11/shutterfly-holiday-collection.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IDSHgzeSp7ImA9Wx5UFk8.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-2652373781198326043</id><published>2010-10-20T21:52:00.000-05:00</published><updated>2010-10-20T21:52:59.681-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-20T21:52:59.681-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy GString SQL" /><title>Be careful using GStrings for SQL</title><content type="html">If you are like me, you love the ease with which you can create Groovy scripts to manipulate your databases.  Gone are the days of writing utility classes to make these changes, thanks to Groovy and the &lt;a href="http://groovy.codehaus.org/gapi/"&gt;SQL &lt;/a&gt;package.  But if you aren't careful, you can run into a couple of strange errors if you use the GStrings.&lt;br /&gt;
&lt;br /&gt;
For the below example, I have a table named LOCATION in my 'test' database that has two columns: location_id and location_name.  The example below works fine and you notice that I am not using any variables in the SQL statement &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;import groovy.sql.Sql

db = Sql.newInstance('jdbc:mysql://127.0.0.1:3306/test', 'root', 'root', 'com.mysql.jdbc.Driver')

def sqlStatement = """select * from location where location_id &gt; 3"""

db.eachRow (sqlStatement){ 
   println it
}

println "Done!"
&lt;/pre&gt;&lt;br /&gt;
Next, try making the SQL a bit more dynamic by specifying the table name, column name and key value as variables within the GString and watch what happens.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;import groovy.sql.Sql

db = Sql.newInstance('jdbc:mysql://127.0.0.1:3306/test', 'root', 'root', 'com.mysql.jdbc.Driver')

def tableName = 'location'
def columnName = 'location_id'
def key = 3
def sqlStatement = """select * from $tableName where $columnName &gt; $key"""

db.eachRow (sqlStatement){ 
   println it
}

println "Done!"
&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="brush:plain"&gt;WARNING: Failed to execute: select * from ? where ? &gt; ? because: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''location' where 'location_id' &gt; 3' at line 1
&lt;/pre&gt;&lt;br /&gt;
The quick fix I found was to call the toString() method on the GString and this resolves the problem. I found a line in "&lt;a href="http://www.manning.com/koenig/"&gt;Groovy In Action&lt;/a&gt;" which helps explain the problem:  &lt;blockquote&gt;&lt;b&gt;The special use of GStrings as SQL statements limits the use of placeholders to places where a question mark would otherwise be allowed in a prepared statement.&lt;/b&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;import groovy.sql.Sql

db = Sql.newInstance('jdbc:mysql://127.0.0.1:3306/test', 'root', 'root', 'com.mysql.jdbc.Driver')

def tableName = 'location'
def columnName = 'location_id'
def key = 3
def sqlStatement = """select * from $tableName where $columnName &gt; $key""".toString()

db.eachRow (sqlStatement){ 
   println it
}

println "Done!"
&lt;/pre&gt;&lt;br /&gt;
Keep this in mind the next time you use the Groovy SQL class!&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/hlhMoYzhFOk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/2652373781198326043/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2010/10/be-careful-using-gstrings-for-sql.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/2652373781198326043?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/2652373781198326043?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/hlhMoYzhFOk/be-careful-using-gstrings-for-sql.html" title="Be careful using GStrings for SQL" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>7</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2010/10/be-careful-using-gstrings-for-sql.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMGRnszfip7ImA9Wx5TFU8.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-1157349083011530536</id><published>2010-07-30T16:13:00.000-05:00</published><updated>2010-07-30T16:13:47.586-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-30T16:13:47.586-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ant" /><title>Get value from SQL into an Ant property</title><content type="html">Recently I had to adjust some of our JMS configuration and needed make sure we set the ServerPeerID configuration value to a unique value among our servers.  We have a unique server number in our database so I figured that I would just use that value.  In order to do this, I needed to get the database value into an Ant property, which is then used to generate the configuration file, which includes the ServerPeerID.  Below is the Ant task and steps I used to do this.&lt;br /&gt;
&lt;br /&gt;
Steps:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Define where the SQL results will be written&lt;/li&gt;
&lt;li&gt;Make sure the file does not already exist&lt;/li&gt;
&lt;li&gt;SQL task to get the result&lt;/li&gt;
&lt;li&gt;Load the file back into a property&lt;br /&gt;
&lt;/li&gt;
Use the propertyregex task to strip out just the unique number  &lt;/ol&gt;&lt;br /&gt;
&lt;strong&gt;Warning:&lt;/strong&gt; The syntax highlighter appears to be reformatting my XML and not allowing the self closing tags.  Probably my problem but you should be able to get the idea from the &lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;&lt;pre class="brush:xml"&gt;&lt;target name="setstorenumber"&gt;
   &lt;property name="sql.output.file" value="storenumber.txt"&gt;
   &lt;delete file="${sql.output.file}" quiet="true"&gt;
   &lt;sql driver="${store.database.driver}" output="${sql.output.file}" password="root" print="true" showheaders="false" url="your_database_url_goes_here" userid="root"&gt;
      &lt;classpath refid="jboss.classpath"&gt;
      SELECT PREF_VALUE FROM PREFERENCE WHERE PREFERENCE_ID = 71;                
    &lt;/classpath&gt;
     
    &lt;loadfile property="store.number" srcfile="${sql.output.file}"&gt;
    &lt;propertyregex input="${store.number}" property="server.peer.id" 
     regexp="(\d*).*" select="\1"&gt;
&lt;/propertyregex&gt;&lt;/loadfile&gt;&lt;/sql&gt;&lt;/delete&gt;&lt;/property&gt;&lt;/target&gt;&lt;b&gt;
&lt;/b&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/TpRSfJ4hEPg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/1157349083011530536/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2010/07/get-value-from-sql-into-ant-property.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1157349083011530536?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/1157349083011530536?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/TpRSfJ4hEPg/get-value-from-sql-into-ant-property.html" title="Get value from SQL into an Ant property" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2010/07/get-value-from-sql-into-ant-property.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IMQH04cCp7ImA9WxFRFUw.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-3218373276333837058</id><published>2010-04-28T23:31:00.002-05:00</published><updated>2010-04-28T23:33:01.338-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-28T23:33:01.338-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy sockets serversocket client" /><title>Groovy Sockets example</title><content type="html">I found several &lt;a href="http://pleac.sourceforge.net/pleac_groovy/sockets.html"&gt;sites&lt;/a&gt; and blogs with Groovy socket examples but none that showed a matched pair of the server and the client sending data back and forth.  Collecting bits from different sources, I put together the following server and client scripts using Groovy.  &lt;br /&gt;
&lt;br /&gt;
The sample works by sending a line of data as a request; thus the server calls readLine() and the client sends a new line character at the end of the input.   The server echos the request back to the client along with a timestamp.  For those that skip reading the documentation, ServerSocket's &lt;a href="http://groovy.codehaus.org/groovy-jdk/java/net/ServerSocket.html"&gt;accept&lt;/a&gt; method "Accepts a connection and passes the resulting Socket to the closure which runs in a new Thread." so this server creates a new thread for each request.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Groovy Socket server&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;import java.net.ServerSocket
def server = new ServerSocket(4444)

while(true) {
    server.accept { socket -&gt;
        println "processing new connection..." 
        socket.withStreams { input, output -&gt;
            def reader = input.newReader()
            def buffer = reader.readLine()
            println "server received: $buffer"
            now = new Date()
            output &lt;&lt; "echo-response($now): " + buffer + "\n"
        }
        println "processing/thread complete."
    }
}
&lt;/pre&gt;
&lt;b&gt;Groovy Socket client&lt;/b&gt;

&lt;pre class="brush:groovy"&gt;s = new Socket("localhost", 4444);
s.withStreams { input, output -&gt;
  output &lt;&lt; "echo testing ...\n"
  buffer = input.newReader().readLine()
  println "response = $buffer"
}
&lt;/pre&gt;
&lt;br /&gt;
Give it try!  Hope this helps...&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/tho7r8P7M3M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/3218373276333837058/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2010/04/groovy-sockets-example.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/3218373276333837058?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/3218373276333837058?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/tho7r8P7M3M/groovy-sockets-example.html" title="Groovy Sockets example" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2010/04/groovy-sockets-example.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUDSHg7cSp7ImA9WxFREU4.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-5798737773477506620</id><published>2010-04-24T14:44:00.000-05:00</published><updated>2010-04-24T14:44:39.609-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-24T14:44:39.609-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="webstart web start jnlp javaws_vm_args" /><title>Trouble connecting to Web Start client?</title><content type="html">Do you have problems getting either the debugger or JConsole attached or connected to your Web Start client?&amp;nbsp; We worked around this for way too long until we finally found the trick: environment variable JAVAWS_VM_ARGS.&lt;br /&gt;
&lt;br /&gt;
JNLP allows for&lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/faq.html#203"&gt; vm args to be passed to the Java runtime&lt;/a&gt; but there is a limited set of arguments that are allowed to be passed on.&amp;nbsp; Anything not in that list of secure properties is ignored.&amp;nbsp; You can find the list of secure properties in the &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/syntax.html"&gt;Developers Guide.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
As I said ealier, if you want to attach a debugger or JConsole to you Web Start application, then you need to use the JAVAWS_VM_ARGS parameter.&amp;nbsp;&amp;nbsp; For example, if I want to attached to my web start client for debugging purposes then I can do the following:&lt;br /&gt;
&lt;br /&gt;
set &lt;span class="searchTerm"&gt;JAVAWS&lt;/span&gt;_&lt;span class="searchTerm"&gt;VM&lt;/span&gt;_&lt;span class="searchTerm"&gt;ARGS&lt;/span&gt;=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
in my environment, start the client and then attach to the process using port 5005.&amp;nbsp; The same goes for attaching to JConsole, set the properties you need in JAVAWS_VM_ARGS, so com.sun.management.jmxremote.* should all be set inside JAVAWS_VM_ARGS.&lt;br /&gt;
&lt;br /&gt;
Hope this help!!!&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/ZleWz9sOzuY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/5798737773477506620/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2010/04/trouble-connecting-to-web-start-client.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/5798737773477506620?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/5798737773477506620?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/ZleWz9sOzuY/trouble-connecting-to-web-start-client.html" title="Trouble connecting to Web Start client?" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2010/04/trouble-connecting-to-web-start-client.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QGQXw9cSp7ImA9WxBRFUo.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-6596005734302980688</id><published>2010-01-03T22:28:00.000-06:00</published><updated>2010-01-03T22:28:40.269-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-03T22:28:40.269-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy html MarkupBuilder" /><title>Ant task ported to Groovy - Part 3</title><content type="html">Welcome to the final posting of this series where I have been porting one of my Ant tasks from Java to Groovy.&amp;nbsp; If you haven't read &lt;a href="http://programmingitch.blogspot.com/2009/12/java-ant-task-ported-to-groovy-part-1.html"&gt;part 1&lt;/a&gt; or &lt;a href="http://programmingitch.blogspot.com/2009/12/ant-task-ported-to-groovy-part-2.html"&gt;part 2&lt;/a&gt;, then you might want to take a quick pass through those before reading this posting.&amp;nbsp; In this posting, I will show the following:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;FileValidator class ported to Groovy&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Using HTML Builder to generate the HTML report&amp;nbsp; &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Full listings of the scripts &amp;amp; classes created&lt;/li&gt;
&lt;/ul&gt;&lt;b&gt;FileValidator ported to Groovy&lt;/b&gt;&lt;br /&gt;
One of the last tasks left to do is to port the &lt;i&gt;FileValidator &lt;/i&gt;class from Java over to Groovy.&amp;nbsp; The &lt;i&gt;FileValidator&lt;/i&gt; class is created in the process() method of the &lt;i&gt;Validator &lt;/i&gt;class and called for every file to be validated.&amp;nbsp; This is another example of where the Groovy code is a lot shorter and more concise than the Java code.&amp;nbsp;&amp;nbsp; The &lt;i&gt;FileValidator &lt;/i&gt;class handles the iteration thru a file, line by line, checking each regular expression checking for a potential error condition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;

/**
 * File validator runs a list of regular expressions against the file
 * attempting to validate the file.  Errors are kept in a list and
 * then the caller can get the list of errors and log them - right
 * now the ant task will log them. 
 *
 */
public class FileValidator {

    private List regExDescriptors;
    private File file;
    private List errors;
    
    /**
     * Default constructor
     * @param list List of RegExDescriptors used to validate a file
     * @param file File to be validated
     */
    public FileValidator(List list, File file) {
        regExDescriptors = new ArrayList(list);
        this.file = file;
        errors = new ArrayList();
    }
    
    public List getErrors() {
        return errors;
    }
    
    public void validate() {
      // see if we should exclude this file  
      processExcludes();
      
      // Run the regEx(s) against the file to check for problems
      BufferedReader in = null;
      try {
          in = new BufferedReader(new FileReader(file));
          String str;
          int lineNumber = 1;
          while ((str = in.readLine()) != null) {
              for (Iterator iter = regExDescriptors.iterator(); iter.hasNext();) {
                  RegExDescriptor validator = (RegExDescriptor) iter.next();
                  Matcher matcher = validator.getMatcher(str);
                  if (matcher.find()) {
                   errors.add( validator.getDescription() + " on line " + lineNumber);
                  }
              }
              lineNumber++;
          }
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          if (in != null)
              try {
                  in.close();
              } catch (IOException e) {
              }
      }  
    }

    private void processExcludes()
    {
        String fullName;
        try
        {
            fullName = file.getCanonicalPath();
        }
        catch (IOException e)
        {
            fullName = file.getName();
            e.printStackTrace();
        }
        for (Iterator iter = regExDescriptors.iterator(); iter.hasNext();)
        {
            RegExDescriptor descriptor = (RegExDescriptor) iter.next();
            if (descriptor.excludeFile(fullName))
            {
                iter.remove();
            }
        }
    }    
}&amp;nbsp;&lt;/pre&gt;&lt;b&gt;Groovy code for file validation&lt;/b&gt;&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;//**************************************
// process each file, line by line
//**************************************
files.each {fileName -&amp;gt;
  def errors = []
  def lines = new File(fileName).readLines()
  def lineNumber = 1
  lines.each {line -&amp;gt;
    // for each line - iterate thru descriptors looking for matches if file not excluded
    descriptorList.each {
      if (!(fileName =~ /$it.exclude/)) {
        if ((line =~ /$it.regex/).find()) {
          errors.add(it.description + " on line " + lineNumber)
          errCnt++
        }
      }
    }
    lineNumber++
  }
  if (errors)
    results.put((fileName), errors)
}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Generating the results report&lt;/b&gt;&lt;br /&gt;
The last part of the port was to create an html output report similar to a JUnit report.&amp;nbsp; The Java code could have been better but it was simply a large set of write statements.&amp;nbsp; I decided to use the HTML markup builder to generate the output report. &lt;br /&gt;
&lt;pre class="brush:groovy"&gt;//*******************************************************
// generate the report
//*******************************************************
def writer = new FileWriter("$opt.r")
def html = new groovy.xml.MarkupBuilder(writer)
def rptDate = new Date()

html.html {
  head{
    title 'Validator Report'
  }
  body {
    h1 "File Validation - as of $rptDate"
    h2 "Validation Descriptors for file extension $opt.e"
    table ('border':0, 'cellpadding':5, 'cellspacing':2, 'width':'80%'){
      tr ('bgcolor':'#a6caf0') {
        th ("Description")
        th ("Validating Regular Expression")
      }
      //iterate thru descriptors - listing the regular expressions used in validation
      descriptorList.each { descriptor -&amp;gt;
        tr ('bgcolor':'#eeeee0') {
          td (descriptor.description)
          td (descriptor.regex)
        }
      }
    }
    // Summary table - just a file &amp;amp; error count
    h2 'Validation Summary'
    table ('border':0, 'cellpadding':5, 'cellspacing':2, 'width':'80%'){
      tr ('bgcolor':'#a6caf0') {
        th ("Files Processed")
        th ("Error Count")
      }
      tr ('bgcolor':'#eeeee0')  {
        td ("$files.size")
        td ("$errCnt")
      }
    }
    if (errCnt)
    {
      // Error details table
      h2 "Validation Details for extension $opt.e "
      table ('border':0, 'cellpadding':5, 'cellspacing':2, 'width':'100%'){
        tr ('bgcolor':'#a6caf0') {
          th ("File")
          th ("Errors")
          th ("Details")
        }
        //iterate thru results map key is filename and value is list of error text)
        results.each { k, v -&amp;gt;
            tr ('bgcolor':'#eeeee0')  {
               td (k)
               td (v.size())
               td {
                 ul {
                   //iterate thru the list of errors
                   v.each {
                     li (it)
                   }
                 }
               }
            }
        }
      }
    }
  }
}
writer.toString()

&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Porting Results&lt;/b&gt;&lt;br /&gt;
Initial Java Ant task:&amp;nbsp; 3 classes and 326 lines of code&lt;br /&gt;
Groovy port: 1 script of 102 lines of code and 1 class with 9 lines of code.&amp;nbsp;&amp;nbsp; There are about 40 lines of processing code and the rest of the code/lines are from the html markup builder for the report.&lt;br /&gt;
&lt;br /&gt;
Shorter and more concise, you decide! &amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Groovy script and class source&lt;/b&gt;&lt;br /&gt;
Here's the full Validator.groovy script&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;/**
 *  Validator script ported from Java Ant task
 */

//********************************************
// handle command line parms - all required
//********************************************
def cli = new CliBuilder(usage: 'groovy Validator -e extension -p propertyFile -d directory -r reportFile')

cli.h(longOpt: 'help', 'usage information')
cli.e(longOpt: 'extension', args: 1, required: true, 'file extension to be validated')
cli.p(longOpt: 'prop', args: 1, required: true, 'property file containing regular expresssion')
cli.d(longOpt: 'directory', args: 1, required: true, 'base directory to start file search')
cli.r(longOpt: 'reportFile', args: 1, required: true, 'output file for validation report')

def opt = cli.parse(args)
if (!opt) return
if (opt.h) cli.usage()

println "Processing $opt.e files \n\tusing $opt.p \n\tfrom directory $opt.d \n\tand generate report output to $opt.r"
println 'extracting files...'

//*******************************************
// get all the files for provided extension
//*******************************************
def files = new FileNameFinder().getFileNames(opt.d, "**/*.$opt.e")
println "processing $files.size files..."

//**************************************************************
// load properties into list of ValidatorDescriptor objects
//**************************************************************
Properties properties = new Properties();
try {
  properties.load(new FileInputStream(opt.p));
} catch (IOException e) {}

def config = new ConfigSlurper().parse(properties)
def descriptorList = []
config."$opt.e".each {
  descriptorList &amp;lt;&amp;lt; new ValidatorDescriptor(it.value)
}

def errCnt = 0
def results = [:]

//**************************************
// process each file, line by line
//**************************************
files.each {fileName -&amp;gt;
  def errors = []
  def lines = new File(fileName).readLines()
  def lineNumber = 1
  lines.each {line -&amp;gt;
    // for each line - iterate thru descriptors looking for matches if file not excluded
    descriptorList.each {
      if (!(fileName =~ /$it.exclude/)) {
        if ((line =~ /$it.regex/).find()) {
          errors.add(it.description + " on line " + lineNumber)
          errCnt++
        }
      }
    }
    lineNumber++
  }
  if (errors)
    results.put((fileName), errors)
}

//*******************************************************
// generate the report
//*******************************************************
def writer = new FileWriter("$opt.r")
def html = new groovy.xml.MarkupBuilder(writer)
def rptDate = new Date()

html.html {
  head{
    title 'Validator Report'
  }
  body {
    h1 "File Validation - as of $rptDate"
    h2 "Validation Descriptors for file extension $opt.e"
    table ('border':0, 'cellpadding':5, 'cellspacing':2, 'width':'80%'){
      tr ('bgcolor':'#a6caf0') {
        th ("Description")
        th ("Validating Regular Expression")
      }
      //iterate thru descriptors - listing the regular expressions used in validation
      descriptorList.each { descriptor -&amp;gt;
        tr ('bgcolor':'#eeeee0') {
          td (descriptor.description)
          td (descriptor.regex)
        }
      }
    }
    // Summary table - just a file &amp;amp; error count
    h2 'Validation Summary'
    table ('border':0, 'cellpadding':5, 'cellspacing':2, 'width':'80%'){
      tr ('bgcolor':'#a6caf0') {
        th ("Files Processed")
        th ("Error Count")
      }
      tr ('bgcolor':'#eeeee0')  {
        td ("$files.size")
        td ("$errCnt")
      }
    }
    if (errCnt)
    {
      // Error details table
      h2 "Validation Details for extension $opt.e "
      table ('border':0, 'cellpadding':5, 'cellspacing':2, 'width':'100%'){
        tr ('bgcolor':'#a6caf0') {
          th ("File")
          th ("Errors")
          th ("Details")
        }
        //iterate thru results map key is filename and value is list of error text)
        results.each { k, v -&amp;gt;
            tr ('bgcolor':'#eeeee0')  {
               td (k)
               td (v.size())
               td {
                 ul {
                   //iterate thru the list of errors
                   v.each {
                     li (it)
                   }
                 }
               }
            }
        }
      }
    }
  }
}
writer.toString()

println "validation complete - possible error count = $errCnt"

//********************************
// for testing launch browser
//********************************
//"c:/program files/Internet Explorer/iexplore.exe $opt.r".execute()
&lt;/pre&gt;&lt;br /&gt;
Here's the one short class - ValidatorDescriptor.groovy&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;class ValidatorDescriptor {
    String description
    String exclude
    String regex

    String toString() {
       "regEx="+regex + " description=" + description + (exclude ? " exclude("+exclude+")" : "")
    }
}
&lt;/pre&gt;&lt;br /&gt;
And finally, my set of properties used for validation:&lt;br /&gt;
&lt;pre class="brush:text"&gt;#################################################################
#
# SQL file regular expressions
#
#################################################################

#
# Find instances of trailing spaces after the semicolon.
# This causes MySQL problems.
#
#
sql.1.regex=;\\s+$
sql.1.description=Trailing spaces after semicolon
sql.1.exclude=SQLServer|Oracle

#
# Instances of lines starting with GO
#
sql.2.regex=^GO
sql.2.description=GO statement


#
# Find spaces before ending semicolon (but not DELIMITER ; which is used for MySQL Stored Procedures)
#
sql.4.regex=^(?!DELIMITER)\\s+;$
sql.4.description=Spaces before ending semicolon
sql.4.exclude=SQLServer|Oracle


#
# Oracle scripts using nvarchar
#
#
sql.5.regex=nvarchar
sql.5.description=Oracle scripts using nvarchar
sql.5.exclude=SQLServer|MySQL|Store Update

#
# MySQL scripts using ntext
#
#
sql.6.regex=\\sntext
sql.6.description=MySQL scripts using ntext data type
sql.6.exclude=SQLServer|Oracle
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
There you go - another itch successfully scratched!&amp;nbsp;&amp;nbsp; Maybe this task/script will be of help to others.&amp;nbsp; The design was to make this a generic file validation utility and the SQL validation is the only use we have found so far.&amp;nbsp; Enjoy!&lt;br /&gt;
&lt;b&gt; &lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/cH5BAHAMv_g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/6596005734302980688/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2010/01/ant-task-ported-to-groovy-part-3.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/6596005734302980688?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/6596005734302980688?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/cH5BAHAMv_g/ant-task-ported-to-groovy-part-3.html" title="Ant task ported to Groovy - Part 3" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2010/01/ant-task-ported-to-groovy-part-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cCRXc_fyp7ImA9WxBSFEs.&quot;"><id>tag:blogger.com,1999:blog-7371895490737388670.post-7988869346073663085</id><published>2009-12-21T23:44:00.004-06:00</published><updated>2009-12-21T23:51:04.947-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-21T23:51:04.947-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy CliBuilder ConfigSlurper" /><title>Ant task ported to Groovy - Part 2</title><content type="html">Welcome back if you read&lt;a href="http://programmingitch.blogspot.com/2009/12/java-ant-task-ported-to-groovy-part-1.html"&gt; part 1&lt;/a&gt; of this posting.&amp;nbsp; If you haven't read part 1, you may want to take a quick look at that before reading this part of the posting.&amp;nbsp; This posting (part 2) will show the following changes or ports from Java to Groovy for the validator ant task.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://groovy.codehaus.org/gapi/groovy/util/CliBuilder.html"&gt;CliBuilder &lt;/a&gt;for command line interface&lt;/li&gt;
&lt;li&gt;ValidatorDescriptor class&lt;/li&gt;
&lt;li&gt;Consuming the properties file&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;b&gt;Switch from Ant to a Groovy task&lt;/b&gt; &lt;br /&gt;
As I mentioned in part 1, this port will not be an exact port because I am creating a groovy script rather than an Ant/Gant task - partly because I haven't played with Gant yet!&amp;nbsp; Some of the existing Ant task code is shown below.  For those familiar with creating Ant tasks, you will notice the class extends &lt;i&gt;Task&lt;/i&gt; which is an abstract class.&amp;nbsp;&amp;nbsp; The code overrides the execute() method. &amp;nbsp; The validator task checks the input and output parameters and then calls the validate() method to validate the files.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.PatternSyntaxException;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class Validator extends Task {

    private static final String DEFAULT_EXCLUDE = "";
    
    // constants used to create the property file keys 
    // --&amp;gt; extension.&lt;number&gt;.regex or extension.&lt;number&gt;.description 
    private static final String REGEX       = ".regex";
    private static final String DESCRIPTION = ".description";
    private static final String EXCLUDE     = ".exclude";
    
    private String extension;
    private String directory;
    private String propertyFile;
    private String reportFile;
    
    private int fileCnt;
    private int errorCnt;
    private List descriptors;
    private Properties props;
    private Map errorMap;

    /**
     * Default constructor
     */
    public Validator() {
        props = new Properties();
        descriptors = new ArrayList();
        errorMap = new HashMap();
        errorCnt = 0;
        fileCnt = 0;
    }

    /**
     * Sets the extension for the task
     * @param extension extension of the files to be validated
     */
    public void setExtension(String extension) {
        this.extension = extension;
    }
    
    /**
     * Sets the root directory to be processed.  This directory
     * and all of its subdirectories will be processed.
     * @param directory directory to be processed.  
     */
    public void setDirectory(String directory) {
        this.directory = directory;
    }
    
    /**
     * Sets the root directory to be processed.  This directory
     * and all of its subdirectories will be processed.
     * @param directory directory to be processed.  
     */
    public void setPropertyFile(String fileName) {
        this.propertyFile = fileName;
    }

    /**
     * Set the report file to be created as output
     * @param reportFile name of the html file to be
     *   generated to show any errors
     */    
    public void setReportFile(String reportFile) {
  this.reportFile = reportFile;
 }
    
 /**
     * Creates an xml file from the bugs file
     */
    public void execute() throws BuildException {
        checkParameters();
        try {
            validate();
        } catch (BuildException e) {
            throw e;
        }
    }

    /**
     * Check that all required attributes have been set
     * @throws BuildException if any of the required attributes
     *      have not been set.
     */
    private void checkParameters() {
           if (extension == null || extension.length() == 0  
                ||   directory == null || directory.length() == 0 
                ||   reportFile == null || reportFile.length() == 0 
                || propertyFile == null || propertyFile.length() == 0) 
               throw new BuildException("Extension, directory, reportFile and property file attributes "
                      + "must be defined for task &amp;lt;" + getTaskName() + "/&amp;gt;" );
    }

    private void validate() {
        File dir = new File(directory);
        log("Processing file extension : "+extension+"\n");
        
        try {
            props.load(new FileInputStream(propertyFile));
                      
            setDescriptors();
            visitAllDirsAndFiles(dir);
            
            writeReport();
            
            log("Validator processed "+fileCnt+ " files and found "+errorCnt+" possible errors!");
            
        } catch (Exception e) {
            log(e.toString());
        }
    }
   private void writeReport() {
     try {
  FileWriter writer = new FileWriter(reportFile);
  writeHeaders(writer);
  writeContents(writer);
  writeTrailer(writer);
  writer.close();
 } catch (IOException e) {
  throw new BuildException(e);
 }
   }

   // some code omitted here - but shown later!!!
}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Groovy replacement using CliBuilder&lt;/b&gt;&lt;br /&gt;
While not a whole lot shorter than the Ant equivalent, it is short, concise and a good example of &lt;a href="http://groovy.codehaus.org/gapi/groovy/util/CliBuilder.html"&gt;&lt;i&gt;CliBuilder&lt;/i&gt;&lt;/a&gt; usage.&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;def cli = new CliBuilder (usage: 'groovy Validator -e extension -p propertyFile -d directory -r reportFile')

cli.h(longOpt: 'help', 'usage information')
cli.e(longOpt:'extension',  args:1, required:true, 'file extension to be validated')
cli.p(longOpt:'prop',       args:1, required:true, 'property file containing regular expresssion')
cli.d(longOpt:'directory',  args:1, required:true, 'base directory to start file search')
cli.r(longOpt:'reportFile', args:1, required:true, 'output file for validation report')

def opt = cli.parse(args)
if (!opt) return
if (opt.h) cli.usage()

println "start processing $opt.e files using $opt.p from $opt.d and output to $opt.r"
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;RegExDescriptor becomes ValidatorDescriptor&lt;/b&gt;&lt;br /&gt;
First the java...&lt;br /&gt;
&lt;pre class="brush:java"&gt;import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * Regular Expression Descriptor used to help
 * validate source files.  
 *
 */
public class RegExDescriptor {

    private String description;
    private Pattern excludePattern;
    private Pattern pattern;

    public RegExDescriptor(String regExString, String description, String exclude) throws PatternSyntaxException {        this.description = description;
        pattern = Pattern.compile(regExString, Pattern.CASE_INSENSITIVE);
        if (exclude != null &amp;amp;&amp;amp; exclude.length() &amp;gt; 0)
            excludePattern = Pattern.compile(exclude);
        else
            excludePattern = null;
    }

    public Matcher getMatcher(String line) {
        return pattern.matcher(line);
    }

    public String getDescription() {
        return description;
    }
    
    public boolean excludeFile(String name) {
        if (excludePattern == null) 
            return false;
        Matcher matcher = excludePattern.matcher(name);
        return matcher.find();
    }

    public String getPattern()  {
     return pattern.pattern();
    }
    
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("Validator description=").append(description);
        sb.append(" regEx=").append(pattern.pattern());
        if (excludePattern != null)
            sb.append(" exclude regEx=").append(excludePattern.pattern());
        return sb.toString();
    }
}
&lt;/pre&gt;Now the Groovy equivalent, which I renamed to ValidatorDescriptor.  Like a lot of Java classes ported to Groovy, it is significantly shorter since we don't need to specify the getters and setters.  The toString() method is really needed but I used it in testing to display the ValidatorDescriptor classes created from the properties file.&lt;br /&gt;
&lt;pre class="brush:groovy"&gt;class ValidatorDescriptor {
    String description
    String exclude
    String regex

    String toString() {
       "regEx="+regex + " description=" + description + (exclude ? " exclude("+exclude+")" : "")
    }
}
&lt;/pre&gt;&lt;b&gt;Consuming the properties file&lt;/b&gt;&lt;br /&gt;
The next task is to read the properties file and create a list of objects representing each of the errors I am attempting to capture. &amp;nbsp; If you remember from &lt;a href="http://programmingitch.blogspot.com/2009/12/java-ant-task-ported-to-groovy-part-1.html"&gt;part 1&lt;/a&gt; of the posting, there can be three properties: regex, description and exclude.&amp;nbsp; The java processing to read the file and create the list of RegExDescriptors was located in two steps: the first was to read the file into a &lt;i&gt;Properties &lt;/i&gt;object and then call the &lt;i&gt;setDescriptors&lt;/i&gt; method in the &lt;i&gt;Validator &lt;/i&gt;class as part of the main method called by Ant.&lt;br /&gt;
&lt;br /&gt;
The idea is to group the properties together by the extension and the number that is part of the key.  Each matching set is used to construct the RegExDescriptor.&amp;nbsp; The RegExDescriptor creates a &lt;i&gt;Pattern &lt;/i&gt;for the regular expression checking for the error and another for the file name exclusion check.&amp;nbsp; The patterns are compiled at construction time.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;props.load(new FileInputStream(propertyFile));
setDescriptors();

// later in Validator
/*
     * Setup the regular expression descriptors 
     * using the extension to determine which properties
     * are to be used when validating the files.
     */
    private void setDescriptors()
    {
        // strip the leading . and add one to end
        String prefix = extension;
        char c = extension.charAt(0);
        if (c == '.')
            prefix = prefix.substring(1);
        prefix = prefix + ".";
        
        int idx = 1;
        boolean done = false;
        
        // build list of validators using the extension to create the property keys
        while(!done) {
            String regexKey = prefix + idx + REGEX;
            if (props.containsKey(regexKey)) {
                String descriptionKey = prefix + idx + DESCRIPTION;
                String excludeKey = prefix + idx + EXCLUDE;
                try {
                    idx++;
                    String exclude = props.getProperty(excludeKey, DEFAULT_EXCLUDE);
                    descriptors.add( new RegExDescriptor(props.getProperty(regexKey),
                                                       props.getProperty(descriptionKey),
                                                       exclude) ); 
                } catch (PatternSyntaxException e) {
                    StringBuffer sb = new StringBuffer(100);
                    sb.append("Exception compiling regular expression key(").append(regexKey);
                    sb.append(") :").append(props.getProperty(regexKey)).append("\n").append(e);
                    sb.append("\nSkipping this expression...\n");
                    log(sb.toString());
                }
            } else {
                done = true;
            }
        }
    }
&lt;/pre&gt;&lt;b&gt; &lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
Now for the Groovy implementation.&amp;nbsp; It starts out the same, loading a &lt;i&gt;Properties &lt;/i&gt;object.&amp;nbsp; Next, we use the &lt;a href="http://groovy.codehaus.org/gapi/groovy/util/ConfigSlurper.html"&gt;ConfigSlurper &lt;/a&gt;class to group and parse the properties.&amp;nbsp; An empty list to hold the descriptors is defined and then we iterate across the extension (sql in my case) keys and build the new &lt;i&gt;ValidatorDescriptor &lt;/i&gt;objects.  Notice the use of the GString aware string as part of the key for calling the each closure.&lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
&lt;pre class="brush:groovy"&gt;Properties properties = new Properties();
  try {
     properties.load(new FileInputStream('validator.properties'));
  } catch (IOException e) {}

  def config = new ConfigSlurper().parse(properties)
  def descriptorList = []
  config."$extension".each {
     descriptorList &amp;lt;&amp;lt; new ValidatorDescriptor(it.value)
  }
&lt;/pre&gt;&lt;br /&gt;
In the next (and last) posting in this series, we will cover the following:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Replace the FileValidator class&lt;/li&gt;
&lt;li&gt;Using the HTML Builder to generate a report&lt;/li&gt;
&lt;li&gt;Complete listing of the script and classes&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/ScratchingMyProgrammingItch/~4/d5Wtdt1Nvp0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://programmingitch.blogspot.com/feeds/7988869346073663085/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://programmingitch.blogspot.com/2009/12/ant-task-ported-to-groovy-part-2.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/7988869346073663085?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7371895490737388670/posts/default/7988869346073663085?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ScratchingMyProgrammingItch/~3/d5Wtdt1Nvp0/ant-task-ported-to-groovy-part-2.html" title="Ant task ported to Groovy - Part 2" /><author><name>Mike Miller</name><uri>http://www.blogger.com/profile/09697567698545249690</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://programmingitch.blogspot.com/2009/12/ant-task-ported-to-groovy-part-2.html</feedburner:origLink></entry></feed>
