Archive for the ‘work’ Category

Tools that should be in your software development toolbox

Wednesday, December 2nd, 2009


Eliciting Requirements (Business Analyst, Designer)

Visualization and wireframing tools are the bees knees.  My favorite is http://www.wireframesketcher.com that integrates with eclipse, can be managed with change control (SVN).   I was a proponent of doing this on a piece of paper (but wireframesketcher makes for even LESS throwaway) while allowing a document

Capturing Requirements (Business Analyst)

I used to try to capture things in UML — I still think class diagrams and sequence diagrams are great, but there weren’t good tools for it.  http://www.objectaid.com is good for UML in Eclipse (also Green).  There might be better paid for tools, but I like these two.

Also for sequence diagrams, I really think  http://www.websequencediagrams.com/ has the right approach.  Plus styling to make it look like you wrote it on a napkin.  I found that too often there were edge cases that could be captured in UML if you knew the right syntax, but even if you did, the person READING the UML had to know it as well.  This is where I found comments (little notes) to be a better mechanism for the explanation.  There is another tool I found:  http://sdedit.sourceforge.net/example , but have not used which supports multithreading, etc.

I’ll update this post with other tools that I think are useful.  Like a carpenter, I have a bunch of tools in my toolbox.  Tools make the difference.  I’ll include tools for source control, build, etc.

Installing Springsource Tool Suite (STS) in Eclipse 3.5 (Galileo)

Saturday, October 17th, 2009


I’m really interested in seeing the Grails and Groovy work that has been including in STS 2.2.1. I followed the instructions here: http://blog.springsource.com/2009/06/24/installing-sts-into-eclipse-35/, but unfortunately I got stuck at step 6. It kept asking for a mylyn feature group 3.3.0I20091013,3.4.0.

Ugh!

No doubt installing it now has caused the instructions to go out of date.  Fortunately at http://www.eclipse.org/mylyn/downloads/ there were a bunch of weekly updates.  After adding the weekly update sites to eclipse:

http://download.eclipse.org/tools/mylyn/update/weekly/e3.4  and http://download.eclipse.org/tools/mylyn/update/weekly/extras

This enabled me to install STS.

UPDATE

If you want to install STS on Eclipse.  Visit this page:  http://www.springsource.com/products/eclipse-downloads.  It will give you a current version of Eclipse 3.5.1.  Run Update on it, then install the STS link update.

WireframeSketcher 1.5 now with text styling EVERYWHERE

Thursday, August 20th, 2009


I have to hand it to Peter, the update to WireframeSketcher 1.5 is very cool.  I really like the ability to add icons inside tables, checkboxes inside lists, etc. to make the mockups even closer to the real thing that we create with RIA.  1.5 now lets you add Links, Icons, Bold, Italics, Underline, Strikeout.

The code-complete on the icons really rocks.  Well Done, Peter!

If you use Eclipse, and you do development and you’re not using Mockups, you’re missing out.  Try it out and then go buy a license.

Locking Column Sizes in Flex

Tuesday, July 21st, 2009


This post from Joe, really saved the day.  The gist of it is that you need to specify horizontalScrollPolicy = “on” to have the columns locked to a specific size when you’re resizing a grid and hiding and displaying various columns.

WireframeSketcher Rocks!

Thursday, July 2nd, 2009


I’m working on a project with some other team members and I have to say that WireframeSketcher really rocks! I’ve long been a proponent of drawing up the screens on a piece of paper and used drawing tools to draw my mockups. A friend of mine turned me on to balsamiq mockups. The sketches it produces are nice and look pencil drawn and all (I like the look of them — very fun), but it had a major problem:

  • it wasn’t fast enough. running balsamiq as an air application was very slow — moving pictures around on my screen was painful.

wireframesketcher has

  • it’s integrated into my IDE (Eclipse) — so I can bring it up fast.  I have access to SVN for sharing.  Very nice
  • I really like the code complete (ctrl+space).  It brings up a fast list of components that I can scroll through and then use code complete to see what I want to include.

Some features I’d like to see:

  • I like mockup’s resizing function.  I select the items, I grab the edge of the screen and drag and everything or shrinks relatively in size.  In wireframesketcher, it actually shrinks the individual elements, too.  I wish it didn’t do this.
  • Custom components that we can include in the list.  If nothing but pictures.  It would be great to be able to add our own composite xml components to the mix.
  • Android and iPhone components (it would be addressed if we could do custom compenents).  Maybe grab some of the pictures from:  yahoo

Btw, wireframesketcher is authored by Peter Severin.  I wonder if this is the same guy as the JasperAssistant guy?   I think it is based on this link.  Oh well, I won’t hold it against Peter.  I liked JasperAssistant for a while (we bought several licenses), but it didn’t update features as fast as I’d like.  wireframesketcher seems to be moving right along.

Google I/O 2009

Thursday, May 28th, 2009


Here’s a brief update of Google I/O.  Lots of good content at the conference.

Day 1

  • Keynote – HTML 5 (Canvas, GEO Location, Webworkers and two others I can’t think of).  Support or planned support on all browsers (Firefox, Chrome, Safari, Opera)  except Internet Explorer.  I remembered the two other things — how could I forget:  Video and Threading! App-Cache.
  • Android Developer Challenge #2 announced.  Only 1.9 Million allocated (they previously had $5M bucks).  But everyone at the conference got a free Android Phone (HTC Dream).   Now I don’t have to replace my blackberry right away.  It’s really sweet!.
  • Mobicodes (QR Codes) are hot at the conference — scanned with the camera and capable of holding 4K of data.  Used on the badges and used on the Scavenger Hunt.  Wish I realized that the codes at the session feedback were included — because they were 20 points each :( .
  • Hooked up with the Android dev guys to talk to them about writing an app for Android  (now that I have a kick ass phone).
  • After putting our lives at risk trying to get to Tommy’s Joynt, we decided to grab some Italian food closer to the hotel.  Tommy’s Joynt is probably a lunch visit (during the daytime).
  • All the codenames for Android are bakery products:  Cupcake, Donut, Eclair.  I hope they serve up some Ho-Hos.  Mmmm.

Day 2

  • The Lego Guy – incorporating developers into process — first devs hacked the Mindstorm and Lego freaked out — then invited them in to participate in development.  Ultrasonic sensor was the result.
  • Keynote – The Google Wave – Google’s interpretation of a server/network based mechanism for collaboration.    Solves some of mails problems (like trying to figure out where you are in a thread and bringing people into the context).  Realtime editing by multiple users.  Uses OpenSocial for gadgets to integrate other sites (e.g. blogs).  Incorporates Wiki like functionality,
  • Questions:  how will it integrate with Mail?  It appears that will be up to the developers to figure out.
  • Android Game Development session was very crowded … probably because the Wave Programming session was following it up.  Canvas is slow for drawing sprites.  OpenGL draw_texture is the clear winner for drawing sprites.
  • Wave Coding — looks like being a google apps reseller would be great if you get paid for Wave too.  Robots are hosted on AppEngine.

JasperAssistant supporting a newer version of JFree Charting

Friday, May 15th, 2009


I had a problem where I was coding a Chart Customizer to a newer version of JFree Chart than was in JasperAssistant 3.0.1.

Here’s the JFree chart dependency:

<dependency>

<groupId>jfree</groupId>

<artifactId>jfreechart</artifactId>

<version>1.0.9</version>

</dependency>

 

I ran into this problem when trying to view the report in JasperAssistant:

Specifically:

org.jfree.chart.plot.PiePlot.getSectionPaint(LJava/lang/Comparable;)LJava/awt/Paint;

This error is caused by me writing my code to JFreeChart 1.0.9 when JasperAssistant is still using 1.0.0. I’m sure 1.0.9 supports the api in 1.0.0, but vice versa is not true.

Is there an easy way to update the JFreeChart version used? Can I update it myself?

 

I had tried to update the plugin dependency in eclipse\plugins\com.jasperassistant.designer.core_3.0.1\plugin.xml

and removed:

eclipse\plugins\com.jasperassistant.designer.core_3.0.1\lib\jfreechart-1.0.0.jar

and added:

eclipse\plugins\com.jasperassistant.designer.core_3.0.1\lib\jfreechart-1.0.9.jar

I ended up with:

java.lang.NoClassDefFoundError: org/jfree/chart/plot/PlotOrientation

at net.sf.jasperreports.engine.base.JRBaseChartPlot.<init>(Unknown Source)

at net.sf.jasperreports.charts.base.JRBasePiePlot.<init>(Unknown Source)

at net.sf.jasperreports.charts.design.JRDesignPiePlot.<init>(Unknown Source)

at net.sf.jasperreports.engine.design.JRDesignChart.setChartType(Unknown Source)

at net.sf.jasperreports.engine.design.JRDesignChart.<init>(Unknown Source)

at net.sf.jasperreports.charts.xml.JRPieChartFactory.createObject(Unknown Source)

at org.apache.commons.digester.FactoryCreateRule.begin(FactoryCreateRule.java:389)

at org.apache.commons.digester.Digester.startElement(Digester.java:1361)

at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:533)

at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:798)

at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:878)

at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1693)

at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:368)

at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:834)

at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)

at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:148)

at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1242)

at org.apache.commons.digester.Digester.parse(Digester.java:1647)

at net.sf.jasperreports.engine.xml.JRXmlLoader.loadXML(Unknown Source)

at com.jasperassistant.designer.pJ.a(SourceFile:39)

at com.jasperassistant.designer.fF.b(SourceFile:105)

at com.jasperassistant.designer.fF.e(SourceFile:89)

at com.jasperassistant.designer.fF.c(SourceFile:82)

at com.jasperassistant.designer.editors.ReportEditor.setInput(SourceFile:451)

at com.jasperassistant.designer.ik.init(SourceFile:217)

at com.jasperassistant.designer.editors.ReportEditor.init(SourceFile:557)

at org.eclipse.ui.internal.EditorManager.createSite(EditorManager.java:799)

at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:643)

at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:428)

at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:594)

at org.eclipse.ui.internal.PartPane.requestActivation(PartPane.java:262)

at org.eclipse.ui.internal.EditorPane.requestActivation(EditorPane.java:98)

at org.eclipse.ui.internal.presentations.PresentablePart.setFocus(PresentablePart.java:192)

at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation$1.handleEvent(TabbedStackPresentation.java:94)

at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:267)

at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:272)

at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.handleMouseDown(AbstractTabFolder.java:342)

at org.eclipse.ui.internal.presentations.util.AbstractTabFolder$3.mouseDown(AbstractTabFolder.java:79)

at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:179)

at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)

at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)

at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3823)

at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3422)

at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2382)

at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2346)

at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2198)

at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:493)

at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288)

at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:488)

at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)

at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113)

at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:193)

at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)

at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)

at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386)

at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:585)

at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:549)

at org.eclipse.equinox.launcher.Main.basicRun(Main.java:504)

at org.eclipse.equinox.launcher.Main.run(Main.java:1236)

 

To get around this problem I just renamed:

eclipse\plugins\com.jasperassistant.designer.core_3.0.1\lib\jfreechart-1.0.9.jar

to:

eclipse\plugins\com.jasperassistant.designer.core_3.0.1\lib\jfreechart-1.0.0.jar

and left the plugin.xml the way it was originally.

It works.  Woot

SpringSource’s Roo

Sunday, May 10th, 2009


Roo looks like it aims to eliminate/reduce some of the complexity with the setup of an Java application. I tried my hand at the vote and petclinic application by following the instruction in the readme. I ran into a problem with deploying the app to my local tomcat 6 instance. Roo uses the Hibernate EntityManager, but for some reason, I’m getting these errors.  I would have thought that this example would have worked right out of the chute.

I found that from http://forum.springsource.org/forumdisplay.php?f=67 I could run mvn package and get it to run correctly under Tomcat.  It appears to be a problem with the AspectJWeaving.

 

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [applicationContext.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.springsource.vote.domain.Choice
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:288)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:103)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1238)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1006)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:412)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:383)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:271)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:268)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:170)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:469)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:717)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:376)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:254)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:198)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.springsource.vote.domain.Choice
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1332)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:412)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:383)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:271)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:268)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:170)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:282)
... 32 more
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: com.springsource.vote.domain.Choice
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:671)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:534)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:286)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1121)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1225)
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:159)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:425)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:131)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1363)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1329)
... 41 more
May 10, 2009 9:10:51 PM org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
May 10, 2009 9:10:51 PM org.apache.catalina.core.StandardContext start
SEVERE: Context [/vote] startup failed due to previous errors
Hibernate EntityManager 3.3.2.GA
Processing PersistenceUnitInfo [
name: persistenceUnit
...]

Apps I’ll get for the Android Phone

Saturday, February 21st, 2009


I’ve visited the Android Market and here are some of the apps that I think I’ll have to get for the Android Phone:

  • ringdroid
  • aknotepad
  • mytracks — Google stole my idea :(
  • latitude (with Google Maps)
  • quotepro or stocker — I like to track stocks – google now has google finance on android.
  • droidrecord
  • PhoneAnalyzer
  • GasTrip
  • locale
  • weather
  • I’m looking forward to it and Greg just let me know that the G2 is going to be coming out soon.

Time to Get an Android Phone?

Saturday, February 21st, 2009


As people that know me well know, I like gadgets. I’ve followed the mobile phone scene for a long time — since I bought my first bag phone from Ameritech. Many Palm devices along with a phone and finally I settled on a convergent device — The Hiptop (Sidekick). It was really a great convergent device from a cool startup with great potential.. I recently (11 months ago or so) had to abandon my Sidekick (from Danger). This was before Microsoft ended up buying them.

So without a phone, I purchased an iPhone. I was somewhat an early adopter and unlocked it. I was in the 14 day trial window when Apple was playing with their upgrades and bricking phones. It scared me that I just spent $400 on a phone that might end up being a bookend.

I temporarily got into a month-to-month contract with Cincinnati Bell and got a cheap Nokia device. It really didn’t suit me well and the iPhone 3G was a ways off as was Android. Google did, however, release the Android SDK. (Nov 2007).

I really resisted going with a RIM device but I ended up going with a Blackberry Curve which is a really great device compared to the older Blackberries with the wheel on the side and the weird font. The interface is sweet, the device is light. It has an MP3 player, you can customize your ringtones using MP3s, it plays movies (.3GP MP4 format), the built-in browser is improved with google search from the main screen, and Google has written a bunch of apps for it: Google Sync (Calendar and Contacts), Google Maps (with Latitude). Amazon had a great deal on the curve. I ended up getting $50 back on the rebate.

So now, I have my Curve and I’d really like to get an Android phone with location awareness (GPS, Compass, 3G, and always ON connectivity) and a richer development environment than the Blackberry. My friend Greg and Keefe both got them. It’s time for me to get on the bandwagon.