Tuesday, September 29, 2009

Open JDK has a lot to answer for

by Richard Vowles

I have never been so disgusted with a podcast as when listening to the excuses coming from Alex and Joe in Episode 279 of the Java Posse Podcast. If there was ever a clear message from Sun that the value of Java code written and maintained in the future is less than the value of Java code today, this was it.

Alex and Joe seem to believe that since the Open JDK now exists, Sun can sit back and pick and choose from implementations that other people do instead of investing in its flagship product (the one its stock ticker is named after, how ironic). Not only this, but they seem to believe that they can do so and be completely fickle about it. Dick's comment about the JCP I think is superfluous, there is no JCP process for JDK 7 so they are putting it in what they will.

Whether Alex/Joe's opinion are a reflection of Sun's official policy I don't know, but I hope that on purchase Oracle dump this attitude (and anyone who holds it) and puts new life into the language. This complacency is simply not acceptable, you innovate or you become irrelevant. I know that the team have to solve modularity in JDK 7 and that it is a big problem to solve, but the messages that Alex and Joe are sending are completely wrong and they deserve a severe caning from PR. The implication is that while Sun spends its resources on JavaFX, its core language, Java languishes. Borland did this with Delphi and JBuilder and look where it got them! (Borland is now owned by a COBOL company, MicroFocus, Delphi is now owned by a database company, Embarcadero - oooooh now *that* is spooky).

IMHO Scala is clearly an academic dumping ground of ideas and the static camp are using it because they have nothing else to express their needs in. And please don't mention JavaFX. Sun clearly needs new and strong leadership in this team to bring Java forward.

After 24 hours I am no longer angry, just extremely disappointed that this situation has been allowed to develop. If ever there was a reason to fork the open jdk, this is it. Larry, its up to you now.

Monday, May 11, 2009

mor.ph and deployment fun

by Richard Vowles

So I use http://mor.ph for deployment of my Grails applications. The development account was great, fantastic to deploy to and try out your application. I didn't realize this transformed (database and all) into your deployed site otherwise I would have held it in dev mode until the customer had set up all their data, but then I wouldn't have discovered some other problems... Like that since you get two app servers, and it load balances, it serializes session state (how often, I don't know). But as I use the Acegi plugin for Grails, it generally (definately in my case) creates a User object - which isn't serialized..... Which means I have been getting persistence errors all through my logs.

Of course, I thought I had solved it with just User and Role, but I forgot I embedded an Address in there as well, and it would need the treatment. Wouldn't it be great if these sites gave you a bundle you could run in a VM on your own machine to mimic their deployment so you could fix your issues before you swap from single server, single db to the full cluster of mor.ph? Oh well, it is a great service in any case!

Sunday, May 10, 2009

groovy tip #3534

by Richard Vowles

Don't do integer arithmetic in gstrings.

int time = 1730
println "${time/100}"

I know Mars Edit is going to screw up that code block. Anyway, although time is an int, it gets converted to a BigDecimal in the gstring, and you get a 17.3 instead of the expected 17.

And last but not least, our first Illegal Argument podcast has gone out. It hasn't shown up on iTunes yet, hopefully that will be soon.

Site Mesh and pageProperty in Grails

by Richard Vowles

So Grails 1.1 comes with SiteMesh 2.4 and uses the FastPageParser. If you go have a look in your web-app/WEB-INF/sitemesh.xml file you will see the following:
        <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
        <parser content-type="text/html;charset=ISO-8859-1"             class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
        <parser content-type="text/html;charset=UTF-8"            class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
        <mapper class="org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper" />

How many of you Grails developers have ever had to look in there? Cool isn't it that Grails shields you from this stuff - one of the many, many reasons why I love this framework.

Unfortunately, FastPageParser is actually deprecated and has bugs when using the <content tag="x"> constructs - HTML comments are output as raw text and <script> tags loose their <. Migrating to Site Mesh 2.4.1 (or .2 now with the GAE) fixes the <script> problem, but not the HTML problem.The partial solution (as emailed to me by one James) is to replace it with the HTTPPageParser - this is faster (by about twice) and is the recommended replacement for FastPageParser.

The only problem is that it has an outstanding bug - if you include an "<" anywhere in an HTML element (e.g. in the value) then the rendering goes haywire. It is a known fault in Site Mesh but no-one bothered to create a test case for Joe or investigate precisely where the problem is. Content tags are pretty important to anyone laying out their content in any kind of sophisticated manner (as is extractProperty, which isn't actually surfaced in Grails for some weird reason), so I gave Joe the test case and narrowed it down to the Lex rules. Unfortunately, I am not a Lex guru, so I had to leave it there.

I'll be putting up a screen cast of this stuff at some point in the near future. I'll link when its available.

Sunday, April 12, 2009

More on Grails Mail

by Richard Vowles

Actually testing the grails mail plugin and having it sending email and then decoding the results were a little more difficult that expected. dumpster 1.6 (last updated in 2005) was buggy for MIME messages - it didn't obey the ordering of the message headers or keep the line feeds in emails.

Then it was finding a way to decode the message so I could spelunk through it and ensure it matched what was required. I'm almost finished now - the attachments file files and byte arrays work, but the InputStream is giving me a Bad file descriptor which I think might be related to trying to read the stream multiple times, but it happens in native code so I'm not sure.

I also have to check how to check JNDI data sources and then I thought I would check the JIRAs for other issues.

A sample method looks like this:

void testSendMailViewWithTags() {
def mailService = new MailService ()
mailService.mailSender = mailSender

def ctx = RequestContextHolder.currentRequestAttributes ().servletContext
def applicationContext = ctx[GrailsApplicationAttributes.APPLICATION_CONTEXT]

mailService.groovyPagesTemplateEngine = applicationContext.getBean (GroovyPagesTemplateEngine.BEAN_ID)

mailService.sendMail {
to "fred@g2one.com"
subject "Hello John"
body (view: '/_testemails/tagtest', model: [condition: true])

assertEquals 1, server.receivedEmailSize

MimeMessage m = new MimeMessage ((Session) null, new StringBufferInputStream (server.receivedEmails[0].toString ()))

MimeMultipart content = m.content
assertEquals 1, content.count
assertEquals 1, content.getBodyPart(0).getContent().getCount() // only 1, it should be text
assertEquals "text/plain", content.getBodyPart(0).getContent().getBodyPart(0).getContentType().split(";")[0]
assertEquals "Condition is true", content.getBodyPart(0).getContent().getBodyPart(0).getContent().trim()

mailService.sendMail {
to "fred@g2one.com"
subject "Hello John"
body (view: '/_testemails/tagtest', model: [condition: false])

assertEquals 2, server.receivedEmailSize

m = new MimeMessage ((Session) null, new StringBufferInputStream (server.receivedEmails[1].toString ()))

content = m.content
assertEquals 1, content.count
assertEquals 1, content.getBodyPart(0).getContent().getCount() // only 1, it should be text
assertEquals "text/plain", content.getBodyPart(0).getContent().getBodyPart(0).getContentType().split(";")[0]
assertEquals "", content.getBodyPart(0).getContent().getBodyPart(0).getContent().trim()

Saturday, April 11, 2009

Changing the new grails-mail

by Richard Vowles

So now that I have set up repositories on github and forked them, I am moving my changes into github for others to use. To ensure they are robust though, they need to have testing - and that is usually pretty difficult for SMTP based email servers - but I have come across a library called dumbster that is designed specifically for unit testing of such facilities!

I'll be creating tests for all of my own functionality as well as migrating the tests for Marc and Greame's tests and start to knock off all the defects that are in the repo for the plugin.

I have a post coming up that has detailed the method that I use for using the pageProperty tag in Grails, but I can't get MarsEdit to change my < symbols for me so I can paste XML/HTML into this document. It is extremely annoying! I might write a Griffon app just to try it out.

Friday, April 10, 2009

I have just been updating the Groovy that comes with Grails 1.1 to Groovy 1.6.1 - and found out that there is a whole heap of Swing and Ant stuff in the file. Given this gets uploaded with your war file, this seems pretty silly. I am sure the Ant stuff gets used in Grails with Gant, but Swing?

There must be a way of getting a swingless Groovy. Useful for Griffon, but clearly not for Grails.

Friday, February 27, 2009

Grails many-to-many

by Richard Vowles

I am sure others have come across this and figured out, but just in case Google (TM) wishes to index it, I had the problem trying to figure out how to remove an item from the many part of one side of a many to many collection.

Here it basically was:

static hasMany = [danceLevels:DanceLevel]
static belongsTo = DanceStyle

static hasMany = [danceStyles:DanceStyle]

So the key here is that you can only remove/delete from the side noted in the belongsTo - you cannot take a dance style and remove a specific dance level from it, you have to find the dance styles on the dance level and remove the style - otherwise Hibernate (although it recognizes the dirty collection) does not do anything about it. No matter how you stuff about the cascade maping.

Friday, February 20, 2009

Grails plugins

by Richard Vowles

So I am working on a replacement website for a customer using Grails and I am using 7 plugins: acegi, easybtest, code-coverage, fck-editor, mail, morph-deploy and navigation. This is cool, the plugins are generally very good, but the only ones I have not had any problems with are easybtest, code-coverage and fck-editor. Why?

  • mail - mail has problems in that it isn't suitable for morph (mor.ph), it also has no support for attachements, has code that isn't reliable (when setting to/cc/bcc) and various other problems. I notice there is a mail-0.6-SNAPSHOT which adds support for headers - done by Peter Ledbrook, which has not yet seen the light of day.
  • acegi - when something goes wrong here, it is almost impossible to figure out what - there is little or no logging. This is really irritating. Other than that, it is an absolutely wonderful plugin that is mature and comprehensive and growing with the capabilities of the Internet (eg. Facebook and openId integration)
  • morph-deploy - this is an early work given the increasing popularity of morph amongst grails devotees, but it is missing the removal of the mail archive (which is understandable as you don't need to do it unless you have the mail plugin!). It is a pity it can't recognize plugins and remove their dependencies if morph doesn't want them
  • navigation - shipped this has blocking faults with requiring logging and occasionally loading before logging is loaded (which is now fixed by Marc Palmer in the latest snapshot) and also that when you have multiple navigation elements in a single controller it blows chunks (null pointers - which is as yet unfixed in the HEAD).
What does this mean for me? Well, I am using grails 1.1 (beta 3) now, and plugins are no longer included in the source tree (which is sensible, it is a good change), but it leads to a big pain in the backside problem - to use these plugins I have to fix them. To fix them - they are not in the local project, and managing them in a source code development environment when you have more than one developer and you need to share fixes is now problematic.

I'm going to need to figure out how to sort this out - and I've bitten the bullet and decided to join grails plugin dev to see if I can make a difference.