jquery

gist JS

Monday, December 11, 2006

X60 Tablet Memory Prices


  • 512 MB PC2-5300 DDR2 667MHz Memory (1 DIMM) [add $0.00]

  • 1 GB PC2-5300 DDR2 667MHz Memory (2 DIMM) Memory Sale! Additional 512MB memory is free (You save: $80).

  • 1 GB PC2-5300 DDR2 667MHz Memory (1 DIMM) [add $90.00]

  • 1.5 GB PC2-5300 DDR2 667MHz Memory (2 DIMM) [add $99.00] [Lenovo recommended]

  • 2 GB PC2-4200 DDR2 533MHz Memory (1 DIMM) [add $820.00]


Does this make sense to anyone? This is just bizarre right?

Wednesday, December 06, 2006

Updated Spring Configuration

Here's an updated version of the HostPrecedingPropertyPlaceholderConfigurer that I introduced here.

This version makes for cleaner property files since you don't need to duplicate everything for each HOST, just the properties that are different.

The goal of this class is to be able to deploy your spring project to multiple hosts without needed to reconfigure / edit any properties files. This method makes it much easier to keep properties files in svn or cvs as well, because when Bob makes a change to the testDB server properties, he won't blow away your DB username etc when you checkout his changes.



package com.aavu.server.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;


/**
* HostPrecedingPropertyPlaceholderConfigurer
*
* Extends PropertyPlaceholderConfigurer to insert $hostname.property if
* the property name starts with HOST
* sample properties file:
*
* jdbc.user=live_user
* server.jdbc.url=jdbc:postgresql://db.host.com:5432/db
* server.magic.file.location=/var/magic_file
*
* jdbc.user=devel_user
* devel.jdbc.url=jdbc:postgresql://devel-db.host.com:5432/db
* devel.magic.file.location=c:\\var\magic_file
*
* my.property=a property referenced through a method besides
* HostPrecedingPropertyPlaceholderConfigurer
*
* <bean id="propertyConfigurer"
* class="com.util.spring.HostPrecedingPropertyPlaceholderConfigurer">
* <property name="location" value="classpath:config.properties" />
* </bean>
*
* <bean id="dataSource"
* class="com.mchange.v2.c3p0.ComboPooledDataSource"
* destroy-method="close">
* <property name="driverClass" value="${jdbc.driverClass}" />
* <property name="jdbcUrl" value="${HOST.jdbc.url}" /><!--Do a host lookup!-->
* <property name="user" value="${jdbc.user}" />
* <property name="password" value="${jdbc.password}" />
* </bean>
*
*
* @author Jeff Dwyer (blog) http://jdwyah.blogspot.com
*
*/
public class HostPrecedingPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {

private static Logger log = Logger.getLogger(HostPrecedingPropertyPlaceholderConfigurer.class);

protected String resolvePlaceholder(String placeholder, Properties props) {

try {

if(placeholder.startsWith("HOST.")){
log.debug("Host: "+InetAddress.getLocalHost().getHostName()+" for property "+placeholder);
String replace = placeholder.replaceFirst("HOST", InetAddress.getLocalHost().getHostName());
return props.getProperty(replace);
}else{
log.debug("reg");
return props.getProperty(placeholder);
}
} catch (UnknownHostException e) {
log.warn(e);
return null;
}
}
}

Friday, December 01, 2006

Changing cats into dogs

Hibernate Modifying subclass's discriminator value on update

Well, despite the naysayers above I've succeeded in doing the unnatural and have changed the type of a polymorphic Hibernate class.

Dog changeCatToDog(Cat cat){
int res = (Integer) getHibernateTemplate().execute(new HibernateCallback(){
public Object doInHibernate(Session sess) throws Exception {
String hqlUpdate = "update Animal set discriminator = 'dog' where animal_id = :id";
int updatedEntities = sess.createQuery( hqlUpdate )
.setLong( "id", cat.getId() )
.executeUpdate();
return updatedEntities;
}});

getHibernateTemplate().evict(t);

return (Dog) getHibernateTemplate().get(Dog.class, cat.getId());
}

Monday, November 27, 2006

Micro$oft Money 2007

"Pissing off your customer before the software is even installed."

A play in 3 parts with one nano-spam bot.

Act 1
We'd like to keep you informed via email about product updates, upgrades, special offers and pricing. We will not pass your details onto third parties. If you do not wish to be contacted via email, please ensure that the box is not checked.

Nice one M$oft. Nice one. This is how you win my trust. Don't even pretend you're illiterate and that that wasn't intentionally confusing. How about "If you wish to be contacted, check the box."

Act 2
Some $6 extended download protection crapola that has absolutely no description of what it does. What, am I just supposed to quiver in fear of what might happen if I don't buy it? Assoles.


Act 3
oo more fun.
Hidden at the bottom of the rebate in the smallest text you've ever seen is a little 'please check here not to be spammed' box. I guess they decided the double negative wasn't necessary since it was in 6 point font. Really, it's almost worth purchasing the software so you can download this pdf and see how absurdly small it is. It would almost be cute if it weren't so evil. Kind of like a nano-spam bot.


and now that we've installed... Act 4
Microsoft Money 2007 is a steaming pile of $hit. I've just frozen it three times in as many minutes. Seems that "Is this your regularly scheduled transaction?" actually means "Go into endless loop?"

Sunday, November 19, 2006

Don't miss this

My god. Or.. do I mean 'his' God?

Sunday, October 08, 2006

bile

I'm not a particularly bilous fellow, but the advantages of disgorging one's Bile on the Internet are well known, so here goes.

One. When did NOVA become a childrens show. They just introduced the periodic table. And there's a neutron cartoon with a bungie cord. I remembered NOVA as being an interesting show operating with a small assumption of a shared scientific background. No? Maybe that was just me.

Two. Tony Kornheiser. Now there's a reason to listen to football on univision like I do for the world cup (side-bile: ABC, here's how you sort this out. Fly to Dublin. Go into a pub. Find a mean looking guy and knock him over the head and drag him back. Now fly to Italy, Turkey and Mexico. Repeat. Give them all microphones & free beer. Now you're sorted. Repeat for all major sports telecasts except wrestling, which would be much more entertaining hosted by the 5 queer eye guys. Actually have them host everything on your network. Them or the MST3K guys.) The only good news to come out of this is that I've never really like Joe Theismann's style much, but now I really like to hear him get irritated w/ Kornheiser, since I'm so darn irritated myself. If there's a rumble in the studio at some point this season I promise I'll watch more than 2 games next year. But c'mon, he sounds like a man who's never watched a football game. And my god he wouldn't shut up about the game being over. Who does that? Isn't the whole point of commentators to get you to stay there and watch the ads until MNF finished at 1:30 in the morning in some 37-10 rout? But now I've got Kornheiser calling the game after the half and giving me special insight into the fact that the momentum isn't going their way. Bring back Dennis Miller. He didn't belong either, but who cares.

Erm Three. Not sure. I'll think of something. I told you I wasn't very bilous. Um.. the state of health care in the US. Not very bilous eh? fine. go see hani.

Wednesday, September 27, 2006

Hibernate cannot dereference scalar collection element

You're getting this because nobody told you about the secret little hibernate 'elements' and 'indices' functions. Yes I know there's 1001 tutorials/books/etc on how to creating a mapping file with lists or sets or maps. But no, no of course it wouldn't be usefull to put in said tutorials a small hint as to how one actually queries these collections.

from the hib docs:
"
from Player p where 3 > all elements(p.scores)
from Show show where 'fizard' in indices(show.acts)
"

Monday, September 25, 2006

Old office. New office.



First the old office. A study in comparative cultures and attitudes towards ourselves. Notice the wall of failed build CD's. Notice how being haunted by past failures in this environment seems to make sense.

Notice the smiley face mug near my hand. Notice the soothing stress balls. Notice the paper behind my head, Keller's recipe for the best roast chicken ever. A priceless document scavenged from the bowels of the Internet and the only real treasure one can expect to find in cubicle-ville.

Notice the shirt that says DREAM contrasted with the general lack of dreams..

Ok, enough of that.



Now the new office.

Mark, you'll notice that even without stepping out the door there is much fall goodness to be had here. But your reminder does not go unheeded and is well appreciated. I won't forget to go find the real mountains too.




This is the conference room. Still 1-man show so we don't have to worry about OSHA regulations for cliff-side offices.





Leisure room. Sadly no dart board. You can't have everything.

Saturday, September 09, 2006

Plea to the CSS Gods

oh css gods why have you forsaken me!

So css is the one true path. fine. I don't much care, but fine. I'll go with your standard.

Great, DIV's. I can make little boxes wherever I want coolio. Let's try to little 2 little red boxes, ten pixel on the side, touching corners. Easy right?

<div style="background-color: red; position: absolute; left: 200px; top: 200px; width: 10px; height: 10px; padding: 0px; padding-right: 0px;"/>
<div style="background-color: red; position: absolute; left: 210px; top: 210px; width: 10px; height: 10px; padding: 0px; padding-right: 0px;"/>

Whoa! Those corners aren't even close!
(At (200,200) on your screen there's a little red box. At (410,410) there's another)



hmm.. let me bash my head into a wall for 20 minutes. ok, that's better. how about:

<div style="background-color: black; position: absolute; left: 250px; top: 250px; width: 10px; height: 10px; padding: 0px; padding-right: 0px;"></div>
<div style="background-color: black; position: absolute; left: 260px; top: 260px; width: 10px; height: 10px; padding: 0px; padding-right: 0px;"></div>

ahhh... yes. I see. Closing the tag with another tag is the One True Path(tm) Shame on you who would assume that the way in which you close your tag should be completely friggin irrelevant to how it's layed out on the screen.






can anybody explain this to me?



Friday, September 01, 2006

GWT NestingCallbacks

Spent some time playing around with creating GWT callback "nests". Basically the idea was to have something where you could add a bunch of AsyncCallbacks into a queue, then have them fire each other off.

Basically, I wanted a blocking async call, but after reading some very good posts about this found that it's just not possible due to some javascript thread things. Moreover, it really avoids the whole point of async GUIs. (Granted, I'd planned to have a cache, so that it was unlikely to need the nested calls to be truly asynchronous, blah blah...)

Anyway I solved my problem another way, but I may play around with these nested callbacks some more. I liked the idea of big asynchronous monsters rolling around in my code.

Man I'm enjoying GWT.


public class NestingCallbacks {

List nest = new ArrayList();

/**
* add it to the beginning
* @param nestable
*/
public void addToNest(NestedStdAsyncCallback nestable){
nest.add(0, nestable);
}

public void doIt(){

System.out.println("doIt");
NestedStdAsyncCallback cur = (NestedStdAsyncCallback) nest.get(0);
nest.remove(0);
cur.run(nest);

}

}




public class NestedStdAsyncCallback {

private AsyncCallback callback;

public NestedStdAsyncCallback(AsyncCallback callback) {
super();
this.callback = callback;
}


public void run(List nest) {

System.out.println("run ");

callback.onSuccess(null);

if(nest.size() > 0){
System.out.println("nest size now "+nest.size());
NestedStdAsyncCallback next = (NestedStdAsyncCallback) nest.get(0);
nest.remove(0);
next.run(nest);
}else{
System.out.println("end of the line");
}

}


}

Tuesday, August 29, 2006

Seam's audacious approach

Well, this thread on tss pointed me to a pretty damn interesting podcast from our friend Gavin about Seam. Pretty amazing actually.

Getting around the fact that Gavin can be something of an unrestrained ass, he is also clearly clairvoyant about some things. In fact, if I were to offer up my own flash of amateur psychology (and what else are blogs good for?) I'd say that it's simple audacity that makes Gavin King tick, and that that's why he's been so successful at shifting the landscape. If you're not a fan of his, you should listen to this too. While I myself have cursed Hibernate & the sometimes brusque forum, it is understandable that you'd be a bit frustrated the 6000th time somebody pisses & moans that the free framework you developed doesn't serialize the entire DB and send it over to fix your lazy load problem.

Coming into this podcast I was really skeptical of annotations. They seemed like a separation of concerns nightmare waiting to happen. Deployment specific tags just waiting to be incompatible. I say give me the nice clean lines of a pure & simple POJO.

But now I'm not so sure.

There's a real point to be made that my POJO's are really nothing without Spring's DI, and the rest of my Spring MVC web tier is of course tied closely to SpringMVC. In fact there's nothing really wrong with this either, and I've found Hibernate/SpringMVC/Freemarker to be an eminently workable combo. Plugging Acegi in was cake & my simple GWT wrapping site with user administration was the work of an afternoon.

Moreover, there sure was a lot of power in those annotations. And would it be any more embeded and than switching from what I've got now? I do have to disagree with a bit of his disdain for layers however. I really DID switch my database tier out the other day (db4o to hibernate) and the process was lovely. New DAO impl's, new appicationContext-hibernate.xml and... off she goes! Well, up until GWT bonks on a hibernate PersistantList, but that's for another day.

The main revelation in the podcast is Gavin's defense of stateful web applications. After some amusing IBM potshots, he really starts to make some sense (interestingly, the more expletives/minute the more sense he seems to make.) The only real issues I've had with Spring MVC have been
  1. Inefficiencies from not wanting to use the session, because.. well the session was verboten at work due to vapor-concerns about scalability

  2. Back-Button, refresh, history...

  3. Lazy Loading, NonUniqueIdentifier etc. exceptions


Seam's great solution is to just go ahead and use the session, but to introduce the idea of conversational scope. While this is precisely what Spring WebFlow does as well & I could've solved a couple of the problems above more easily with access to the session, I have to admit that Seam's implementation was pretty darn slick. I'd love to hear a good debate about the relative merits of the two (well, a bit flamey, but still good), as well as somebody to rebut Gavin's assertion that stateful session beans are not as unscalable and unworkable as we'd all been led to believe.

And back to audacity. Finishing up that podcast I really wonder whether being such a... so forthright, about his opinions really leads to more willingness to innovate. I love the Spring project, but I wonder if it will end up too much of a fixed J2EE and not enough of a revolution.


I'd really love to see a little more about Seam's Ajax capabilities. That's on the things to google list. Right now I'd definitely consider Seam vs my Spring MVC for a new traditional web app. However for the project at hand, the guts in GWT land and I wouldn't throw away my ability to manipulate DOM code like a Swing-set for all the component based wonderful-ness on offer.

Just don't load my site in two tabs at the same time ;)

Thursday, August 17, 2006

java MD5 password hash

So you want to hash a password, store in the DB and go on your merry way. Not being wise in the way of hashing you might think that a simple google for "java MD5 hash" will do you right, but you'd be wrong. In fact it has a good shot of leading you to something like the following (at least 2 examples that I found), which has a cute little bug lurking beneath the surface.

private String hashPassword(String password) {
String hashword = null;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(password.getBytes());
BigInteger hash = new BigInteger(1, md5.digest());
hashword = hash.toString(16);

} catch (NoSuchAlgorithmException nsae) {

}
return hashword;
}


hashPassword("test")->
98f6bcd4621d373cade4e832627b4f6

but the right answer is:
098f6bcd4621d373cade4e832627b4f6
(note the '0')

The trick of course is that the integer 045 == 45, even in bigInteger land.

A simple

return pad(hashword,32,'0');
private String pad(String s, int length, char pad) {
StringBuffer buffer = new StringBuffer(s);
while (buffer.length() < length) {
buffer.insert(0, pad);
}
return buffer.toString();
}

will sort you.

Glad I chose "test" as a test password or I might have found this at a more unfortunate juncture as the other 3 test users I created worked without a hitch. Amazing to think that in this day and age, blindly copying code from the Internet into you app is still an imperfect method of application development.

Of course if you copy & paste this code, well, that's totally different. It's been tested.. er.. well visually inspected for at least.. um.. a minute.

OMG there's a new Neal Stephenson book.

Wednesday, August 16, 2006

NoSuchRequestHandlingMethodException for your MultiActionController?

Make sure you're returning the right type of ModelAndView from your MultiActionController.


import org.springframework.web.servlet.ModelAndView; --good--
import org.springframework.web.portlet.ModelAndView; --bad, and very frustrating--

Sunday, August 13, 2006

Thoughts GWT, SCM, etc

So just slammed into subversive's:
170002: Unknown authorization method

after switching my project over from subclipse 20 minutes before since I'd become totally fed up with strange 'this directory is already in the repository' comments and general arcane error messages that must be cleared with oddly named menuitems. Do I lose cool points for saying I'd be more than happy to go back to cvs? I understand the svn arguments, but really scm is 99% the eclipse plugin and 1% source code management theory for me.

Thankfully Igor at Polarion seems to have sorted subversive in 1.0.1... Oh except for the fact that 1.0.1 seems to rogered everything and now it tries to connect to svn%20ssh instead of svn+ssh. Sweet. He says it'll be fixed Friday. I think that was 2 days ago.

happily reverting subversive 1.0.0RC2 seems to have worked, although it did delete all of my repository information & disconnect me automatically for all of my projects without asking nicely...


Thankfully GWT continues to be a favorite bauble. Most of my complaints are based simply on my impatience. Integrating Acegi is going allright, although it has exposed some tradeoffs that are important to keep in mind. If you'd like you com.myco.client.domain.User to implement acegi's UserDetail... you're in for a bit of frustration as even once you figure out that you need to have the source included in you 3rd party acegi.jar, you're still stuck with futsing with module.xml's and inheritance etc that will soon make you run for cover.

com.myco.server.domain.ServerSideUser extends User has sorted me for now, although the proliferation of workaround code continues.

Starting to poll for developers to enlist in aid of my new project. This is not a dig on my friends, but I'm starting to wish I'd spent a bit more time playing video games in college and getting to know the code kittens. These artsy well rounded types can program worth a damn.

-j

Friday, July 21, 2006

Thoughts on the GWT

Cons:
No java 1.5 generics feels a bit like someone killed my pet fish. (Note: this is only a little like having your puppy killed.) Really though, I had no idea how nauseous untyped collections make me.

Serialization is still definitely a bit rough. I've been converting everything to lists before it goes over the wire and this has made things better, but I will be very stoked when a release come out that fixes this and I can rip out all manner of Set->Array->Set code. Some people seem to claim it already works, but all I know is that Set s = new HashSet(); explodes serialization for me.

Also, I wanted my domain object to have a Widget property, but I think I'm going to have to back down on this one. Specifying transient worked as advertised, but then when the object is deserialized on the server it tries to create the widget and I get a "GWT has not been properly initialized" issue. Some insightful comments about this type of thing here.
There are definitely some rough edges.

Lastly, while reports of Spring integration abound I would warn you not to accept this as given for the moment. The amount of head banging into odd errors is on the high end of the scale, and you'll soon find yourself connecting to svn repositories on a laptop in Poland in the vain hope that you'll be able to make sense of someone random Poles framework.

Just in general, my attempts to integrate with just about anything else have been pretty rough. Even deploying to something out of hosted mode brings lots of gotchas that will make you pine for "mvn package" like a baby. They're mentioning maven usage for the next release, but let's all cross fingers for maven 2, eh?

Pros:
In general though, the speed of development is astounding. Well, maybe not so astounding if you're used to writing desktop apps where creating a functional rich GUI is pretty easy, but compared to anything else out there.. I feel like this is the future plain & simple. I looked at the new Dojo release yesterday and, while I would have been interested a couple weeks ago... now it just doesn't thrill me at all. Scriptaculous integration is super easy, so you get all your fun tricks. If all you need is a couple auto-completes I think rails or grails, or spring mvc & scriptaculous are all lovely choices. The second you start thinking about DOM manipulation though, despite all the nice looking MochiKit type things, I just can't imagine not giving GWT a shot.

In combination with db4o I can't imagine a faster way to get a web 2.0 app up and running. We'll see how long db4o makes it as our db of choice, since I read disconcerting things about max ~10 requests/sec, but I promise you you'll fall out of your chair the first time you just call db.set(myReallyComplexObj) and everything works like a charm.

Monday, June 05, 2006

google getting sloppy

or have they always been? I forget?

So I go to check out Google Reader... Not that I don't love my sage, but when the 500 lb. gorilla dances... um... you dance with it? I'm not really sure where I was going with that. It's all getting a bit graphic.

Ok hmm importing a list... ok it wants OPML fine, never heard of it. And sage? Hell's yeah, export to OPML. Now just import into google... and kabam. Very not happy.

Ok, we're back from Google message's temporary lapse. Cool, I can mouse scroll through the list... but it doesn't select anything. hmm. Maybe they're "Getting Real" & getting the product out there, bugs be damned.

Overall I guess it's allright. Getting my news reader away from machine dependencies is good, although I'm mostly just happy that I found the import/export in sage. I like my information all layed out before me.

Sunday, June 04, 2006

Kundera

"It would be senseless for the author to try to convince the reader that his character once actually lived. They were not born of a mother's womb; they were born of a stimulating phrase or two or from a basic situation. tomas was born of the saying "Einmal ist keinmal." Tereza was born of the rumbling of a stomach."

Thursday, June 01, 2006

Alternatives to Advanced Configuration of the Spring MVC Framework

So I read a good article Advanced Configuration of the Spring MVC Framework and his final solution is a whole bunch of applicationContext-somehost.com.xml configuration files.

Hmm... it addresses the problem, but how about we just add the hostname into the properties file and append the hostname before we get it?

ok, ok, it screws with some assumptions about what a properties file is, but it deploys on as many hosts as you like, with changes limitted to this one file.


server.jdbc.user=live_user
server.jdbc.url=jdbc:postgresql://db.host.com:5432/db
server.magic.file.location=/var/magic_file
devel.jdbc.user=devel_user
devel.jdbc.url=jdbc:postgresql://devel-db.host.com:5432/db
devel.magic.file.location=c:\\var\magic_file

my.property=some other prop


<bean id="propertyConfigurer"
class="com.util.spring.HostPrecedingPropertyPlaceholderConfigurer">
<property name="location" value="classpath:config.properties" />
</bean>
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>

package com.util.spring;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

/**
* HostPrecedingPropertyPlaceholderConfigurer
*
* Extends PropertyPlaceholderConfigurer to insert $hostname.property
*
* sample properties file:
*
* server.jdbc.user=live_user
* server.jdbc.url=jdbc:postgresql://db.host.com:5432/db
* server.magic.file.location=/var/magic_file
*
* devel.jdbc.user=devel_user
* devel.jdbc.url=jdbc:postgresql://devel-db.host.com:5432/db
* devel.magic.file.location=c:\\var\magic_file
*
* my.property=a property referenced through a method besides HostPrecedingPropertyPlaceholderConfigurer
*
* <bean id="propertyConfigurer"
* class="com.util.spring.HostPrecedingPropertyPlaceholderConfigurer">
* <property name="location" value="classpath:config.properties" />
* </bean>
*
* <bean id="dataSource"
* class="com.mchange.v2.c3p0.ComboPooledDataSource"
* destroy-method="close">
* <property name="driverClass" value="${jdbc.driverClass}" />
* <property name="jdbcUrl" value="${jdbc.url}" />
* <property name="user" value="${jdbc.user}" />
* <property name="password" value="${jdbc.password}" />
* </bean>
*
*
* @author Jeff Dwyer (blog)
*/
public class HostPrecedingPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {

private static Logger log = Logger.getLogger(HostPrecedingPropertyPlaceholderConfigurer.class);

protected String resolvePlaceholder(String placeholder, Properties props) {
try {
return props.getProperty(InetAddress.getLocalHost().getHostName()+"."+placeholder);
} catch (UnknownHostException e) {
log.warn(e);
return null;
}
}

}




UPDATE So I've noticed that this was a pretty popular entry & I thought I should update it to what I'm actually doing now. I've put in a little if/else & regex that replaces "HOST*" with the hostname. So now my properties still look like:

server.jdbc.url=jdbc:postgresql://db.host.com:5432/db
devel.jdbc.url=jdbc:postgresql://devel.host.com:5432/db

and they're referenced by ${HOST.jdbc.url}

This way you don't need to copy all the properties for every machine, just the HOST-specific ones. This is all working very well in production and makes scm of properties files much much easier, alleviating the confusing deploy time errors when everything seems broken and you realize someone has checked in development properties which override the correct server properties.

Monday, May 15, 2006

Travels, travails, freemarker

Spring MVC, freemarker boolean form check.


<#macro booleanFormCheck path attributes="">
<@spring.bind path/>
<input type="checkbox" id="${spring.status.expression}" name="${spring.status.expression}" value="true"
<#if spring.stringStatusValue == "true">checked="checked"</#if> ${attributes}
<@spring.closeTag/>
<#assign hiddenName = "_"+spring.status.expression/>
<input type="hidden" name="${hiddenName}">
</#macro>

First off, I must be the 100th person to write this. A little boolean formCheck that puts the hidden field in for you? spring.ftl is well and good, but how about a new bloatedSpring.ftl with lots of goodies like this one.

Printing a date that might be null in freemarker


Sounds easy right? Well, I'm sure it is, but damn if I didn't spend a half hour massaging my temples. (oh and I'm positive there's a lovely way to do this in place, but I'll be damned if I'm going to spend any more time looking.

<#macro printDate date="">
<#if date?has_content>
${date?date?string.short}
<#else>
None Provided
</#if>
</#macro>


Turning a number that's been turned into a string back into a number.


(If the number is greater than 999)
Right. So it all works fine. You've got a nice drop-down select. Now you (silly thing that you are) want a confirmation page, but rather than telling them they've selected pop-rocks flavor #38, you want to tell them that they've selected flavor "Rasberry Crush", so pop that back in the referenceData and off you go...

up until you get to flavor 1000 (or should I say "1,000"). Then you spend a while sitting in front of the people you convinced ot ditch jsp, helplessly trying to change you internationalization settings to take out commas and having simple no luck with ?int and it's ilk... until you find... ?c

<#macro printLookup array element>
<#if element?exists && element?string == "-1">
None Provided
<#else>
${array[element?c]}
</#if>
</#macro>

Happily this also solves other infuriating 9300->"9300"->(int)9,300 freemarker bind exception explosions:

<#macro formInputInt path attributes="" fieldType="text" >
<@spring.bind path/>
<input type="${fieldType}" id="${spring.status.expression}" name="${spring.status.expression}" value="<#if fieldType!="password">${spring.status.value?default(0)?c}</#if>" ${attributes}
<@spring.closeTag/>
</#macro>
<#macro formHiddenInputInt path attributes="" >
<@formInputInt path, attributes, "hidden"/>
</#macro>

Wednesday, May 03, 2006

Books - Spring 06 Edition

Books aquired:
  • Bully for Brontasaurus, Gould

  • The collected pdf's of John Searle


Books held in hand significantly at bookstore:

Books read:
  • The System of the World, Neal Stephenson



Well, the beast that is the Baroque Series is finalement slew. It is a true testament to a work of fiction that the last 80 pages of your nigh-on 3000 page odyssey are things to savor and nothing at all like the grim dregs of a cup of flip gone wrong. One can only hope that Eliza de la Zeur will return in another time. I am very much unfinished being in love with her.

The Searle bears explaining I suppose.

Oh and all apologies to Nick Hornby. My use of your lovely format is intended only for personal use. All other use is expressly unintended and wholy unexpected as you can clearly see by the number of people that frequent this blog.

Thursday, April 20, 2006

freemarker sitemesh body onload

So you've got a:
<body onload="doMyOnload();">

in your freemarker template, but
<body>
${body}

in the decorator blows this away...

The site mentions
<body onload="<decorator:getProperty name="body.onload" />">
but you're not using jsp because you've convinced yourself you're better than that.


So you eventually figure out...

<body ${page.property["body.onload"]}>

And you're all set again. Isn't that nice. 29 tabs died to bring you this information. Use it wisely.


UPDATE the commenter speaks the truth. I'd switched over at some point but never updated this.
<body onload="${page.properties["body.onload"]?default("")}">

Tuesday, April 11, 2006

Freemarker Booleans in Beans

Note to self, making model beans that you want to use in Freemarker? Make sure them boolean's are java.lang.Boolean (in the docs) and change your getters from isMyBool() to getMyBool() (not in the docs), otherwise it's headscratching time trying to figure out why it can't find your junk.


Expression command.myBooleanis undefined on line 262, column 6 in WEB-INF/freemarker/verify.ftl.
The problematic instruction:
----------
==> if command.myBoolean [on line 262, column 1 in WEB-INF/freemarker/verifyStudy.ftl]
----------

Java backtrace for programmers:
----------
freemarker.core.InvalidReferenceException: Expression command.myBoolean is undefined on line 262, column 6 in WEB-INF/freemarker/verify.ftl.
at freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124)
at freemarker.core.Expression.isTrue(Expression.java:145)



Most important though is to get on junit testing your freemarker views. Getting this all set was such a lovely vindication of sorts for me. Nice tests all the way from the DB to the web? Without this testing the above would've been misery. Now? I just feel pretty much invincible.

Monday, March 13, 2006

why I like being a programmer

A couple reasons why I like being a programmer:


  • There exists a task to deploy your war file to Tomcat. But using the oh so odd configuration of Windows XP & Tomcat 5.5 & Ant 1.6.5 actually trying to run this task just fails, and you don't know why until you find a post called:
    i-put-a-spell-on-you-because-youre-mine-aka-why-is-tomcat-holding-onto-jars


  • -First off, you get to be on the cutting edge.
    -Even better, you get to buy books written by the actual authors of these opensource packages.
    -But most fun is reading about your fellow plebian developers getting smacked down on public forums by these same developers for not being able to figure stuff out.
    Stop arguing with me, and obey the migration guide! Down boy!


  • Long winded comparisons of how different web frameworks handle really simple tasks, and no examples anywhere of anyone doing anything half as complex as anything that seems to be of any use. But perhaps that's better described over at the Bile Blog.

Friday, March 10, 2006

photo splash


I swear I had no idea that pink and yellow clashed this much. I assure you I'm taking steps for next season.


ALLEZ!!


This is the beginning of my in-office vineyard. Don't rain on my parade.


I worked on this boat for an entire summer back in 2000, and I can tell you that I have more experience with varnish & that tap rail than anyone in their right mind should have. And that's not even getting into the joys of repainting the chain locker.. Anyway it looks like somebody new has purchased her from the pair that I worked for and pushed the marketting up a couple notches. I can't say it's not worth it though, she a pretty great sail and has pretty much spoiled me for life as far as the big boats ae concerned..

Monday, January 30, 2006

The preDickies are back!!

The best darn oscar predictions on the whole Internet.
Tommy's Oscar preDickies

Dartmouth Podcasts

Wow.
Dartmouth Podcasts

go alma mater. how hip.

Thursday, January 26, 2006

wilco's experimental sound.

here's one thing I'm done with. Experimental ambient sound.

Wilco 'A Ghost is Born,' track 11 minute.. about 7:00 to 9:00. I'm listening to it right now. Why? I'm mostly scared it's going to hurt my ears. This won a whole bunch of awards for best blah blah of the blah blah. I bet the reviewers skipped this bit though. Track 11, album's almost over... next.

Is this fit for anything but skipping? Does anyone listen to this track regularly? Hey, put that on? Yeah, groovy. You can't exactly dance to it, but.. I like it. It sounds like.. like.. 'A stoned dude with keyboard effects?' Yeah. Ok fine, the ability to listen to it regularly isn't really a good criteria. I'll grant that. But how about just ever.

Do I lose artistic legitimacy for not being able to take this?

Allright, it's still going. I was going to listen to it so that you wouldn't have to, but I'm done. No more suffering for the masses. If you want to know what it sounds like you'll have to do it your damn self. The bit I listened to sounded a bit like being in a a warehouse with some some weird aliens trying to open a portal into our world or something. You know what I mean. Don't pretend you don't.


Of course I do kinda like this album...

Thursday, January 12, 2006

Affordable luxury

So, you work in a cubicle. We'll assume this as granted since who else has the kind of Internet access and free time necessary to find something like this.

It's winter. There's no sun. There's no window (anymore, but that's a long story). You're tired. You stayed up late. You woke up.. well late, but the point is you're tired. It's a Monday. Or a Thursday. Or really any day. Are there even days anymore? You've been sitting here as long as you can remember.

That's right kids, it's time for comfort purchasing.


But some comfort purchases don't really deliver. You buy the English language canon Amazon recommends for you based on your somewhat idealized preferences, but you don't have the time to read these things. Clothes are lovely, but you sit behind a desk. Who are we kidding? We don't need sundresses and yachting wear or even rugged wicking things. We should just wear sweatsuits to work. Or those one piece reflective unitards of the future. Or little yellow and black worker bee suits.

Point is it's no good buying things that make you wish you weren't there. I mean here. Focus people. You're in your office and that's where you get paid to be.

But you feel this overwhelming lack in your cubicle. What will fill it? Will anything?

And this is the part where you should rejoice. Because you're reading this, and I'll tell what to buy. Grado RS-60 headphones.

Wasn't that easy? Now you want proof I'm sure, and besides you need something to read until they arrive. We'll that's where the Grado's really come into their own. A world wide web (for lack of a better phrase) full of people that spend their lives posting to newsgroups to make you feel better about your purchase. You read reviews, you read anecdotes, you start making snotty references to top of the line Sony headphones. You get them. You listen. You bathe in the glory of your most excellent purchase.


But then comes the inevitable fall. Your life has been transformed. Your music tastes are changing. You're changing. Listen to that sound! You can hear everything. Is someone coughing in the recording studio? You feel like offering him a lozenge he's so close. Jazz is amazing. Vocalists can be downright naughty. You're practically inside Eric Clapton's strings... and Bob Dylan. Well, actually Bob Dylan is starting to creep you out a little. If you close you eyes it sounds like his throat may be trying to kill him.

And yes, amongst these flowers is you downfall. You have another computer at home. You dislike carrying your cans (see how cool you've become) around with you. You opt to buy another pair... and you slip into the dark dark world of the audiophile.

You purchased the SR-60 and it changed your life. Simple, buy another pair of these amazing devices. Hahaa! MwahHahHah even! Because you're now cognizant of the power of music, you idly let your eyes gaze down the list of available Grado's... 60's... 80's ... 125's start to seem like an option... they make aluminum ones! And wood ones at the top of the line? Wood? Wood! My good god all I we need in life is a pair of Grado RS-1's and the gorgeous little amp they rode into town on!

But you hold back. You're analytical, quantitative... but this gets you nowhere. "You're among the qualitative people now!"

But you snap back to reality. SR-60's eh? For beginners. Next? 80 eh? more bass... ok... but what am I missing up there? I'm already hearing things I've never heard in the music before, what else could there be? What else is out there! $150 for the SR-125's is starting to put up warning flags... but what's this? Alessandro MS-1? Who are these masked crusaders? I only buy Grado, but... modded Grados? You mean some Italian man in Chicago buys Grados microwaves them and resells them? The connoisseurs choice you say? Not everyone knows about them? Even your trusty newsgroups are starting to fail you. Some people write in saying they're the best.. but most are clamoring for information. Where can you even buy them? It's all unclear. Does the grand pooba 'John My Last Name is Grado' endorse them? Is this an underground thing? Slowly, you get the feeling that those who've bought them are too involved in their music to even come to the forum any more.. they've achieved musical Nirvana!! What have you done? What are you waiting for!

And then they come. What a day. You take them tenderly out of their box. Just like your SR-60's but Alessandro! You can't wait... you plug them in... and your fate begins to tighten around you.

They sound.. good, great, but now you've got to compare them to the 60's. You listen to the same song, furiously switching between the two. Comparing passages. Is there a difference? You attempt a 'blinded' switch.. you can tell the difference with your eyes closed.

But the 60's are the winners.


You're desolated. You return to the forum full of sad news, but soon remember your saving grace. You've forgotten the fabled 'burn-in.' You return home and methodically 'burn' them in, leaving them playing at above comfortable volume all night long. The next day is the new big day... no. Wait, yes! There is more bass. Yes. There is truly richer bass. Thank you, oh spirits of the cubicle!

But this joy and laughter lasts only a little. Your Santana is simply.. muted. You're turning the volume up louder to try to get the fidelity and.. it's starting to just make your ears bleed. A sense of loss starts to set it. You return to the Internet. Searching searching.. The brave souls who seemed to have reached Nirvana now seem like hopeless newbies. Perhaps the man that said these needed to be amped was simply right... you feel like a total shmo.

But you don't give up.

Eventually you start noticing the padded part of your cans. The 60's have this bowl shaped thing that exposes everything directly... Your new MS-1's have foam all across the earpiece... You search for pads... And find out just how deep the rabbit hole goes.

Now you have 15 browser tabs open. The MS-1 shipped with... 'comfies'?!?! You're outraged. What self respecting Grado owner would possibly substitute sounds for comfort? You're on the warpath. The 60's earpads are bowls.. You find reviews of headphone pads. They claim that Grado's are more effected by pad choice than any other headphone alive. You switch the bowls into the MS-1... and a small tear comes to your eye.


And you think you're done.

But you're not.

Because now you need to buy another set of pads.

So you just add some bowls to the shopping cart... when you see that there are 'flats' for a whopping $30. $15 more for even less FOAM! You head back to the reviews. Flats are quite simply the gold standard. Bowls are simple not 'it.'

For some people.

You learn that a flat alternative is yellow pads from another manufacturer that you'll need to dye, punch holes in and slice yourself. You learn there's a cottage industry in doing these and that their results are even BETTER than the flats, and if those were such a substantial improvements from the bowls...

You look down at your bowls in disgust. To think that there was a time you enjoyed their sound! You read about reversing them and start listening with them on backwards marveling at your previous stupidity.. You look like an idiot with his headphones on backwards. You go to order the modded pads...

and their store is closed forever...

You ebay. You google. You answers.com. There are no answers for questions like these.