tag:blogger.com,1999:blog-73718954907373886702024-03-05T10:04:42.511-06:00Scratching my programming itchHints and tips learned while scratching my programming itch.Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.comBlogger43125tag:blogger.com,1999:blog-7371895490737388670.post-43684321810007472092015-01-21T23:20:00.003-06:002015-01-21T23:20:31.716-06:00"I detect a disturbance in the (Groovy & Grails) Force"As you may know by now, Pivotal <a href="http://blog.pivotal.io/pivotal/news-2/groovy-2-4-and-grails-3-0-to-be-last-major-releases-under-pivotal-sponsorship" target="_blank">recently announced</a> that it will be withdrawing funding support for the Groovy and Grails open source projects after March 31st 2015. For more information, you can listen to <a href="http://groovypodcast.podbean.com/e/groovy-podcast-ep-5/" target="_blank">Peter Ledbrook's recent podcast</a> with Graeme Rocher and Guillaume Laforge, the project leads for those projects.<br />
<br />
When I first heard the news, I felt like I had been "punched in the gut". While not an overly active member, I have considered myself part of the Groovy and Grails community for the past couple of years. I started playing around with Groovy in 2009 and have been hooked ever since! I know I drove folks crazy at my last job talking about all the things we could do with Groovy.<br />
<br />
Based on a comment from Graeme in the podcast, I have created this posting to share what I have done with Groovy and Grails in the past. And hopefully more to come!<br />
<br />
<ul>
<li>I started by reading <a href="http://www.manning.com/koenig/" target="_blank">Groovy in Action</a> </li>
<li>Then starting reading other Groovy and Grails books </li>
<li>I subscribed to the <a href="http://www.groovymag.com/" target="_blank">GroovyMag</a> for several years. </li>
<li>I have attended our <a href="http://www.dfw2gug.org/" target="_blank">local Groovy and Grails</a> user group meetings</li>
<li>I haunted <a href="http://www.agiledeveloper.com/" target="_blank">Venkat Subramanian</a> and <a href="http://www.kousenit.com/" target="_blank">Ken Kousen</a> at the local <a href="http://nofluffjuststuff.com/home/main" target="_blank">NoFluffJustStuff</a> conferences, attending all of their Groovy and Grails talks.</li>
<li>I even sneaked some Groovy code into a project at work after reading <a href="http://www.manning.com/kousen/" target="_blank">Making Java Groovy</a></li>
<li>My attempt at adding the <a href="https://code.google.com/p/spock/" target="_blank">Spock testing framework</a> for our testing was unfortunately met with a lot of resistence - which I still can't understand! :-( </li>
<li>And this blog was originally created as place for me to share all of my new Groovy and Grails knowledge with others interested in learning.</li>
</ul>
<div>
Groovy & Grails re-kindled my enthusiam for programming and for that, I would like to say "Thank You" to these teams.</div>
<div>
<br /></div>
The Groovy/Grails community is awesome and hopefully will to grow and prosper. It is my hope that a large organization steps up and takes over responsibility for both projects. The core teams for both of these projects are a set of very sharp individuals and should have no problems finding work. Let's just hope for the sake of the Groovy & Grails community that they get the opportunity to stay together and continue their fine work, because I am guessing some of them probably felt like they got "punched in the gut" too.<div>
<br /></div>
<div>
Best of luck guys!<br /><br />
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
</div>
Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com1tag:blogger.com,1999:blog-7371895490737388670.post-59739922986725081592014-03-20T16:04:00.000-05:002014-03-20T16:04:16.360-05:00Book Review: Programming Groovy 2 Dynamic Productivity for the Java Developer<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN7jvWnlG7DNIF0fg8L_nm5PW62xI422ezxn-ZHTrdFWuWa3Jc5NmNqaBxw4QcprQDiSr5ypI9xoyES40FXc52c9huPPiZ6ukdCCm3N14XfXAqmtoJ9aC32PBW_AN8r8GmwJyJIoF-nLq1/s1600/groovy2.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN7jvWnlG7DNIF0fg8L_nm5PW62xI422ezxn-ZHTrdFWuWa3Jc5NmNqaBxw4QcprQDiSr5ypI9xoyES40FXc52c9huPPiZ6ukdCCm3N14XfXAqmtoJ9aC32PBW_AN8r8GmwJyJIoF-nLq1/s1600/groovy2.jpg" height="200" width="165" /></a></div>
<b>Overview</b><br />
"<a href="http://pragprog.com/book/vslg2/programming-groovy-2" target="_blank">Programming Groovy 2 Dynamic Productivity for the Java Developer</a>" is Dr. Venkat Subramaniam's latest book covering Groovy and important features of this dynamic language. The book goes into detail on how to use many of the dynamic features of the language and can help make you more productive with the language.<br />
<br />
The book is broken down into 4 parts (see below), with 19 chapters covering approximately 300 pages. I would not suggest this book as an introduction to the Groovy language, but once you are past the intro-level, this book is a <b>must-have</b>!<br />
<br />
<b>Contents</b><br />
<br />
<ul>
<li><b>Part 1 Beginning Groovy</b> includes Getting Started, Groovy for Java Eyes, Dynamic Typing, Closures and working with Strings and Collections</li>
<li><b>Part 2 Using Groovy</b> includes Exploring the GDK and working with XML, Databases, Scripts and Classes</li>
<li><b>Part 3 MOPping Groovy</b> includes 6 chapters on working with the MOP in Groovy</li>
<li><b>Part 4 Using Metaprogramming</b> includes chapters on Groovy Builders, Unit Testing and Mocking and Creating DSLs in Groovy</li>
</ul>
<br />
<b>Pros</b><br />
<br />
<ul>
<li>Excellent coverage on the dynamic features of the Groovy language, including the MOP and Metaprogramming. </li>
<li>Examples are short and to-the-point! You are not forced to read thru the creation of some sample application being created throughout the reading of the book. Just enough code to get the point across, and as with almost all books, the code is downloadable. </li>
</ul>
<br />
<b>Cons</b><br />
<br />
<ul>
<li>The book could have been shorter without a lot of the 'introductory' material from Part 1. The problem there is, that would cut about 125 pages from the book and I would guess the publishers have some 'bare minimum number of pages' for their books. </li>
</ul>
<br />
<b>Conclusion</b><br />
Another awesome publication from Venkat. A "must have" for anyone wanting to improve their Groovy Kung-Fu. Venkat covers all the cool features of Groovy in an easily understandable way. <br />
<br />
I have bought and read a lot of technical books thru the years, but only had 1 that I carried in my briefcase every day. Now its time to add another book to the briefcase - Groovy 2 Dynamic Productivity for the Java Developer, and I don't even get to use Groovy in my day job!Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-27628119002048276912014-03-11T07:00:00.000-05:002014-03-11T13:58:52.706-05:00Parameterized JUnit testsSometimes you encounter a problem that just screams for using "parameterized" tests rather than copy/pasting the same method many times. The test method is basically the same and the only thing that changes is the data passed in. In this case, consider creating a test case that utilitizes the "<a href="http://junit.sourceforge.net/javadoc/org/junit/runners/Parameterized.html" target="_blank">Parameterized</a>" class from JUnit.<br />
<br />
I recently ran into a problem where our validation of an email address did not allow unicode characters. The fix was fairly straight-forward, change the regular expression to allow those characters. Next, it was time to test the change. Rather than copy/paste separate methods for each set of data, I decided to learn about the Parameterized method. Below is the result. The data includes the expected result and the email address to be validated.<br />
<br />
<b>JUnit test class</b><br />
<pre class="brush:java">package com.mycompany.client;
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import com.mycompany.test.TestServiceUtil;
/**
* Parameterized test case for validating email addresses against a regular expression.
* We need to allow unicode characters in the userid portion of the email address, so
* these test cases where created to help validate the validateEmailAddress method
* in the FieldValidationController class.
*
* @author mmiller
*
*/
@RunWith(Parameterized.class)
public class TestFieldValiationController {
@Parameters(name = "{index}: {1} is valid email address = {0}")
public static Iterable<object> data() {
return Arrays.asList(new Object[][] {
{ true, "john@mycomp.com" }, { true, "john123@mycomp.com" },
{ true, "j+._%20_-brown@mycomp.com" }, { true, "123@mycomp.com" },
{ false, "john brown@mycomp.com" }, { false, "123@mycomp" },
{ false, "john^brown@mycomp.com" }, { true , "1john@mycomp.com" },
{ false, "john#brown@mycomp.com" }, { false, "john!brown@mycomp.com" },
{ false, "john()brown@mycomp.com" }, { false, "john=brown@mycomp.com" },
{ true, "johñ.brown@mycomp.com" }, { false, "john.brown@mycomp.coñ" },
{ true, "johú@mycomp.com" }, { true, "johíáó@mycomp.com" }
});
}
private boolean expected;
private String emailAddress;
public TestFieldValiationController(boolean expected, String emailAddress) {
this.expected = expected;
this.emailAddress = emailAddress;
TestServiceUtil.getInstance();
}
@Test
public void validateEmail() {
assertEquals(expected, FieldValidationController.getInstance().validateEmailAddress(emailAddress));
}
}
</object></pre>
<br />
<b>Hope this helps!</b>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-54045609508526792612014-03-10T13:49:00.000-05:002014-03-10T13:49:18.420-05:00Creating a simple JAX-RS MessageBodyWriterJAX-RS is really cool and with the help of JAXB a lot of response data types can be converted for you simply by adding annotating the data objects with JAXB annotations. I am fairly new at JAXB but some simple cut/paste of annotations will take you a long way.<br />
<br />
There maybe some types of data that you can't or won't annotate for the purposes of returning that data type from a JAX-RS resource method. One simple example is returning either a boolean (primitive) or the wrapper Boolean class. I read a question on StackOverflow where someone asked if they could return a boolean from a resource method and since I didn't know the answer, I decided to try it! My version only returns XML, not JSON but you should get the idea.<br />
<br />
I started with the Jersey <a href="https://jersey.java.net/documentation/2.0/getting-started.html#running-project" target="_blank">User's Guide HelloWorld</a> example and starting modifying from there. I used the pom.xml and the only change was to uncomment a block to allow using JSON.<br />
<br />
<b>Main class </b><br />
This the main class from the Hello World example without any changes.<br />
<br />
<pre class="brush:java">package com.example;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.io.IOException;
import java.net.URI;
/**
* Main class.
*
*/
public class Main {
// Base URI the Grizzly HTTP server will listen on
public static final String BASE_URI = "http://localhost:8080/myapp/";
/**
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
* @return Grizzly HTTP server.
*/
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in com.example package
final ResourceConfig rc = new ResourceConfig().packages("com.example");
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
/**
* Main method.
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
System.out.println(String.format("Jersey app started with WADL available at "
+ "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
System.in.read();
server.stop();
}
}</pre>
<br />
<b>Resource class</b><br />
I created a resource class that included a GET method to return a boolean and another GET method to return the wrapper Boolean class. Notice the getBool() and getBoolean() methods return XML as the first option.<br />
<br />
<pre class="brush:java">package com.example;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* Root resource (exposed at "myresource" path)
*/
@Path("myresource")
public class MyResource {
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* @return String that will be returned as a text/plain response.
*/
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
public String getIt() {
return "Got it!";
}
@GET
@Path("/bool")
@Produces({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
public boolean getBool() {
return false;
}
@GET
@Path("/Boolean")
@Produces({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
public Boolean getBoolean() {
return Boolean.TRUE;
}
}
</pre>
<br />
<br />
<b>BooleanMessageBodyWriter class</b><br />
Here's the interesting part, creating the <a href="https://jsr311.java.net/nonav/javadoc/javax/ws/rs/ext/MessageBodyWriter.html" target="_blank">MessageBodyWriter</a> class to allow the resource method to return XML for the boolean or Boolean.<br />
<b><br /></b>
<pre class="brush:java">package com.example;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.WebApplicationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.DataOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
@Provider
@Produces("application/xml")
public class BooleanMessageBodyWriter implements MessageBodyWriter<boolean> {
@Override
public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) {
System.out.println("isWriteable called...");
return type == Boolean.class;
}
@Override
public long getSize(Boolean myBool, Class type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
// deprecated by JAX-RS 2.0 and ignored by Jersey runtime
return 0;
}
@Override
public void writeTo(Boolean myBool,
Class type,
Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<string object=""> httpHeaders,
OutputStream entityStream)
throws IOException, WebApplicationException {
StringBuilder sb = new StringBuilder();
sb.append("<boolean><boolean>").append(myBool.toString()).append("</boolean></boolean>");
DataOutputStream dos = new DataOutputStream(entityStream);
dos.writeUTF(sb.toString());
}
}
</string></boolean></pre>
<br />
I haven't used Maven before but the following targets are all you need to compile and run the project, after installing maven (of course!).<br />
<ul>
<li><b>mvn compile</b> - compiles the code</li>
<li><b>mvn exec:java</b> - starts the Grizzly HttpServer and deploys the restful service.</li>
</ul>
<div>
Hope this helps!</div>
Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com2tag:blogger.com,1999:blog-7371895490737388670.post-63166897980050953102014-01-14T17:38:00.002-06:002014-01-14T17:38:24.308-06:00Book Review: Professional Node.js Building JavaScript-Based Scalable Software <div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEildufAmuc7wXI-TPewQ53d5linDpmb0okYfwcHIr00CFlWM5-D4dW_k9NgR98rHrGAC-Qxat-_5xw6gRLfaj2oqAqhcTeF7zwD-KdqTzIDqr6NqYc7sq-PAC1xG66gyTC3FElL1QqrOf5O/s1600/pronodejs.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEildufAmuc7wXI-TPewQ53d5linDpmb0okYfwcHIr00CFlWM5-D4dW_k9NgR98rHrGAC-Qxat-_5xw6gRLfaj2oqAqhcTeF7zwD-KdqTzIDqr6NqYc7sq-PAC1xG66gyTC3FElL1QqrOf5O/s200/pronodejs.jpg" width="200" /></a></div>
<b>Overview</b><br />
As a result of the recent explosion of JavaScript's popularity, partially led by Node.js, I decided to spend some time updating my JavaScript skills. I started reading a lot of articles and posts and then came across a recommended approach to learning <a href="http://nodejs.org/" target="_blank">Node </a>on <a href="http://javascriptissexy.com/learn-node-js-completely-and-with-confidence/" target="_blank">JavascriptIsSexy.com</a> and decided to give it try.<br />
<br />
<b>Contents</b><br />
The book is broken up into 6 parts(listed below), with a total of 25 chapters covering 350 pages, written by Pedro Teixeira.<br />
<br />
<ol>
<li>Introduction and Setup</li>
<li>Node Core API basics</li>
<li>Files, Processes, Streams and Networking</li>
<li>Building and Debugging Modules and Applications</li>
<li>Build Web Applications</li>
<li>Connecting to Databases</li>
</ol>
<div>
The book is not an introduction to JavaScript, nor does it spend the first couple chapters attempting to ramp up readers on the JavaScript language, which I appreciated. Readers should already have some basic JavaScript knowledge before reading this book.</div>
<div>
<br /></div>
<b>Pros</b><br />
<ul>
<li>Well written and easy to follow along with the code examples</li>
<li>The chapters covered the material without getting too long. Easy enough to spend about 1/2 hour reading a chapter and working through the code examples for the chapter</li>
<li>The book got me excited about the possibilities available using Node.js and started me down a new path to help build my "full stack developer" skills.</li>
</ul>
<b>Cons</b><br />
<ul>
<li>The code examples were good, but I think it would help early in the book to point out where to find the <a href="http://nodejs.org/api/fs.html" target="_blank">Node API documentation</a>, otherwise the reader is sometimes left wondering, "How did they know what methods are available, what to call and what to pass to that API?"</li>
<li>For all the positive impact <a href="https://npmjs.org/" target="_blank">NPM</a> has had on Node.js, the coverage of NPM in the book seems a bit light, although that could just be lack of Node knowledge showing!</li>
</ul>
<b>Conclusion</b><br />
I was very happy with the book and would recommend it for anyone with some basic JavaScript skills looking to learn about Node.js.<br />
<br />
I usually stick to Manning or O'Reilly books but when I started my quest for Node knowledge, neither of those publishers had books covering Node. This has since changed and I may try one of those out as well. Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-65478692951904989482013-09-06T16:10:00.000-05:002013-09-06T16:10:05.130-05:00Not all JSON created equal, at least from Java implementations!<b>Setting the stage</b><br />
I have spent the majority of my career on the 'server-side' of applications. When I have worked on the client side, it has been Java Swing, so up to now I haven't worked much with JSON. My (incorrect!) assumption was that all JSON is created equal.<br />
<br />
We are creating a new REST API for our product at work and plan on supporting both JSON and XML for both the requests and responses. We are using <a href="http://www.jboss.org/resteasy" target="_blank">RESTEasy </a>from JBoss and the process has been fairly straight-forward.<br />
<br />
Below is a screen shot of two sets of JSON generated from our CustomerResource using RESTEasy with the exact same code from our perspective. The only difference is how I configured RESTEasy to generate JSON. In one case, I used <a href="http://jettison.codehaus.org/" target="_blank">Jettison </a>and in the other case I used <a href="http://wiki.fasterxml.com/JacksonHome" target="_blank">Jackson</a>. I expected that both tools would generate exactly the same output - <b>WRONG</b>! See below for some of the differences.<br />
<br />
<b>Results</b><br />
<b><br /></b>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrq8RlHiBxjd2idC2ln-yodpM6YThNc_5hZ1TlqVrxG-x5ne4nRJ1yJNU8KY07TYliG-F4d0HwValJ-WM1oPG4BdQEDwvW0mEVhgZlOx5mdSSIOgvfgPsM-fFKz71pLxgZMFOCC075wH_P/s1600/json.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="404" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrq8RlHiBxjd2idC2ln-yodpM6YThNc_5hZ1TlqVrxG-x5ne4nRJ1yJNU8KY07TYliG-F4d0HwValJ-WM1oPG4BdQEDwvW0mEVhgZlOx5mdSSIOgvfgPsM-fFKz71pLxgZMFOCC075wH_P/s640/json.png" width="640" /></a></div>
<br />
The results above show a simple customer entry with a set of 1 phone number and a set of 1 address. <br />
<br />
I have noticed following differences (there may be others…):<br />
<br />
<ul>
<li>Jettison has a name entry for the object whereas Jackson does not (Customer,Addresses, Address,PhoneNumbers, PhoneNumber) </li>
<li>Jettison appears to force all values to a String, using the double quotes, whereas Jackson does not for number fields, like customerId, where it does not double quote the value</li>
<li>Jackson is currently showing null fields, like addressLine2 & addressLine3 whereas Jettison is not. This may be configurable.
Jackson uses JAXB annotations to assist with its marshaling/serializing and also contains some of its own annotations as well which might be used to help adjust the output.</li>
</ul>
<div>
Hope this helps!</div>
Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-52770309222879505392013-08-09T11:29:00.002-05:002013-08-09T11:29:52.300-05:00Groovy moonlighter mistake: Not all "method chaining" does what you might think<br />
<b>Setup</b><br />
I am using <a href="https://code.google.com/p/spock/" target="_blank">Spock </a>to help inject Groovy into our project and currently that means testing our new RESTful API. We need to be able to send and receive both XML and JSON. To test our POST method, I created a default Cart object and get the JSON representation. I decided to try to use <a href="http://curl.haxx.se/" target="_blank">curl </a>to call some of the methods, so for this POST method call, I needed to save the JSON to a file. Later, I wanted to make sure the file was created.<br />
<br />
<b>Problem Code</b><br />
The code below gets a NullPointerException calling the exists() method.<br />
<br />
<pre class="brush:groovy">public void "POST Creates New Cart with JSON"() {
when:
File f = new File("cart.json").write(getDefaultCartJSON())
def response = '''curl -X POST -i -d @cart.json --header "Content-Type:application/json"
http://localhost:7001/restservices/carts'''.execute().text
then:
f.exists()
response.startsWith("HTTP/1.1 201 Created")
}
}
</pre>
<br />
<b>Root Cause:</b><br />
The problem wasn't obvious immediately to me (hey I wrote it!). The problem is the<a href="http://groovy.codehaus.org/groovy-jdk/java/io/File.html#write(java.lang.String)" target="_blank"> write() </a>method returns a void, not the file object.<br />
<br />
<pre class="brush:groovy"> File f = new File("cart.json").write(getDefaultCartJSON())
</pre>
<br />
<b>Corrected Code</b>
<br />
Below is the corrected code. So you don't always need to assign the result of a 'new' into a variable, even though that's how many of us learned to program.<br />
<br />
<pre class="brush:groovy">public void "POST Creates New Cart with JSON"() {
when:
new File("cart.json").write(getDefaultCartJSON())
def response = '''curl -X POST -i -d @cart.json --header "Content-Type:application/json"
http://localhost:7001/restservices/carts'''.execute().text
then:
new File("cart.json").exists()
response.startsWith("HTTP/1.1 201 Created")
}
}
</pre>
<br />
<b>Wrap-up</b><br />
Obviously this was not some major problem or break-through, just something to keep in mind as you write your code. Maybe this will help prevent others from making the same mistake(s) I made. :-)<br />
<br />
Hope it helps!<br />
<b><br /></b>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-10667932952711838692013-08-08T14:31:00.001-05:002013-08-08T14:31:53.773-05:00Groovy moonlighter mistake: Spock requires JUnit to run inside Eclispe<b>Setup</b><br />
<b><br /></b>
I was rushing a bit the other day to get a new project setup in Eclipse. The project is for some RESTful API work we are doing. Naturally, I started looking for a way to inject Groovy into the process (regardless of how much resistance I continue to encounter from my colleagues). :-) Why not include the <a href="https://code.google.com/p/spock/" target="_blank">Spock testing framework</a> I thought. Great, if the team doesn't want to use Groovy, they can still write their test cases the old way, but I am going to inject Spock to the project!<br />
<br />
Now I am off and running:<br />
<ul>
<li>Eclipse project created: check</li>
<li>Added Groovy Nature to the Eclipse project: check</li>
<li>Included the Spock jar in the build path: check</li>
<li>First test case written using Spock and it compiles: check</li>
<li>Run my test case from within Eclipse: WTF, Eclipse where's the JUnit menu option (screenshot below)</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCDEUHz4Wfi5W7nUFQBiKRlZLgRAcfsKCb1NH1PUusTweSIrOrQ9Ja9W4nZiS3RLkYRL_uBh_AHwO5xmhBJHNZBlfeZ-H83FMY2UsQVei-5R5ku95egW6qGDP9IShdjjXygg98fwsTOkQ5/s1600/spockWithoutJUnit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCDEUHz4Wfi5W7nUFQBiKRlZLgRAcfsKCb1NH1PUusTweSIrOrQ9Ja9W4nZiS3RLkYRL_uBh_AHwO5xmhBJHNZBlfeZ-H83FMY2UsQVei-5R5ku95egW6qGDP9IShdjjXygg98fwsTOkQ5/s640/spockWithoutJUnit.jpg" width="640" /></a></div>
<br />
<b>Resolution:</b><br />
Spock requires JUnit to run inside Eclipse (duh!). So I added the JUnit jar to my build path and now as you can see in the screenshot below - all is better with my world - now I can run my Spock tests within Eclipse!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkB4bZ4qAR_oeumFPYuD9nQURT5WBrYLR3sgm1I7Z41DxhdzAaClGq7nK3-M_TIDplyZKK5BttGCLfCwDfT1RVPxcLks4o_BMH7700Trgn_pPJALSALgjQTsxq1vXYbXrGH_QMmZn1aUaz/s1600/spockWithJUnit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="409" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkB4bZ4qAR_oeumFPYuD9nQURT5WBrYLR3sgm1I7Z41DxhdzAaClGq7nK3-M_TIDplyZKK5BttGCLfCwDfT1RVPxcLks4o_BMH7700Trgn_pPJALSALgjQTsxq1vXYbXrGH_QMmZn1aUaz/s640/spockWithJUnit.jpg" width="640" /></a></div>
<br />
I have to thank <a href="http://danveloper.com/" target="_blank">danveloper </a>for the tagline "Groovy moonlighter". We were exchanging emails about one of his projects when I complained that my Groovy practice is limited to nights and weekends. At that point he called me a 'Groovy Moonlighter". Thanks Dan!<br />
<br />
Hope this helps!<br />
<br />
<br />
<br />Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-32975027796477328802013-07-08T13:40:00.001-05:002013-07-08T13:40:33.401-05:00Book Review: Making Java Groovy<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidNwYhUyVMOTqCgNzN1Oy60GBjdd9VgizYVZ8o1MdZdfV_pX4eoT5qrsOtgRISMwqPFXxNmf48zWosOSjl33Xddb5uwiyzcQPEhw8riUbc-QyomyeHaIBDqQX_WAooeIAerJP8ABhK-Nzg/s187/kousen_cover150.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidNwYhUyVMOTqCgNzN1Oy60GBjdd9VgizYVZ8o1MdZdfV_pX4eoT5qrsOtgRISMwqPFXxNmf48zWosOSjl33Xddb5uwiyzcQPEhw8riUbc-QyomyeHaIBDqQX_WAooeIAerJP8ABhK-Nzg/s187/kousen_cover150.jpg" /></a></div>
<b>Overview</b><br />
This review might be considered 'jumping the gun' a bit since this book has not been officially released yet. Only the last chapter (Chapter 11) remains but honestly, even if that last chapter said "This chapter intentionally left blank", it would not adversely affect my review. I signed up for the MEAP program for this book after hearing Ken Kousen present some of this material at my local J<a href="http://javamug.org/" target="_blank">ava Users Group. </a><br />
<br />
<b>Contents</b><br />
The book is broken into 3 parts:<br />
<br />
<ol>
<li><b>Part 1 </b>- Up to speed with Groovy includes 3 chapters that discuss why adding Groovy to Java, Groovy examples and Code-level integration.</li>
<li><b>Part 2</b> - Groovy Tools covers Build processes and Test Groovy and Java projects. These chapters in very handy and timely. While reading these chapters I was introducing Groovy into our Java project and the discussion on how to handle builds mixed with Java and Groovy resolved one of my outstanding questions. The next chapter helped answer other questions about how to handle testing in this 'mixed' environment.</li>
<li><b>Part 3</b> - Groovy in the Real World covers integration with Spring, databases, SOAP and REST </li>
</ol>
<div>
This is also an Appendix that does a very high-level overview of the Groovy for the folks new to Groovy, without stepping on the toes of "<a href="http://manning.com/koenig2/" target="_blank">Groovy In Action</a>"</div>
<br />
<br />
<b>Pros:</b><br />
<br />
<ul>
<li>Great reference that hits all the high points like builds, testing, web services, Spring and databases</li>
<li>Covers most of the scenarios that you will encounter when including Groovy to your Java projects</li>
</ul>
<b>Cons:</b><br />
<br />
<ul>
<li>Footnotes have a different context when reading Ken's book. For the most part, the footnotes in the book are there to:</li>
<ul>
<li>apologize for a bad joke or pun or</li>
<li>explain a joke or reference from the earlier in the text</li>
</ul>
</ul>
<b>Summary</b><br />
This is an excellent book for Java developers wanting to get started with Groovy. This books helps answer some of the possible nagging questions like "How do I handle the builds/compiles?" or "How do I test Java and Groovy code together?".<br />
<br />
This book is a definite <b>BUY</b>, and I am still waiting on Chapter 11 - The Future.<br />
<br />
<br />Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com1tag:blogger.com,1999:blog-7371895490737388670.post-5810472148634931522013-05-27T21:32:00.000-05:002013-05-27T21:40:35.530-05:00Book Review: Getting Started with NoSQL<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIBqa_A2lTN32fRjqz3YnPb5lAIEljcV_6l0tb0U2IdgxgJRmX6dsFyySHqkQW2W7UoN5_4sGkk9LYAEo5hpJ6Gpb0CU8j4IQSwPc2frlaq0NjZ6wobMf7gEdnmAd9GGvGE16u44Kh66J6/s1600/NoSQL.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIBqa_A2lTN32fRjqz3YnPb5lAIEljcV_6l0tb0U2IdgxgJRmX6dsFyySHqkQW2W7UoN5_4sGkk9LYAEo5hpJ6Gpb0CU8j4IQSwPc2frlaq0NjZ6wobMf7gEdnmAd9GGvGE16u44Kh66J6/s200/NoSQL.jpeg" width="159" /></a></div>
<b>Overview</b><br />
Unless you've been living under a rock, you have at the very least, heard of NoSQL. You may not know much about it, what types of NoSQL databases exists, what the functionalities they provide or even know the names of some NoSQL databases. If this is true, then <a href="http://www.packtpub.com/nosql-using-scenario-driven-case-studies/book" target="_blank">Getting Started with NoSQL</a> is for you. The book will help guide you thru an evaluation process of NoSQL databases, considering a set of requirements and use cases with which to help evaluate each type of database.<br />
<b><br /></b>
<b>Contents</b><br />
<ul>
<li>Overview of NoSQL</li>
<li>Characteristics of NoSQL</li>
<li>NoSQL storage types</li>
<li>Advantages and Drawbacks</li>
<li>Comparative Study of NoSQL products</li>
<li>Case Study</li>
</ul>
<b>Pros:</b><br />
<ul>
<li>Quick read, only 142 pages</li>
<li>Provides a good comparison of the NoSQL database types vs the RDBMS, and what NoSQL is and is NOT.</li>
</ul>
<b>Cons:</b><br />
<ul>
<li>Lots of hyperlinks within the text - this was my first time reading an e-book on a Kindle so I don't know if that is typical of not. I expect that is not the case.</li>
<li>Comparatively light coverage of Graph databases vs more popular types, for example Document store</li>
<li>Described as appropriate for "technology decision makers - be it architect, product manager or CTO". I would agree this book is appropriate for developers, architects and possibly product managers. </li>
</ul>
<b><br /></b>
<b>Conclusion</b><br />
The book takes an analytic approach to comparing different NoSQL database types based on a specified set of criteria. It walks you thru the comparisons, evaluating how each database type rates in terms of the criteria and merely suggests which database type they feel would be most appropriate for the use cases being evaluated. <br />
<b><br /></b>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-86371191163031417352013-04-30T22:02:00.000-05:002013-04-30T22:02:03.284-05:00Book Review: Gradle Effective Implementation Guide<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0r-vdTDgrzy2TsHaat38G2S6JOwb3fybHLcZvgOfSg71zKlF-K8lKt_XMKzB4tXL7qQTKsq4O6ianUI1D0N0hIR-uERKZlgmgcr_SLGwWtHQ5h3kXS_J1a7ZnYLVE6UpozQ_6x9IkT5Vs/s1600/gradlebook.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0r-vdTDgrzy2TsHaat38G2S6JOwb3fybHLcZvgOfSg71zKlF-K8lKt_XMKzB4tXL7qQTKsq4O6ianUI1D0N0hIR-uERKZlgmgcr_SLGwWtHQ5h3kXS_J1a7ZnYLVE6UpozQ_6x9IkT5Vs/s320/gradlebook.jpg" width="240" /></a></div>
<b>Overview</b><br />
The choice of build tools in the Java space has basically been Ant or Maven since the early days of Java. 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.<br />
<br />
Now a new build tool has arrived, <a href="http://www.gradle.org/" target="_blank">Gradle</a>. Gradle adoption started slowly at first, but has definitely been picking up momentum as <a href="http://java.dzone.com/hibernate-users-learn-gradle" target="_blank">more</a> and <a href="http://java.dzone.com/hibernate-users-learn-gradle" target="_blank">more</a> projects migrate from either Ant or Maven over to Gradle. Gradle can't be ignored!<br />
<br />
Gradle is built on top of the Groovy. The tool provides a rich Domain Specific Language (DSL) based on Groovy. The DSL is the key component of Gradle.<br />
<br />
<b>Contents</b><br />
<ul>
<li>Starting with Gradle, creating and working with build scripts </li>
<li>Gradle for Java projects</li>
<li>Dependency management</li>
<li>Testing building and publishing artifacts</li>
<li>Multi-project builds</li>
<li>Gradle with Groovy and Scala</li>
<li>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</li>
<li>Using Gradle with Continuous Integration - covers Jenkins, TeamCity and Bamboo</li>
<li>IDE support - provides excellent coverage of Eclipse and IntelliJ IDEA support</li>
</ul>
<b>Pros</b><br />
<ul>
<li>Very good reference guide</li>
<li>Sample source filled with a lot of complete examples</li>
<li>It's by <a href="http://mrhaki.blogspot.com/" target="_blank">Mr. Haki,</a> creator of <b>Groovy Goodness,</b> <b>Grails Goodness</b> and of course, <b>Gradle Goodness</b> blog postings!</li>
</ul>
<b>Cons</b><br />
<ul>
<li>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.</li>
<li>The book contains only a single reference to Ant and no discussion on Gradle's integration with Ant. 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. 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.</li>
<li>The book is 356 pages but a lot of pages are 'eaten up' by showing the output of all the example build scripts, and screen shots from Chapter 11, Using Gradle with Continuous Integration and Chapter 12 IDE support.</li>
</ul>
<b>Summary</b><br />
The book is a very good reference for using Gradle and I would definitely recommend it for anyone interested in learning more about Gradle. <br />
<br />
<b>Gradle thoughts (not specific to the book)</b><br />
This the <a href="http://programmingitch.blogspot.com/2011/07/book-review-building-and-testing-with.html" target="_blank">second book</a> I have read on Gradle. 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. One of my challenges is that I don't get to use Gradle in my day job, just at night and on weekends. This limited use seems to extend the learning curve, which I think for Gradle is larger/longer than other tools. <br />
<br />
"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. I think one of the keys to learning Gradle is to get a firm grasp on the <a href="http://www.gradle.org/docs/current/dsl/index.html" target="_blank">Gradle DSL</a>. Without a grasp on the DSL, a new Gradle user just keeps wondering "Where are these properties/methods coming from?"<br />
<b><br /></b>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com2tag:blogger.com,1999:blog-7371895490737388670.post-12718430046465866012013-02-18T19:43:00.003-06:002013-02-18T19:43:57.792-06:00Minor Gotchas from migration to Java 7After several years of pushing, we are finally starting to pull our application out of the dark ages 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:
<br />
<ul>
<li>Test cases that had been running successfully for years started failing when we switched to Java 7. It turns out that we had some test cases that depended on previous test cases within the same class. 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 guaranteed, although, up to now(before Java 7), the order was the order found in the source code. <a href="http://intellijava.blogspot.com/2012/05/junit-and-java-7.html" target="_blank"> I found this link</a> that helped explain the inconsistent ordering I was seeing within Eclipse. This is not a problem with Java 7 but rather with our test cases. Just something that cropped up when we started running with Java 7</li>
<br />
<li>Our Swing clients began throwing <b>ClassCastExceptions</b>, and this is code that has been in place for over 10 years, dating back to Java 1.4 Reading the javadocs helped explain the problem, but I decided to research a bit more to find out exactly why this was happening now. We were <a href="http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html#add(E)" target="_blank">adding entries to a TreeSet</a> to hold forward and backward traversal keys for the FocusManager, putting KeyStroke objects into the TreeSet. The <a href="http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html#add(E)" target="_blank">javadoc </a>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, and not getting exceptions. Digging into the java source code, 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. The fix was easy, I created a KeyStrokeComparator and passed that to the TreeSet constructor.</li>
<br />
<li>I also noticed that our java jar signing had started logging a warning about the certificate not being valid. 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<a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6948803" target="_blank"> removal of the MD2withRSA</a> algorithm from the code signing certificates. I worked with support from Verisign to help with the removal of that algorithm from our certificate chain and the warning went away! Unfortunately, that was not the end of the code signing problems. </li>
<br />
<li>Next, our web start clients would no longer start successfully, instead throwing an exception with the all-too-familiar '<b>not all jars signed with the same certificate</b>' error message frequently encountered by web start programs, at least during development! I've written another <a href="http://programmingitch.blogspot.com/2012/08/resolving-not-all-jars-signed-with-same.html" target="_blank">blog post</a> 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. Knowing that all this happened since the certificate was updated caused me to review all of our signed jars to look for clues. 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. 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. </li>
<br />When jars are signed, entries are generated in the MANIFEST.MF file inside the jar, one entry for each class in the jar. These entries contain the name of the class along with some signing algorithm information and after reviewing the MANIFEST.MF files, I found the difference. The 3rd party jars signed before the change included a<b> SHA1-Digest</b> entry for each class but our jars signed from the current build contained entries with <b>SHA-256-Digest.</b> Re-signing all of our 3rd party jars with the updated certificate resolved most of the problems. 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.</ul>
<div>
All in a days work! Just Happy to be current on the Java level. Next up, migrating to EJB3 and Hibernate 3 or 4.</div>
<div>
<br /></div>
<div>
Hope this helps!</div>
<br />
<br />
<div>
<br /></div>
<div>
<br /></div>
Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com1tag:blogger.com,1999:blog-7371895490737388670.post-2450883401236006802012-11-29T23:19:00.000-06:002012-11-30T11:55:28.006-06:00Grails & EJB2, my stumbling pointsI have been 'playing' with Grails for a couple years now. I say 'playing' because I don't get to use Grails for my day job. 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. Yeah, I know, nobody still uses EJB 2.1! I have been pushing for some technical upgrades and hopefully that will happen this year, but that not want I want to talk about.<br />
<br />
In the past, when I wanted to create a small work-related Grails project, I took what I saw as the easier way out. I used the static mappings in the domain object to map tables and columns to fields in the domain object, and this works fine. 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. Below is a list of my stumbling points along the way to getting this project working. Only one of the points is EJB2 related but the others are all valid for a lot of current projects.<br />
<br />
<b><span style="font-size: large;">My stumbling points:</span></b><br />
<ol>
<li><b>resources.groovy bean definition</b>: JndiObjectFactoryBean vs SimpleRemoteStatelessProxyFactoryBean</li>
<li><b>LinkageError</b> - referencing javax.management.MBeanServer</li>
<li><b>Compile errors after removing Hibernate</b> </li>
<ol>
</ol>
<li><b>BuildConfig.groovy </b></li>
</ol>
<b>resources.groovy bean definitions:</b><br />
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. I found some examples that worked great if you were using EJB 3.x. If you are using EJB 3.x, you reference the <b>JndiObjectFactoryBean</b> and this returns the remote service interface. 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. Again, the problem is that I am using EJB 2.1. Another couple google searches turned up Dave Klein's "<a href="http://www.slideshare.net/daveklein/grails-integration-strategies#btnNext" target="_blank">Grails Integration Strategies"</a> presentation and the answer was there on page 15. For EJB 2.x, you need to use the <b>SimpleRemoteStatelessProxyFactoryBean</b> in order to get the remote service interface. Spring's SimpleRemoteStatelessProxyFactoryBean handles retrieving the home interface, calling PortableRemoteObject.narrow() and then calling create() in order to return a remote service interface for EJB 2.1.<br />
<br />
<b>resources.groovy for EJB 2.x</b><br />
<br />
<pre class="brush:plain">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")
}
}
</pre>
<b><br /></b>
<br />
<b>resources.groovy for EJB 3.x</b><br />
<br />
<pre class="brush:plain">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")
}
</pre>
<div>
<br /></div>
<b><br /></b>
<b>Linkage Error:</b><br />
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. I am using JBoss as my application server and using the JBoss jars within Grails. 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:<br />
<ol>
<li>delete Tomcat and install Jetty, which I did and it worked great!</li>
<li>deploy a war to Tomcat. Apparently this problem only happens in the development environment and deploying your application as a war side steps this problem.</li>
</ol>
<br />
Below is an example of the LinkageError<br />
<br />
<pre class="brush:plain">c:\dev\groovy\hv>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 <bootloader>) 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]]
</bootloader></pre>
<b><br /></b>
<b>Compile errors after removing Hibernate:</b><br />
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! 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. Easy fix - edit BuildConfig.groovy to remove the database migration plugin and re-run. Below is a copy of both the short error version and the longer version, which used --stacktrace to get a full stacktrace.<br />
<b><br /></b>
<br />
<pre class="brush:plain">c:\dev\groovy\hv>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>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
</pre>
<b><br /></b>
<b>Minor mention:</b><br />
Starting in Grails 2.x, BuildConfig.groovy plays a bigger role in dependency resolution. 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 <plugin>' or 'grails uninstall-plugin <plugin>'. 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. I had to use a combination of the command line (grails uninstall-plugin) plus edits to BuildConfig.groovy to resolve my problems. </plugin></plugin><br />
<br />
<b>Final Thoughts:</b><br />
The problems documented above were mainly my fault and not that of Grails! I am just documenting them to possibly help anyone trying the same type of integration. Maybe this will save them some time and frustration!<br />
<br />
Hope this helps!<br />
<ol><ol>
</ol>
</ol>
Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-47023330378964620422012-08-28T22:32:00.001-05:002012-08-28T22:35:26.708-05:00Resolving the "Not all jars signed with same certificate" issueAlmost a year ago I wrote<a href="http://programmingitch.blogspot.com/2011/10/jars-signed-with-mutliple-code-signing.html" target="_blank"> posting </a>on how to resolve the "Not all jars signed with the same certificate" problem encountered from time to time with signed Web Start applications. 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. For those familiar with Groovy, that's still my suggestion.<br />
<br />
Recently one of our customer service folks was fighting this same problem at a customer site. To make matters worse, they were not familiar with Groovy, so using my previous script was not an option. I decided to bite the bullet and write the Java equivalent. <br />
<br />
Below is my Java-equivalent of the Groovy script. The code is saved as the <a href="https://github.com/mikemil/JarSigners" target="_blank">JarSigners project at GitHub</a>.<br />
<br />
<br />
<pre class="brush:java">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<string list="list" tring="tring">> map;
private Set<string> certs;
public JarSigners(String folderName) {
this.folderName = folderName;
map = new HashMap<string list="list" tring="tring">>();
certs = new HashSet<string>();
}
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() > 1) {
System.out.println("WARNING: More that one certificate shows up in the jars!");
}
System.out.println("Details jar->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<string> list = map.get(zipEntryName);
list.add(zipEntryName);
} else {
List<string> list = new ArrayList<string>();
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!");
}
}
</string></string></string></string></string></string></string></pre>
<br />
<br />
Hope this helps!Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-61662874369736571452012-08-23T22:56:00.001-05:002012-08-23T22:56:43.394-05:00Auto-completion for email addresses in Swing<br />
Recently we added the ability to send Electronic Receipts from our Point-of-Sale product at work. One of the requirements was to enhance the user interface around the capture of email addresses. We were just using a standard JTextField to capture the value. 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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpIsH6Pp3la46YsWtucrLLDL5e4mhbLdHKAoEGiiU2KNxldCJWsnm5MADNkRiapR8aYRDhln150k3woJAlMg-omWo6xbIxxc38sBwf9myvXKvNmRQKSrnWfycIMMKVqA270e11jbFJ2NrR/s1600/addressCompletion.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpIsH6Pp3la46YsWtucrLLDL5e4mhbLdHKAoEGiiU2KNxldCJWsnm5MADNkRiapR8aYRDhln150k3woJAlMg-omWo6xbIxxc38sBwf9myvXKvNmRQKSrnWfycIMMKVqA270e11jbFJ2NrR/s1600/addressCompletion.png" /></a></div>
<br />
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! After a couple searches, I found a<a href="http://samuelsjoberg.com/archive/2009/10/autocompletion-in-swing" target="_blank"> great starting point</a> for the new code. Samuel Sjöberg's auto-completion was extremely close to what I wanted. Rather than auto-completing a person's name, I wanted to provide auto-completion for the part of the email address after the "@". I also modified the code a bit to read the auto-completion candidates from a properties file. This allows you to provide a properties file containing some of the most common email addresses. Below is a copy of a sample properties file.<br />
<br />
<pre class="brush:plain">#################################################################################
# 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
</pre>
<br />
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. If no @ sign, add the text. There is also a check to prevent a second @ from being added to the field. 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.<br />
<br />
<pre class="brush:java"> 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() > maxLength) && maxLength > 0))
return;
String text = getText(0, offs); // Current text.
int atSignIdx = text.indexOf(AT_SIGN); // 1st @ sign
if (atSignIdx != -1 && offs > 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 && text.length() > 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);
}
}
</pre>
<br />
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. 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.<br />
<br />
Thanks to Samuel for posting his code. My updated version can be found at<a href="git://github.com/mikemil/emailAutoCompletion.git" target="_blank"> GitHub</a>.<br />
<br />
Hope this helps!<br />
<br />Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-1012331574809259382012-08-13T21:18:00.000-05:002012-08-13T21:18:49.894-05:00Book Review: MongoDB in Action<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFsYoxqN9BrSX-cl1HTHmPAvDGMgVvjeGUC3X6Zg0s5WbnOmi-uEGuoRdpyQbVfbxmtCdIJue17CviPnbkJ8TxMH5CNlbscBPXoHQV-lDs4CoLpkAVQV9X2RcsHha8WRG2BkVtugTyKBMA/s1600/mongdb_in_action.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFsYoxqN9BrSX-cl1HTHmPAvDGMgVvjeGUC3X6Zg0s5WbnOmi-uEGuoRdpyQbVfbxmtCdIJue17CviPnbkJ8TxMH5CNlbscBPXoHQV-lDs4CoLpkAVQV9X2RcsHha8WRG2BkVtugTyKBMA/s320/mongdb_in_action.jpg" width="255" /></a></div>
<b><span style="font-size: large;">Overview</span></b><br />
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. I didn't really have any specific requirements, like document model vs key value pairs vs graph database. I just wanted something fairly current and covering one of the main players in the area.<br />
<br />
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. The other nice surprise was the size of the book. 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. This book weighs in at 278 pages and that includes 5 appendices!<br />
<br />
<b><span style="font-size: large;">Contents</span></b><br />
The book is broken down into 3 parts:<br />
<br />
<ol>
<li><b>Getting Started,</b> 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.</li>
<li><b>Application Development in MongoDB</b> covers principles of schema design, MongoDB databases, collections, Mongo's query language, updates atomic operations and deletes.</li>
<li><b>MongoDB Mastery</b> covers index and query optimization, replication, sharding and deployment. </li>
</ol>
<span style="font-size: large;"><b>Summary</b></span><br />
An excellent book by Kyle Banker and yet another excellent book from the folks at Manning Publications. I blew through the first two parts of the book, eager to learn more about NoSQL and MongoDB. 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. <br />
<br />
It took a bit longer for me to get through part 3 of the book, no fault of the author or book. 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!<br />
<br />
Overall, I would recommend this book to anyone interested in learning about MongoDB.<br />
<br />
<br />
<br />
<br />Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-26615546553554657242012-07-16T21:22:00.002-05:002012-07-18T15:54:27.054-05:00GDK vs JDKA lot of folks new to Groovy quickly ask the question, "What's is the GDK?" or "What's the difference between the <a href="http://groovy.codehaus.org/groovy-jdk/" target="_blank">GDK </a>and the JDK?" <br />
<br />
If you take a look thru the GDK documentation, you will see that the GDK acts like an extension to the Java JDK. New methods are added to the GDK help remove the ceremony and allow Groovy code to be short and concise. Think of it as a big decorator pattern! 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.<br />
<br />
Maybe a picture will help. You can see some of the new GDK methods added to the Java classes below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp60khOgtGYCDnZ2T9hb5aBLrN-kjWieOD9ScxGP0sGNM_BhtbGZaF8CGehT386WR7XGAq34pGa02agsV3kIsTnZ3y_AGCOxE5TbC9HP4dRdd8bhnoyJwVFCN6FxHundwiE4qvgTzNQmdW/s1600/GDKvsJDK.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp60khOgtGYCDnZ2T9hb5aBLrN-kjWieOD9ScxGP0sGNM_BhtbGZaF8CGehT386WR7XGAq34pGa02agsV3kIsTnZ3y_AGCOxE5TbC9HP4dRdd8bhnoyJwVFCN6FxHundwiE4qvgTzNQmdW/s640/GDKvsJDK.png" width="640" /></a></div>
<br />
Hope this helps!Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com1tag:blogger.com,1999:blog-7371895490737388670.post-49975009101350032792012-07-14T20:48:00.000-05:002012-07-16T20:33:20.545-05:00JBoss AS7 JNDI & EJB 3.1 Naming changes<span style="background-color: white;">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:</span><br />
<br />
<ul>
<li>JBoss 4.2.3 to AS 7.1.x (currently looking at 7.1.1)</li>
<li>EJB 2.1 to EJB 3.1</li>
<li>Hibernate 2 to Hibernate 3 or 4</li>
</ul>
<div>
in quick fashion. I mean, who wants to ship a new release with 8-10 year old software, not me!</div>
<div>
<br /></div>
<div>
<span style="background-color: white;">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. 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.</span></div>
<div>
<span style="background-color: white;"><br /></span></div>
<div>
<span style="background-color: white;"><b>In the past/current</b></span></div>
<div>
In our current code, the JNDI naming has been very simple:</div>
<div>
<ol>
<li><span style="background-color: white;">We </span><span style="background-color: white;">concatenated</span><span style="background-color: white;"> "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.</span></li>
<li><span style="background-color: white;">In the code, we use the following code to handle the JNDI lookup. The really nice part was that the same code could be used by remote clients AND on the server, within the container.</span></li>
</ol>
<div>
<b>Current Code</b></div>
<div>
<br /></div>
<div>
<pre class="brush:java">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);
</pre>
<span style="font-family: 'Times New Roman';"><span style="white-space: normal;"><b><br /></b></span></span><br />
<b style="background-color: white;">AS7 and EJB 3.1</b><br />
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. 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.
<br />
<br />
<span style="white-space: normal;"><span style="font-family: 'Times New Roman';">
</span></span>
<span style="font-family: 'Times New Roman';">AS 7 now has two <a href="https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project" target="_blank">options for remote EJB invocation</a>. The information you need can be found in the JBoss docs, it just didn't hit me over the head! After struggling with this issue for a couple days, I decided to create a small program to help make the differences (hopefully) very clear. Below is the program that I created to invoke a stateless session bean from a remote client. I deployed the "<b>ejb-remote"</b> sample from the 7.1 Quick Start samples. The code attempts to load the remote service using both remote methods. The expectation is that for the first set of lookups, the first lookup is successful and the second, using the "ejb:/" naming format fails. 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. Now, both lookups should be successful. I have included all the JNDI properties in the code rather than relying on a copy of "<b>jboss-ejb-client.properties</b>" or "<b>jndi.properties</b>" being picked up from the classpath. </span>
<br />
<pre class="brush:java">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 < 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 < 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!");
}
}
</pre>
</div>
<div>
<br /></div>
</div>
<div>
<b>AS7 on the server-side</b><br />
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!<br />
<br />
<pre class="brush:java">Hashtable jndiProps = new Hashtable();
jndiProps.put("java.naming.factory.initial", "org.jboss.as.naming.InitialContextFactory");
ctx = new InitialContext(jndiProps);
Object ref = ctx.lookup(jndiName);
</pre>
<br /></div>
<div>
<b>Conclusion</b><br />
As I said earlier, the information was/is in the JBoss documentation, but I probably read past it several times. What I was looking for was an example showing loading the EJBs from both the client and the server. <br />
<br />
Hope this helps!<br />
<br /></div>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com2tag:blogger.com,1999:blog-7371895490737388670.post-74593958743191049802012-03-25T21:59:00.000-05:002012-03-25T21:59:31.054-05:00Ajax Examples upgraded to Grails 2.0.0<b>Overview</b><br />
A little over a year ago, I wrote a blog posting providing a complete set of working code showing <a href="http://programmingitch.blogspot.com/2011/01/grails-ajax-examples.html">ajax examples</a> for each of the Grails tags that supports Ajax. Now, I finally found time to upgrade that code to Grails 2.0.0 (from Grails 1.3.7). 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. Seems like no one wants to <a href="http://en.wikipedia.org/wiki/RTFM">RTFM</a>, we just want to get at it! 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.<br />
<br />
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. 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.<br />
<br />
<b>Steps for my upgrade</b><br />
In order to get my application running under Grails 2.0, I needed 5 basic steps:<br />
<br />
<ol>
<li>Run the '<b>grails upgrade'</b> against my project.</li>
<li>Upgrade database to use H2 - <a href="http://pledbrook.github.com/grails-howtos/en/upgradeToGrails2.html#s2">instructions under Persistence here</a></li>
<li>Install plugins: <b>prototype </b>and <b>resources </b>plugin.</li>
<li>Modify the main.gsp layout to accommodate the plugins (resource, prototype).</li>
<li>Modify <b>Config.groovy</b> to set the java script library to prototype.</li>
</ol>
<div>
<b>Step 1</b></div>
<div>
This step is required for any application being upgraded from an earlier version of Grails. I am not going to say anything else about this step.</div>
<div>
<br />
<b>Step 2</b><br />
Follow <a href="http://pledbrook.github.com/grails-howtos/en/upgradeToGrails2.html#s2">Peter Ledbrook's instructions</a> on upgrading the persistence layer to use H2 database instead of the HSQLDB. If you want to continue to use HSQLDB, there are instructions for that too!<br />
<br /></div>
<div>
<b>Step 3</b></div>
<div>
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. 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!<br />
<br />
Make sure the plugins are installed, and then verify that they all got installed successfully (last statement).<br />
<br /></div>
<div>
<pre class="brush:plain">grails install-plugin resources
grails install-plugin prototype
grails list-plugins -installed
</pre>
</div>
<div>
<br /></div>
<div>
<b>Step 4</b><br />
One of the tricky parts here was including <b>plugin="prototype" </b>on the javascript tag in the header section of this page. Below is a copy of my layout\main.gsp. (Be careful using cut/paste on the page below, I had problems with the syntax highligher or blogger (not sure which) adjusting my html tags as it sees fit). Best option, grab the code from <a href="git://github.com/mikemil/AjaxExamples.git" target="_blank">GitHub</a>. Also be sure to understand the <a href="http://grails-plugins.github.com/grails-resources/guide/1.%20Overview.html#1.1.3%20Edit%20your%20Sitemesh%20layout" target="_blank">changes needed for the Resources Plugin.</a><br />
<div>
<pre class="brush:xml">
<title><g:layoutTitle default="Grails" /></title>
<link href="${resource(dir:'css',file:'main.css')}" rel="stylesheet"></link>
<link href="${resource(dir:'images',file:'favicon.ico')}" rel="shortcut icon" type="image/x-icon"></link>
<g:layouthead>
<g:javascript library="prototype" plugin="prototype">
<g:javascript>
function showSpinner(visible) {
$('spinner').style.display = visible ? "inline" : "none";
}
Ajax.Responders.register({
onLoading: function() {
showSpinner(true);
},
onComplete: function() {
if(!Ajax.activeRequestCount) showSpinner(false);
}
});
</g:javascript>
<r:layoutresources>
<div class="spinner" id="spinner" style="display: none;">
<img alt="${message(code:'spinner.alt',default:'Loading...')}" src="${resource(dir:'images',file:'spinner.gif')}" />
</div>
<div id="grailsLogo">
<a href="http://grails.org/"><img alt="Grails" border="0" src="${resource(dir:'images',file:'grails_logo.png')}" /></a>
</div>
<div id="menu">
<g:render template="/common/menu">
</g:render></div>
<g:layoutbody>
<div id="footer">
<g:render template="/common/footer">
</g:render></div>
<r:layoutresources>
</r:layoutresources></g:layoutbody></r:layoutresources></g:javascript></g:layouthead></pre>
</div>
<div>
<b>Step 5</b><br />
Update Config.groovy to define prototype as the javascript library to use.<br />
<br />
<div>
<pre class="brush:groovy">...
grails.views.javascript.library = "prototype"
...
</pre>
</div>
</div>
</div>
The project has been updated and now available on <a href="git://github.com/mikemil/AjaxExamples.git" target="_blank">GitHub.</a><br />
<br />
Hope this helps!Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com8tag:blogger.com,1999:blog-7371895490737388670.post-84354502084314333892012-01-30T21:02:00.002-06:002012-01-30T21:02:36.368-06:00Book Review: Programming Concurrency on the JVM<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqNmBukt_HEAqkJoUIJ7RT2zwQEzGuA-TnjeH_-UWtEhTAFw8YZ75z_1mNptDALOQ7menue3hMbzxew8DEb8534CQfgcnE6SU-cvsKAHF4qr0G436R6UkfyBdIlUc7O7VKXuhvVw4G83TC/s1600/concurrency.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqNmBukt_HEAqkJoUIJ7RT2zwQEzGuA-TnjeH_-UWtEhTAFw8YZ75z_1mNptDALOQ7menue3hMbzxew8DEb8534CQfgcnE6SU-cvsKAHF4qr0G436R6UkfyBdIlUc7O7VKXuhvVw4G83TC/s320/concurrency.jpg" width="260" /></a></div>
<b>Overview</b><br />
Programming concurrency is a tough task to get right, just ask Venkat, he'll tell you so! 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. The presentation was a condensed version of the book, and needless to say, I bought the book to help fill in all the details. <br />
<br />
Not only is Venkat a 'subject matter expert', but his presentation kept everyone engaged and laughing!<br />
<br />
<b>Contents:</b><br />
The book is broken down in 5 parts, with 10 chapters total, at just over 250 pages. The main sections of the book are:<br />
<br />
<ul>
<li><i>Strategies for Concurrency</i> - this discusses the impact of multi-core machines and the three design approaches that are discussed throughout the rest of the book, <i>Shared Mutability</i>, <i>Isolated Mutability</i> and <i>Pure Immutability.</i></li>
<br />
<li><i>Modern Java/JDK Concurrency - </i>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.</li>
<br />
<li><i>Software Transactional Memory - </i>covers Software Transactional Memory (STM), popularized by Clojure, which places access to memory within transactions. STM is one option for getting away from the 'Synchronize and Suffer' model as Venkat call it. The intention is to make threaded code more deterministic. 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. By putting the memory access inside transactions, the transaction manager helps resolve the conflicts without explicit locking.</li>
<br />
<li><i>Actor-based Concurrency - </i>covers actor design approaches as another option for concurrency design without using synchronization. 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.</li>
<br />
<li><i>Epilogue - </i>is a short recap of the topics presented previously and points out the scenarios when each of the solutions would be appropriate.</li>
</ul>
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). The examples are short and concise, enough to help you to get started prototyping against your own concurrency issues.<br />
<br />
<b>Summary</b><br />
This is a good book to get you started on some of these <b>newer</b> concurrency concepts and libraries. It was an easy read, and I completed the reading fairly quickly, as opposed to the "Java Concurrency in Practice" book, which I started and stopped twice and still have not completed yet! <br />
<br />
I would recommend this book to anyone looking to improve their programming skills in the concurrency area. The book provides you with some alternatives to the old standby of '
Synchronize and Suffer' model.<br />
My last recommendation, if you get the opportunity, attend one of Venkat's presentations, you won't be sorry!<br />
<br />Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com1tag:blogger.com,1999:blog-7371895490737388670.post-12239991228392829052012-01-19T22:03:00.001-06:002012-01-19T22:04:06.193-06:00Passing parameters into Groovy script using Binding classI recently saw a question posted on the Groovy/Grails group on LinkedIn asking about ways to pass in parameters to a Groovy script. There were several responses pointing to the <a href="http://groovy.codehaus.org/gapi/groovy/util/CliBuilder.html">CliBuilder</a> class which is certainly one way to handle the problem. I had just finished reading an article by <a href="http://kousenit.wordpress.com/">Ken Kousen</a> in the November issue of <a href="http://groovymag.com/">GroovyMag </a> where Ken mentioned another option: using the Binding class.<br />
<br />
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. The one tricky part is the question "<a href="http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22">When is something in the Binding and when not?</a>" The answer is: when it's not defined, it is in the binding! In the example below, variable <b>c</b> 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.<br />
<pre class="brush:groovy">// 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()
</pre>
Output
<br />
<pre class="brush:plain">[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
</pre>
<br />
<b>Hope this helps!
</b>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-32437889473476556052012-01-17T22:30:00.001-06:002012-01-17T22:30:32.925-06:00Book Review: SQL Antipatterns Avoiding the Pitfalls of Database Programming<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNwhT5b-4RldvIU5K5kR5yrmdnMo4MyPtVbcO-kSB1Ta2dPKqL8GG_ys9qFqlz_Opssk5o9Yk6_Ug1j9nCvlC89jld5dLWDxqKaUpfeKCNeKpHY5JL6aq15JFJ0KmSGUXzvWLCz1Ynlnci/s1600/sql_antipatterns.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNwhT5b-4RldvIU5K5kR5yrmdnMo4MyPtVbcO-kSB1Ta2dPKqL8GG_ys9qFqlz_Opssk5o9Yk6_Ug1j9nCvlC89jld5dLWDxqKaUpfeKCNeKpHY5JL6aq15JFJ0KmSGUXzvWLCz1Ynlnci/s200/sql_antipatterns.jpg" width="200" /></a></div>
<b>Overview</b><br />
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 <i>'on-the-job</i>'. <br />
<br />
The book is bit longer, approximately 300 pages, than some of the other titles I've read from <i>The Pragmatic Programmers</i> shelf, but it is a very easy read. The chapters all follow a similar format: <i>Object</i>, <i>Antipattern</i>, <i>How to Recognize the Antipattern, Legitimate Uses of the Antipattern </i>and <i>Solution.</i> Each chapter the author leads you through a problem that needs correcting within the scope of the database. Next the antipattern is laid out for you and the author shows the disadvantages of using the antipattern. Tips are provided to help identify the antipattern and he also suggests some possible legitimate uses of the antipattern. 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.<br />
<b><br /></b><br />
<b>Contents</b><br />
The book is broken down into 4 main sections:<br />
<br />
<ul>
<li>Logical Database Design Antipatterns - planning database tables, columns and relationships</li>
<li>Physical Database Design Antipatterns - defining tables, indexes and choosing datatypes</li>
<li>Query Antipatterns - SQL command usage, for example, <i>SELECT</i>, <i>UPDATE </i>and <i>DELETE</i></li>
<li>Application Development Antipatterns - correct usage within the scope of a language</li>
</ul>
<div>
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.</div>
<div>
<br /></div>
<div>
There is also an appendix that covers the <i>Rules of Normalization. </i>I had heard of terms like <i>Normalization, First Normal Form, </i>and <i>Second Normal Form </i>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. </div>
<div>
<br /></div>
<b>Summary</b><br />
This is a very good book for software developers just starting to 'cut their teeth' with databases and SQL. It also serves as a good refresher for those with a bit more database experience. In my case, I fall into the later scenario. You can view it as a book of short stories, showing what <b>not </b>to do in these cases.Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-79109339356409155902011-10-26T13:27:00.001-05:002011-10-26T13:27:12.507-05:00Jars signed with mutliple code signing certificates?<span class="Apple-style-span">For anyone that has built and maintained <a href="http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136112.html">Web Start</a> applications, you have probably been through this issue before. Your QA group or worse yet, a customer, calls to tell you that they cannot start your application because the download failed because "</span><span class="Apple-style-span" style="background-color: white; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px;">jar resources in jnlp are not signed by the same certificate</span><span class="Apple-style-span">".</span><br />
<br />
If want your Web Start application to have full access permissions, then you need to sign all the jars that get downloaded. This generally presents the opportunity to encounter one of the following errors:<br />
<ol>
<li>None of the jars are signed. Most likely a build issue and generally only happens once, (I hope!)</li>
<li>Single jar <x> is not signed. Again, most likely either a build or process error.</x></li>
<li><a href="http://stackoverflow.com/questions/430755/jar-resources-in-jnlp-are-not-signed-by-the-same-certificate">Not all jars signed with the same certificate</a>.</li>
</ol>
<div>
The first two are easy to resolve. 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. Now, it's time to make some educated guesses as to what changed recently and look at the most likely/usual suspects. 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.</div>
<div>
<br /></div>
<div>
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. 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. 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). 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. Writing this in Java would be possible, <b>but why write so much code</b>? <b>Why not write a script in Groovy</b>, it would be some much shorter and concise.</div>
<div>
<br />
<b>Groovy Script</b></div>
<pre class="brush:groovy">def dir = new File("C:\\MyDeployment\\jboss\\myserver\\deploy\\myserver.ear")
def jars = dir.list( { d, f-> f ==~ /.*.jar/ } as FilenameFilter)
def map = [:]
jars.each() {
def zipFile = new java.util.zip.ZipFile(new File(dir, it))
zipFile.entries().each { zipEntry ->
if (zipEntry.name.endsWith('.RSA')) {
if (map.containsKey(it)) {
def list = map[it]
list << zipEntry.name
} else {
map[it] = [zipEntry.name]
}
}
}
}
map.each{ println it}
</pre>
<pre class="brush:groovy">
</pre>
<b><i>Hope this helps!
</i></b>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com1tag:blogger.com,1999:blog-7371895490737388670.post-14747179913187962752011-09-29T16:11:00.000-05:002011-09-29T16:11:17.808-05:00Lessons learned from recent PA/DSS auditThe following are some tips/hints and lessons learned during our recent PA/DSS audit. Everyone's mileage will vary. <br />
<br />
Our application runs on both Windows and Linux. We support JBoss and Weblogic for the application server. We support Oracle, SQL Server and MySQL for the database. We have three client applications which are all WebStart clients, so this is NOT a web application. Our EJBs are EJB 2.1 Session Beans.<br />
<br />
<span style="font-size: large;"><b>Hints</b></span><br />
<ul>
<li>Determine exact software stacks needed including all software levels, build levels and whatever else you need. Collect all of this in one safe place.</li>
<li>Get the hardware ready and any scripts that may be needed to use those devices. Our application is a POS, so we had a collection of pin pads that we were required to test with during the audit.</li>
<li>Get any utility software needed</li>
<ul>
<li>Ghost for Win* images (or Win 7 provides a Backup/Restore feature)</li>
<ul>
<li>We ran into some problems with Windows Server 2008 and had to use one of the <a href="http://www.acronis.com/">Acronis </a>tools to create the backup image.</li>
</ul>
<li>PartImage for Linux images</li>
<li><a href="http://www.dban.org/">Darik's Boot and Nuke </a></li>
<li>anything else you might need</li>
</ul>
<li>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.</li>
<li>Install the OS and any 'base' software, which isn't the software to be verified by the audit</li>
<ul>
<li>Keep the partition sizes as small as possible without causing disk output problems. The larger the disk, the longer the forensic scans will take to run.</li>
<li>On Windows - you can have a page file, just don't allow it to grow and shrink. Set the min and max file size to the same value. </li>
<ul>
<li>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. 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.</li>
</ul>
<li>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.</li>
<li> Our auditor also recommended we turn off the Windows Restore points. Again, you don't want Windows doing any extra work that could impact the audit results.</li>
<ul>
</ul>
</ul>
<li>Take images of all boxes. These may be needed to reset a machine back to a 'clean' state for ad additional set of tests.</li>
<li>Talk to each of your authorization providers</li>
<ul>
<li>let them know when your audit is scheduled and ensure you will have connectivity to their test servers</li>
<li>Verify that each provider can supply 'magic authorization values' that will help your trigger the following responses:</li>
<ul>
<li>approvals</li>
<li>declines</li>
<li>referrals</li>
<li>timeouts</li>
<li>void</li>
<li>split tenders</li>
<li>partial auths</li>
</ul>
<li>If any of the authorization providers encrypt their communications, then you may need to ensure you have whatever is needed for that. We needed to download and install the<a href="http://download.oracle.com/javase/1,5.0/docs/guide/security/jce/JCERefGuide.html"> JCE </a>.</li>
<li>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.</li>
<ul>
</ul>
</ul>
<li>Practice taking images and restoring images on all boxes</li>
<ul>
<li>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.</li>
</ul>
<li>Now you can install your software and you should be ready for the audit.</li>
<li>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.</li>
<li>Our auditor previously used <a href="http://x-ways.net/winhex/">WinHex </a>to do the forensic scans. We used the evaluation version to try and double-check ourselves. The problem with that version is that it is slow and can only scan for one card number at a time. 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.</li>
</ul>
Good luck - hope this helps! <br />
<ul>
</ul>
Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com0tag:blogger.com,1999:blog-7371895490737388670.post-31085719672287290392011-07-20T12:56:00.002-05:002011-07-20T14:34:19.927-05:00Book Review: Building and Testing with Gradle<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOvo4Aeao18HeJyNDliMVobkjAtTgoX0A8Nr-wOM1m1sEIy_j5YTmlVQRl3Lon6S5z8xl1gcy5XcT3SGV-Jl66o-b2LZWRw5dVn78PZNaVsF5iYb4a3RhKxnvoK-GuL2ymNl8Tn6P2uTaQ/s1600/gradlebook.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOvo4Aeao18HeJyNDliMVobkjAtTgoX0A8Nr-wOM1m1sEIy_j5YTmlVQRl3Lon6S5z8xl1gcy5XcT3SGV-Jl66o-b2LZWRw5dVn78PZNaVsF5iYb4a3RhKxnvoK-GuL2ymNl8Tn6P2uTaQ/s1600/gradlebook.gif" /></a></div><b><span class="Apple-style-span" style="font-size: large;">Overview</span></b><br />
<br />
Gradle is one of the new "cool kids on the block". It is quickly gaining momentum as projects like Hibernate and Spring migrate their build processes over to Gradle. Gradle can be considered the 3rd generation of Java build tools, with Ant and Maven representing the earlier generations.<br />
<br />
Gradle is built on top of Groovy, which provides the ability to define a Domain Specific Language (DSL). In this case, the Gradle DSL provides a language tailored to the task of building code. If the DSL does not provide exactly what you need, then you can extend the DSL using plug-ins. It is possible to learn Gradle without knowing Groovy, but some initial knowledge of Groovy is beneficial.<br />
<br />
This <a href="http://oreilly.com/catalog/0636920019909/">book </a>is short (89 pages) . It brings back memories of the O'Reilly "A Developer's Notebook" series.<br />
<br />
<div><b><span class="Apple-style-span" style="font-size: large;">Contents</span></b></div><div><b><span class="Apple-style-span" style="font-size: large;"><br />
</span></b></div><div><div><b>Chapter 1, Hello Gradle</b> This chapter leads the reader thru the installation and configuration of Gradle and demonstrates the ubiquitous Hello World (build file) example.</div><div><br />
</div><div><b>Chapter 2, Gradle Tasks</b> This is the best chapter in the book. It drives home the concepts associated with a 'task' and how the tasks can be configured and customized. The most helpful suggestion in the book is found in this chapter. The recommendation is that you read the <a href="http://www.gradle.org/current/docs/dsl/index.html">Gradle DSL documentation</a>. I had previously read the Gradle Users Guide but was still a bit fuzzy on what the properties and methods were and how they were used. . Reading the DSL documentation provides the full picture. It also helps drive home that you are working with a programming language/DSL and not a set of XML tags like Ant and Maven.</div><div><br />
</div><div><b>Chapter 3, Ant and Gradle </b> This chapter compares and contrasts Ant and Gradle. 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.</div><div><br />
</div><div><b>Chapter 4, Maven and Gradle</b> This is the longest chapter in the book comprising about 25% of the book. 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. Gradle provides support for Ivy, Maven's Central repository and a local repository.</div><div><br />
</div><div><b>Chapter 5, Testing with Gradle</b> This chapter is a good overview of using JUnit , TestNG, Spock, Geb and EasyB. Coverage of testing is a bit light given the title of this book. </div><div><br />
</div><div><b>Chapter 6, Multiproject Builds</b> This chapter does a nice job of taking a sample project and showing three different approaches to creating the project build structure. The approaches shown are one master build file, project-specific build files and a hybrid approach. While the sample projects are very small, they provide the reader a starting point to converting their own multiproject builds.</div><div><br />
</div><div><div><span class="Apple-style-span" style="font-size: large;"><b>Summary</b></span></div></div><div><div>This is an excellent book for getting started with Gradle. There are plenty of working examples provided in the source code download package. The authors do a very good job of explaining the concepts and presenting alternative ways of expressing the same options within the DSL.</div><div><br />
</div><div>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.</div><div> </div><div>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." Sounds good to me, bring it on Tim and Matthew!</div></div><div><br />
</div><div style="font-weight: bold;"><br />
</div></div>Mike Millerhttp://www.blogger.com/profile/09697567698545249690noreply@blogger.com1