sábado, 29 de diciembre de 2007

Starting up

This is the first time I'm going to blog to recommend something. I haven't done it before because I find it quite boring. There are lots of blogs (and sites) that do it already. Even for technical stuff.

But I've found this post enlightening. I tried some time ago to build my own company and I failed. Miserably! Really. The worst of all is I didn't take the time, back in the day, to understand what didn't work or what could be improved.

Read 36 Startup Tips: From Software Engineering to PR and More! first and then you'll be able to understand what did I wrong:
  • Code! Code! Code! Of course...I'm a good Java architect (and programmer) but it's difficult to sell just by saying it loud. People have heard it thousands of times from thousands of different people. Prove it!! Designers have a portfolio. I should have had one as well
  • Size! Do not try to embrace so many different areas. It's not credible. A small sized company has to focus if it tries to compete. A lot!
  • And finally..PR. If you're good technically concentrate in that tasks because you probably aren't good at networking. And even if you are, you probably won't have the time to do both things in parallel
The bright side is you don't need to accomplish every point in that list to be mildly successful. After more than two and a half years Internna is still open for business (without loosing a cent). I can't commit my full time to it (as I would like) but there it is if the opportunity arises!

Good luck in your endeavors!

domingo, 23 de diciembre de 2007

Sharing projects with Ant+Ivy+Jetty+Hsqldb

Sometimes (well, many times, really) you are in the need to transport a project (or application) from one machine to another. SUN proudly invented the "Write once, Run everywhere" for Java back in the day but let me share a secret with you, it's far from real. Yes, Java itself is cross-platform but there are a lots of other things involved when talking about portability, just a small list could easily include: JVM versions, JDK/JRE dependencies, different environments (OS, net, paths), third party libraries or products, etc.

If it's an already built application (binary distribution), things become easier. At least, half of the process has been done! In addition, there are some tools available (like IzPack) that help you in the labor. These tools are focused on client installations so I'll skip them today. I would prefer to talk about sharing code between developers.

Since the advent of Maven repositories Java has had a decent way to manage dependencies. Unfortunately, Maven has not come without problems and some people (me included) have opted to skip it entirely (if at all possible, of course). The good news is Ant can do everything Maven does (well, I'm not really sure if Ant can create IDE projects for you..not that Maven shines there anyway!). In our case, Ivy is the sanctioned Ant extension to deal with Maven repositories. One of the nicest features it packs is the automatic installation step (if desired), so if the target machine has Ant already installed Ivy can be used without problems. Let's look at the code:

<project xmlns:ivy="antlib:org.apache.ivy.ant" ...>
   ...
   <target name="install-ivy">
      <get src="http://...ivy.jar" dest="lib/ivy.jar" usetimestamp="true" />
      <path id="ivy.lib.path">
         fileset dir="lib" includes="*.jar"/>
      </path>
      <taskdef
         resource="org/apache/ivy/ant/antlib.xml"
         uri="antlib:org.apache.ivy.ant"
         classpathref="ivy.lib.path"/>
   </target>
   ...
</project>

The code is very simple, it just needs a namespace declaration in the project tag and adding a new target. We are now in disposition to use Maven repositories transparently. Ivy has a proprietary syntax but in the end it's a direct port of Maven's. Use an ivy.xml file with lines like:

<dependency org="log4j" name="log4j" rev="latest.integration"/>

And in the build.xml file include a new target:

<target name="resolve-dependencies">
   <ivy:retrieve />
</target>

Compile as usual and you'll notice that Ivy downloads all the needed JARs recursively. Nice! We have just scratched Ivy possibilities here but it's a good introduction to its potential (try to understand configurations next).

At this point you may have created a web application. This brings a new problem: deployment. How can you ensure that the user will have an AS installed? Or a DB? And what about a DB schema? All this kind of problems can be solved embedding a server (or various) with your code. The best of all is you don't even have to include them, Ant+Ivy will download, configure and start them alone. You have several choices but the most common by far when talking about embedded servers are Jetty and HSQLDB.

Jetty is a powerful yet lightweight servlet container with JPA capabilities (that should be enough 90% of the times). It includes ant tasks to start up and deploy a web application. In ivy.xml add

<dependency org="org.mortbay.jetty" name="jetty-util" rev="6.1.6"/>
<dependency org="org.mortbay.jetty" name="jetty-plus" rev="6.1.6"/>
<dependency org="org.mortbay.jetty" name="jetty-naming" rev="6.1.6"/>
<dependency org="org.mortbay.jetty" name="jetty-ant" rev="6.1.6"/>
<dependency org="org.mortbay.jetty" name="servlet-api-2.5" rev="6.1.6"/>
<dependency org="org.mortbay.jetty" name="jsp-api-2.1" rev="6.1.6"/>
<dependency org="org.mortbay.jetty" name="jsp-2.1" rev="6.1.6"/>
<dependency org="org.eclipse.jdt" name="core" rev="3.1.1"/>
<dependency org="org.mortbay.jetty" name="jetty" rev="6.1.6"/>

And in your build file:

<target name="run" depends="package">
   <taskdef
      classpathref="run.path.id"
      resource="tasks.properties"
      loaderref="jetty.loader" />
   <jetty tempDirectory="${temp.dir}">
      <webApp name="..." warfile="${dist}/..." contextpath="/..." />
   </jetty>
</target>

This will halt your build, boot up Jetty and deploy the specified WAR file. Most of the work is done, the final step is starting and populating the DB. When using JPA with HSQLDB the database will be automatically loaded on startup (just include the JAR in the path). JPA also includes an option to drop and create the schema. That's without doubt the easiest way to bootstrap the DB. An example with hibernate:

<persistence-unit name="..." transaction-type="RESOURCE_LOCAL">
   <provider>org.hibernate.ejb.HibernatePersistence</provider>
   <class>...</class>
   <exclude-unlisted-classes>true</exclude-unlisted-classes>
   <properties>
      <property name="hibernate.connection.username" value="sa"/>
      <property name="hibernate.connection.password" value=""/>
      <property name="hibernate.connection.driver_class"
         value="org.hsqldb.jdbcDriver"/>
      <property name="hibernate.connection.url"
         value="jdbc:hsqldb:mem:test;shutdown=true"/>
      <property name="hibernate.connection.shutdown" value="true"/>
      <property name="hibernate.dialect"
         value="org.hibernate.dialect.HSQLDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
   </properties>
</persistence-unit>

Finally, you may need to populate it with data. I usually use a BootstrapListener (a ServletContextListener). You can instantiate objects and persist them using JPA or include a SQL file and load it directly, it depends on the amount of data really.

By now, and if you've done everything correctly, you have a professional build and execution platform in no more than 100 lines! As an additional security measure you may pack Ant if you aren't sure that the client will have it installed. Oh! By the way, as a much as I dislike Maven...the same results are achievable using it (sigh!).

jueves, 6 de diciembre de 2007

Why Open Source just success in projects

We are polishing our application. Just finishing the lastest touches before we proudly put it in production. It's been over five months of development and we are pretty happy to conclude this phase. It's time now to, akin to the Agile retrospective, sit down and examine the time we have spent. We have suffered (and solved) lots of problems in the way but I would like to talk today about those related with OSS, how did we solve them and what we learned.

First of all, let's review the list of OSS libraries and tools we use:
  • The Spring framework: The main tool. IoC, AOP, MVC, TX, ORM...invaluable. It improves the quality of the solution just by itself.
  • Hibernate: As our JPA provider. We also use the extensions it provides (HQL, annotations, cache)
  • DWR: AJAX made easy, really.
  • dojo: As the widget library. The only comparable JS library in our minds would be Ext JS but in the end we had to choose one. jQuery has haunted us during development. I wish we could have managed to add it as well.
  • Netbeans / Glassfish: Best environment for Java5
  • Honorable mentions: Apache (Ant and Jakarta), JasperReports, Alfresco (we couldn't include it in the end), CruiseControl and Trac
Astonishing, the list of commercial software is pretty narrow: JAVA (should I mention it here by now?), Weblogic and Oracle.

We have tried (and accomplished) to work with the latest and greatest release of each tool. This has lead to just one problem, dojo. When we started coding the available release was 0.42. Sometime during development version 1.0 was announced and API incompatibilities were revealed. In the time, we decided to stick with 0.4x but when 1.0 was launched the number of improvements was so huge that we changed our minds and proceeded to migrate everything. Unfortunately, this meant changing nearly every JSP in the application. The lesson we learned was to wrap widgets inside tag files so further migrations just revolve changing a central repository (but please, really, do not give us more API incompatible releases!).

Working with the latest available technology means finding bugs and situations no one has faced before. We have reported bugs to Spring, Hibernate and DWR. Our experience in this cases has been disparate:
  • The Spring team takes notice and works to solve the issue lightning fast (see SPR-3821, SPR-3530 for example). Sometimes they won't consider a proposal but at least they read them all and comment on them if further explanations are needed(see SPR-3644).
  • Things in DWR are solved using the users mailing list (though there's a JIRA installation as well). The community support is your friend here. Joe Walker (or other commiters) cannot work in a bug immediately (it's understandable) and there's no organization like SpringSource backing the project. Your contributions are welcome and if you find a bug you are encouraged to work to resolve it and return the patch to the community.
  • Hibernate is another beast entirely. You can submit a bug and hope it gets noticed. The project is very mature and rules are enforced. Here, having access to the source code is a bless. Usually your best bet is to debug your problem and patch it, recompile and test. Once you have a working solution file the bug along with the code (preferably with a regression test) and give them time to test it and include it in trunk.
  • Finally, Netbeans. Again we filed some bugs here :) (see issue 91803 for example). It took some time to get fixed but it was promptly assigned so you know someone was in charge of solving it. I was pretty happy in the end
As you see many different types of situations, all of them valid. In comparison, I will mention that we have filed a bug in WLS10 and another in Oracle11. I work for a pretty big company in Spain (more than 20,000 people) with corporate agreements with both BEA and Oracle. You would expect some kind of positive response from them. Take a chair while waiting...And that is if you are lucky (sigh) The worst of it is..there's nothing you can do!