Library quirk in the new Eclipse, and random framework musings

I’ve been working with Struts 2 recently, and like most frameworks it relies on a set of jar files.  I like to work with Eclipse as my primary IDE.  In that framework, my normal mode of operating is to create a User Library containing the jar files I need and then add it to my Dynamic Web Projects through the Java Build Path configuration.

It seems that the system has changed in Eclipse 3.3, aka Europa.  I’m working with the Web Tools Platform plugin, so at least I have dynamic web project capabilies.  I can also set up a Tomcat server easily.

What’s changed is that now, when I add a User Library to the build path, Eclipse warns me that it won’t be deployed to the server.  The warning is:

“Classpath entry org.eclipse.jdt.USER_LIBRARY/libname will not be exported or published.  Runtime ClassNotFoundExceptions may result.”

Yer darn tootin’ they’ll result.  I suppose this is a feature, not a bug, because I have had situations where the libraries were already added to my server’s classpath so I didn’t want to duplicate them in the war file.  Also, some war files become enormous because of all the libraries used.  (The last time I wrote a simple app that used JPA, Spring, and Hibernate the resulting war file was huge.  And the size of the war file that comes with a trivial Grails application is easily over 10 megs.)  Now Eclipse leaves the libraries out of the war by default.

I’m reminded of when the Collections framework for Java was created, and ArrayList turned out to be exactly like Vector but without the synchronization.  The theory seemed to be that you can always add synchronization later (Collections.synchronizedList(myList)), but that you couldn’t remove it from Vector when you didn’t need it.  This change has the same feel to it — you can always figure out a way to deploy the libraries, but you never had a way to get rid of them short of editing the resulting war file.

That’s not necessarily a good thing for me, though.  I’m always tempted to add libraries to my server’s classpath, partly to keep the size of the individual war files down, and partly because I tend to use the same libraries over and over and I hate packing them into every single application.  All those repeated files feel like a waste.

Still, it’s dangerous not to include the jar files in the web application itself.  Version problems can easily arise, especially because I tend to upgrade to the latest version of a given library whenever I can.  For that reason, I’ve resisted the temptation to, say, put Hibernate and Spring into my server’s lib directory.

So what do I do in Eclipse?  It turns out there are two solutions:

1. Declare the libraries to be module dependencies for the war.  That’s done by going into the project properties, then Properties –> J2EE Module Dependencies –> Select All.  Then Eclipse treats the libraries the same way it would any dependent project.

Eclipse Properties J2EE Module Dependencies

2. The other approach is to go on the file system and copy the jar files directly into the WEB-INF/lib directory of the project, then do a refresh.  Apparently Eclipse is smart enough to then add the jars to the classpath for my source code.

I’m not sure which way I’ll prefer in the future.  Eclipse does have a Navigator view which supports drag-and-drop copying, so that’s easy enough.  Still, I hate to leave the IDE when I’m in the middle of using it.

This is also one of the few situations where using MyEclipse wouldn’t make any difference.  Version 6 truly rocks, but it doesn’t have a predefined library for Struts 2.  Maybe Struts 2 was still too new when MyEclipse 6 was being developed.

As an aside, it should be interesting to see which way the framework wars will turn in 2008.  There’s still a huge installed base of Struts 1.* clients out there, but many of them are looking at other options.  The other page-based framework I’ve used is Spring Web MVC, which has its own learning curve.

JSF is part of the Java EE spec, but if you’re used to a page-based framework the switch to a component-based framework is not trivial.  Tapestry is still out there, and it has a few very fervent advocates, but I haven’t heard much growth in it.  I also haven’t gotten any calls about it in quite some time.  Seam is growing, too, but I expect that’ll be popular among the same crowd that likes JSF, since it’s based on JSF anyway.   Of course, there’s also Google Web Toolkit if you want to build a desktop application inside a browser.

Struts 2 is very interesting, and has the modern feel of interceptors and filters and POJOs (oh my!).  It has Spring-like dependency injection, though I think they use Guice by default rather than Spring, not that it really matters.  I never learned WebWork before the merger, so the learning curve has been pretty substantial for me.  Personally I feel that Struts 2 is so fundamentally different than Struts 1 that I’m surprised they kept the Struts name.  That marketing decision may make all the difference, however.

I’ll keep an eye on all of them, of course, but for my own applications, I like Grails. 😉

(Yes, I know that’s the same as saying Spring Web MVC.  We’ll see how that plays out, too.)

Go to see Grails, learn about Hibernate

Today I finally got to see the two Grails presentations by Jason Rudolph at No Fluff, Just Stuff. It’s not really an exaggeration to say I decided to attend the conference largely because I knew he’d be there. I like the NFJS conferences, but since I’m a one-person company, the “budget” for the conference comes right out of my pocket. I have to really want to go. Not only that, but for the past two years I’ve attended during the March session. It feels like a bit of a luxury to go twice in a given year, especially when many of the presentations in the fall overlap those from the spring.

But Jason was going to be there, and not only is he a real expert, he’s also a big part of the reason I’m involved with Groovy and Grails in the first place. I blogged about it a long time ago, but about a year ago I happened to be teaching a Spring class in Philadelphia. I happened to notice that the local Spring users group was hosting Jason, talking about this Grails thing I’d only heard about.

At the time I’d gone through my burst of enthusiasm and subsequent disappointment about Ruby on Rails. By that summer I’d come to the conclusion that Ruby was just too much and too different for me to make for a practical transition, not to mention the fact that I knew I wasn’t going to be able to follow their conventions and that was going to be a problem. Still, spending all that time digging into both Ruby and Rails taught me a ton. That was the first I’d heard about closures, for example. I also finally saw the power of a dynamic language, which ironically made me appreciate JavaScript for the first time, just in time for the Ajax revolution.

I guess you could say I was the perfect audience for Jason’s presentation. The fact that I could see all the Rails-like productivity gains and still be able to leverage all my Java experience was worth diamonds to me.

Today, he gave that introductory talk again, and followed up with a more advanced discussion of domain modeling with GORM, Grail’s Object-Relational Mapping framework. The introductory part was a nice refresher, but I was familiar with most of that material.

The advanced talk was very interesting, however. I needed to see how to work with an existing database schema, because that’s real life (despite what the Rails people seem to think). I knew in principle that since Grails just uses Hibernate under the hood, you could just fall back to Hibernate mappings to do whatever you needed. I’d never actually seen that in action, though.

But here was the surprising part. At one point Jason asked the audience if anyone had used the Hibernate Tools project to reverse engineer a database schema. I said I had, and I thought I had, but apparently I really missed the boat on that one.

I’ve tried the reverse engineering process inside an IDE. I originally tried it with MyEclipse, then I tried JBoss IDE. In both cases I felt like the wizard generated as much work for me as just writing the mapping files myself. I never seemed to get the hang of them. I hated seeing Java classes show up that had attributes like “userses” due to some naming convention. Since MyEclipse had content assist on the XML mapping files, it felt easier for me to just write the raw XML.

What Jason showed, however, was an intermediate step that hadn’t occurred to me. He didn’t go from the database schema all the way to the Java classes, which the wizards wanted me to do. Instead he used an Ant build to generate just the Hibernate mapping files and then edited them to suit his domain classes.

Imagine the sound of a light finally dawning. Here’s clue: Star Trek: the Original Series, first season episode “What Are Little Girls Made Of?”, quote by Ruk, the android left by the Old Ones:

“THAT was the equation! Existence! Survival … must … outweigh programming!”

In other words, I get it now.

I tried it with one of my own database schemas this evening, and of course it worked like a charm. I certainly don’t mind editing the resulting XML mapping files, and, even better, I can recommend the practice for clients who have dozens or hundreds of tables.

Thanks, Jason. 🙂 Now I can get back to really learning the framework.

Some No Fluff, Just Stuff observations

I’ve finished two of the three days of the current No Fluff, Just Stuff conference, officially known as the New England Software Symposium.  I’ve got a fair amount to process now, but here are some random observations, in no particular order:

  • If the NFJS people have any say in it, Groovy and Grails are definitely in the future.  Not everyone agrees, of course, but in general the presenters really enjoy it.  Whether that counts for anything or not remains to be seen.
  • Web frameworks seem to fall into two categories:
    • Page-based frameworks, like Struts and Spring MVC.  Grails falls into this category, too, since it is really just Spring MVC under the hood anyway.
    • Component-based frameworks, like JSF, Seam (which uses JSF), and GWT (Google Web Toolkit).
    • Which category you prefer seems to be a matter of personal preference, but there are no lack of strong opinions on the subject.
  • Ajax support is just assumed everywhere.  There are no “beginner” talks on Ajax anymore, though some frameworks that build in Ajax support went over basic Ajax just to show how much easier they are.
  • David Geary seems to have followed an interesting, winding path from Struts, to JSF, to “Ajaxian Faces”, and ultimately to GWT.  He really, really likes GWT.  Frankly, as component-based frameworks go, that one looks the most fun anyway.
  • Some of the attendees ask very hard questions, and the presenters, who uniformly welcome those questions, have a hard time managing their time allotment as a consequence.
  • I’ll try to be delicate how I say this, but some of the presenters occasionally forget that they don’t live in the real world.  I’ve heard a lot of mumbling from attendees whose jobs or companies don’t easily allow them to move to whatever “the latest and greatest” is.  Sometimes I think the presenters need to be a little less quick to condemn older technologies that are still in very common usage and still get the job done.  I think I read recently that still only about 35% of companies have even moved to Java 5.  Any new framework whose major selling point is new annotations is going to be out of luck there.
  • As for me, I don’t have those sorts of limitations, but I do have to be careful not to get too far ahead of my own market.  My sense of that is:
    • I’m sure the demand for JSF is going to be steady or even grow.
    • GWT looks like an interesting niche, though I’m not sure how active that market will be.
    • Groovy is likely to break through in 2008.  I’m virtually certain I’ll be teaching Groovy classes next year.
    • Grails won’t break through until there’s a stable set of documentation and examples for it.  That won’t happen until the framework goes to 1.0, at least, which they say will be next month but I’ll believe it when I see it.  I’ll be very surprised if I get a call about a Grails class until at least next summer.
    • I still think JPA is going to be massively successful, as soon as all the application server vendors support it.  JBoss 5 is right around the corner.  WebLogic is just about ready.  I think Oracle already supports it, as does (of course), Glassfish.  Where the heck is IBM???  Could they be that clueless?
  • I think I should take a quick look at DWRCastor, too, probably.
  • Spring has become so pervasive that it’s almost conspicuous by its absence.  There have been a couple of presentations on Spring, but everybody uses it or uses something very much like it.
  • I think we’re hitting the “trough of disillusionment” for Ruby on Rails.  I’ve heard at least three frameworks sold as “Rails killers”.
  • David Geary is right, though.  Rails is the best thing ever to happen to Java.  It got framework developers to focus on simplicity, conventions, and ease of use.  Now that they’re getting that, the advantages to using Rails are starting to fade away.

Still, I’ve had a good time.  I’m very much looking forward to seeing Jason Rudolph talk about Grails again, especially because I assume he’ll have updated his code to work with the latest version.  At least I hope so.

Today is a good day, though, since by definition any day the Red Sox win and the Yankees lose is a good day.  Josh Becket won his 19th game as the Sox beat the Yankees 10 – 1.  That’s more like it.  Now if they can destroy Clemens tomorrow life will be very good.

Where have I been (my Google Maps Mashup)?

The user interface leaves a lot to be desired, but my Google Maps mashup went live today. If you want to see where I’ve taught courses over the past three years, you can go here and see.

All of the data is stored in a very simple database consisting of three tables: Courses, Locations, and Clients. Each of those tables has a single integer primary key and columns to represent the details. There is a many-to-one relationship between clients and courses and between locations and courses, too

I didn’t write any SQL to populate the tables or access the data. Instead, I used the Java 5 annotations and the Java Persistence API to annotate my entities.

Here’s the Client class:


@Entity
@Table(name="clients")
public class Client {
  @GeneratedValue
  @Id private int id;
  private String name;

  @OneToMany(mappedBy="client")
  private Set<Course> courses = new HashSet<Course>();

  // ... all the required gets and sets ...
}

and the Location:


@Entity
@Table(name="locations")
public class Location {
  @Id
  @GeneratedValue
  private int id;

  private String city;
  private String state;
  private double latitude;
  private double longitude;

  @OneToMany(mappedBy="location")
  private Set<Course> courses = new HashSet<Course>();

  // ... gets and sets, toString, equals, etc. ...
}

and finally the Courseclass itself:


@Entity
@Table(name="courses")
public class Course {
  @GeneratedValue
  @Id private int id;
  private String title;

  @Column(name="start_date")
  @Temporal(TemporalType.DATE)
  private Date startDate;

  @Column(name="end_date")
  @Temporal(TemporalType.DATE)
  private Date endDate;

  @ManyToOne(cascade=CascadeType.PERSIST,fetch=FetchType.EAGER)
  private Client client;

  @ManyToOne(cascade=CascadeType.PERSIST,fetch=FetchType.EAGER)
  private Location location;

  // ... gets and sets, etc. ...
}

Then I configured my persistence.xml file (required for JPA) to use Hibernate as my persistence provider.


<?xml version="1.0" encoding="UTF-8"?>
  <persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

  <persistence-unit name="TrainingPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
      <property name="hibernate.connection.driver_class" 
        value="com.mysql.jdbc.Driver"/>
      <property name="hibernate.connection.url" 
        value="jdbc:mysql://localhost/training"/>
      <property name="hibernate.connection.username" value="..."/>
      <property name="hibernate.connection.password" value="..."/>
      <property name="hibernate.show_sql" value="false"/>
    </properties>
  </persistence-unit>
</persistence>

No doubt I’ll eventually modify that to use a JNDI lookup for a datasource, but this was an easy way to get started.

Access to the entities requires an EntityManager, which in turn requires an EntityManagerFactory. I wrote a CourseDAO interface and a JpaCourseDAO implementation class to act as the persistence layer. The interface is simple:


public interface CourseDAO {
  void saveCourse(Course course);
  List<Course> getAllCourses();
  List<Course> getCoursesByClient(String clientName);
  List<Course> getCoursesByLocation(String city, String state);
  List<Course> getCoursesByYear(int year);

  List<Client> getAllClients();
  Client getClientByName(String name);
  void saveClient(Client client);

  List<Location> getAllLocations();
  Location getLocationByCityAndState(String city, String state);
  void saveLocation(Location loc);
}

The implementation class, JpaCourseDAO, has an attribute of type EntityManager, along with a set method that is used by Spring 2.0. Here’s that class:


@Repository
public class JpaCourseDAO implements CourseDAO {

  private EntityManager em;

  @PersistenceContext
  public void setEntityManager(EntityManager em) {
    this.em = em;
  }

  public List<Course> getAllCourses() {
    return em.createQuery("select c from Course c").getResultList();
  }

  public List<Course> getCoursesByClient(String clientName) {
    return em.createQuery(
      "select c from Course c where c.client.name=?1")
        .setParameter(1, clientName)
        .getResultList();
  }

  public List<Course> getCoursesByLocation(String city, String state) {
    return em.createQuery(
      "select c from Course c where c.location.city=?1 and c.location.state=?2")
        .setParameter(1, city)
        .setParameter(2, state)
        .getResultList();
  }

  public List<Course> getCoursesByYear(int year) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.MONTH,Calendar.JANUARY);
    cal.set(Calendar.DAY_OF_MONTH, 1);
    cal.set(Calendar.YEAR, year);
    Date jan1 = cal.getTime();

    cal.set(Calendar.MONTH, Calendar.DECEMBER);
    cal.set(Calendar.DAY_OF_MONTH, 31);
    Date dec31 = cal.getTime();
    return em.createQuery(
      "select c from Course c where c.startDate between ?1 and ?2")
        .setParameter(1, jan1, TemporalType.DATE)
        .setParameter(2, dec31, TemporalType.DATE)
        .getResultList();
  }

  public void saveCourse(Course course) {
    em.persist(course);
  }

  public List<Client> getAllClients() {
    return em.createQuery("select c from Client c").getResultList();
  }

  public Client getClientByName(String name) {
    List<Client> matches = em.createQuery(
      "select c from Client c where c.name=?1")
        .setParameter(1, name)
        .getResultList();
    return matches.size() > 0 ? matches.get(0) : null;
  }

  public void saveClient(Client client) {
    em.persist(client);
  }

  public List<Location> getAllLocations() {
    return em.createQuery("select loc from Location loc").getResultList();
  }

  public Location getLocationByCityAndState(String city, String state) {
    List<Location> matches = em.createQuery(
      "select loc from Location loc where loc.city=?1 and loc.state=?2")
        .setParameter(1, city)
        .setParameter(2, state)
        .getResultList();
    return matches.size() > 0 ? matches.get(0) : null;
  }

  public void saveLocation(Location loc) {
    em.persist(loc);
  }
}

Most of it is very straightforward JPA, but I did have to look up how to deal with the dates and times. Java has always had a dicey relationship with temporal data, but at least this works.

As recommended, the DAO class doesn’t have anything in it about transactions. Instead, I have an interface called CourseService and a class called CourseServiceImpl that sit in front of the DAO:


public interface CourseService {
  void addCourse(Course course);
  List<Course> getCourses();
  List<Course> getCoursesByYear(int year);
  List<Course> getCoursesByClient(String clientName);
  List<Client> getClients();
  List<Location> getLocations();
}

and


@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class CourseServiceImpl implements CourseService {

  private CourseDAO dao;

  public void setCourseDAO(CourseDAO dao) {
    this.dao = dao;
  }

  @Transactional(propagation = Propagation.REQUIRED)
  public void addCourse(Course course) {
    Client client = course.getClient();
    Location loc = course.getLocation();

    Client existingClient =
      dao.getClientByName(client.getName());
    if (existingClient != null) {
      existingClient.getCourses().add(course);
      course.setClient(existingClient);
    } else {
      client.getCourses().add(course);
      dao.saveClient(client);
    }

    Location existingLoc =
      dao.getLocationByCityAndState(loc.getCity(), loc.getState());
    if (existingLoc != null) {
      existingLoc.getCourses().add(course);
      course.setLocation(existingLoc);
    } else {
      loc.getCourses().add(course);
      dao.saveLocation(loc);
    }

    dao.saveCourse(course);
  }

  public List<Course> getCourses() {
    return dao.getAllCourses();
  }

  public List<Course> getCoursesByClient(String clientName) {
    return dao.getCoursesByClient(clientName);
  }

  public List<Course> getCoursesByYear(int year) {
    return dao.getCoursesByYear(year);
  }

  public List<Client> getClients() {
    return dao.getAllClients();
  }

  public List<Location> getLocations() {
    return dao.getAllLocations();
  }
}

Again, the idea is that the service has an attribute of type CourseDAO, which is injected by Spring. By using Spring’s transactional annotations, I was able to make all the read methods use the “supports” type, while leaving room for a “required” transaction on the addCourse method.

To fit all the pieces together, here’s the Spring configuration file, which I called applicationContext.xml:


<?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
    xmlns:tx="http://www.springframework.org/schema/tx">

  <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
      <property name="persistenceUnitName" value="TrainingPU" />
  </bean>

  <bean id="transactionManager"
    class="org.springframework.orm.jpa.JpaTransactionManager">
      <property name="entityManagerFactory" ref="entityManagerFactory" />
  </bean>

  <bean id="courseDao" class="com.kousenit.dao.JpaCourseDAO" />

  <bean id="courseService"
    class="com.kousenit.service.CourseServiceImpl">
      <property name="courseDAO" ref="courseDao" />
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager" />

  <bean
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"           
  />

  <bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>

Craig Walls might find a lot of that file familiar, seeing how I adapted it directly from the examples in his most excellent Spring in Action book.

Actually, now that I mention it, Mr. Walls will probably find the whole set-up pretty familiar. My whole persistence layer is based on what I learned from his book. 🙂

To populate the tables, I used the persistence layer as a regular Java SE application rather that working with anything web related yet. To populate the locations table, I also needed latitude and longitude information for each city.

Of course, first I needed a list of all the courses and their information. Although what I needed is in my QuickBooks data, that’s not exactly an easy API to work with (even assuming such an API exists and is available). I debated various approaches, but in the end I just entered the data for each course into a spreadsheet and then saved it as CSV (comma-separated values) file. I know Groovy can access spreadsheet data directly, but it figured it was just easier to go directly to text.

The “hard” (okay, not so hard, but rather detailed) part, was reading and parsing the text data:


def readData() {
  def df = new SimpleDateFormat('MM/dd/yyyy')
  def dataFile = new File('Course_locations.csv')
  def lines = dataFile.readLines()
  for (line in lines) {
    def elements = line.trim().split(',')
    if (elements.size() == 8 && !elements[0].startsWith("#")) {
      def loc = new Location()
      loc.city = elements[5]
      loc.state = elements[6]
      if (loc.latitude == 0 && loc.longitude == 0) {
        def query = "q=${loc.city},+${loc.state}&output=csv&key=${key}"
        def url_string = base + '?q=' +
          ',+' + URLEncoder.encode(loc.city,"UTF-8") +
          ',+' + loc.state + "&output=csv&key=${key}"
        def results = new URL(url_string).text.split(',')
        loc.latitude = results[-2].toDouble();
        loc.longitude = results[-1].toDouble();
      }

      def client = new Client()
      client.name = elements[3]

      def course = new Course()
      course.title = elements[4]
      course.startDate = df.parse(elements[1])
      course.endDate = df.parse(elements[2])
      course.rate = elements[7].toDouble();
      course.client = client
      course.location = loc

      courses << course
    }
  }
}

The cool parts are (1) how I can use my regular Java classes, Location, Client, and Course, right in the Groovy script, and (2) the way I can build a URL string to access the geocoder at Google. The Java code to do the same thing would be a lot longer and much, much uglier.

The Groovy code to save the resulting objects is almost trivial, once Spring is loaded:


def ctx = new FileSystemXmlApplicationContext('src/applicationContext.xml')
def dao = ctx.getBean('courseService')

def saveCourses() {
  courses.each { course ->
    dao.addCourse(course)
  }
}

I played around with various business methods, figuring out how many training days I did in each year, looking a revenue, etc, but sooner or later I had to get back to Google Maps. After all, that was supposed the reason I started this whole exercise.

That’s when I hit a very fundamental problem. Like a good object-oriented programmer, I’d gone to all this trouble to retrieve my data as collections of Java objects. That’s fine if my user interface is in JavaServer Pages, or even Groovy. But JavaScript can’t read Java objects.

Nuts.

This isn’t a new problem, of course. I think the Ajax in Action book even has a discussion about it, to some degree. But this was the first time I really had to deal with it.

I think the potential solutions are:

1. Java wins. In other words, use my server-side Java to generate JavaScript as though it was just any other text, plugging in values from my objects as necessary. It’s kludgy, but doable.

2. HTML wins. Write the server-side Java code to return formatted strings, which the JavaScript can just read like any other text.

3. JavaScript wins. Find a way to convert my Java objects into JavaScript objects. To my understanding, that means JSON. I was tempted to implement a “toJSONString” method in all my entities, but haven’t yet. I still may go that way eventually.

4. Nobody wins. That means XML, of course. As the web services world has already recognized, every programming language can read and write formatted text. Even better, every language these days has a set of libraries for dealing with XML. Java’s approach has to be one of the worst, leading to reams of highly fragile code, but it can be done.

In the end, for this first iteration, I chose option (1). My application is a simple JSP, using JSTL tags to loop over the data and generate the JavaScript.

To make the data available I first wrote a context listener that loaded all the course data into application scope when the web application is first loaded:


public class CourseLoader implements ServletContextListener {
  private ApplicationContext ctx =
    new ClassPathXmlApplicationContext("applicationContext.xml");
  private CourseService dao = (CourseService) ctx.getBean("courseService");

  public void contextDestroyed(ServletContextEvent sce) {
    ServletContext sc = sce.getServletContext();

    sc.removeAttribute("locations");
    sc.removeAttribute("courses");
  }

  public void contextInitialized(ServletContextEvent sce) {
    ServletContext sc = sce.getServletContext();

    sc.setAttribute("locations",dao.getLocations());
    sc.setAttribute("courses", dao.getCourses());
  }
}

Then I wrote the JSP that does the actual mapping work. It has a <div> to hold the map, as Google Maps requires. Here’s the JSP that generates the JavaScript code. Near the top I have a taglib directive to bring in the core JSTL library:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Then I mix JavaScript code into a forEach loop to put markers on the map:


<script type="text/javascript" src="http://www.google.com/jsapi?key=..."></script>
<script type="text/javascript">
  google.load("maps", "2.x");
  google.load("search","1");

  // Call this function when the page has been loaded
  function initialize() {
    var map = new google.maps.Map2(document.getElementById("map"));
    var home = new google.maps.LatLng(41.612958, -72.452903);
    map.setCenter(home, 4);
    var marker;
    var html;
    var polyline;
    var location;
    var polylineOptions = {geodesic:true};
    <c:forEach var="course" items="${courses}">
      location = new google.maps.LatLng(
        ${course.location.latitude},${course.location.longitude});
      marker = new google.maps.Marker(location);
      google.maps.Event.addListener(marker, "click", function() {
        map.openInfoWindowHtml(
          new google.maps.LatLng(${course.location.latitude},${course.location.longitude}),
          "<b>${course.title}</b><br />" +
          "<em>${course.location.city}, ${course.location.state}</em><br />" +
          "${course.startDate} -- ${course.endDate}"
        );
      });
      map.addOverlay(marker);
      polyline = new google.maps.Polyline(new Array(home,location),
        "#ff0000",2,0.5,polylineOptions);
      map.addOverlay(polyline);
    </c:forEach>
    map.addControl(new google.maps.LargeMapControl());
    map.addControl(new google.maps.MapTypeControl());
    map.addControl(new google.maps.OverviewMapControl());
  }
  google.setOnLoadCallback(initialize);
</script>

and there you have it. If you go to my page and do a view source, you can see the tons of repeated code generated by the JSTL foreach loop, <c:forEach>. It’s certainly not the most elegant way to go, but it seems to do the job.

My next plan is to do option (4) and use XML as the common language. To avoid all the horrid Java code required, though, I’m going to use a Groovy MarkUp builder. As a sample, the code will look something like this little experiment, which translates all the locations into XML:


def locationsToXML() {
  def buffer = new java.io.StringWriter()
  def builder = new groovy.xml.MarkupBuilder(buffer)
  def locsXML = builder.locations {
    dao.locations.each { loc ->
      builder.location {
        city loc.city
        state loc.state
        latitude loc.latitude
        longitude loc.longitude
      }
    }
  }
  return buffer.getBuffer().toString()
}

Now that’s how easy it ought to be to convert to XML. Rather than finish all that, though, I figured I might as well get the application up and running, so feel free to have a look and let me know what you think.

I definitely have to give a shout-out to MyEclipse, though. Their editor helped me build the initial JPA and Spring configuration files and added the libraries I needed. The fact that the asm jar files in Spring 2.0 and Hibernate 3.2 conflict isn’t really their fault.

Actually, that’s a post for another day.

MyEclipse + JPA + Spring + Hibernate = DAO (mostly)

I just about have my Google Maps mashup working. When it’s deployed, it’ll show markers for each location where I’ve taught a course. Eventually I’ll filter them by year, connect them to home with polylines, and maybe more.

As a mashup, it’s not the most interesting application ever written, but it’s given me a good opportunity to learn the Google Maps API and to play with some other interesting technologies.

In this case, that means Spring 2.0 and the Java Persistence API (JPA). I needed some way to get my course data into and out of a database, and I certainly didn’t want to hardwire anything if I could avoid it. That meant I really needed a Data Access Object (DAO) layer for my courses.

I’ll describe the details over the next few posts, but here’s the good part. The newest version of MyEclipse, version 6.0, makes it extremely easy to add both Spring 2.0 libraries and JPA to a given project. The wizard provided asks for which JPA provider to use, with the available options being TopLink and Hibernate. Just because I’m familiar with it, I chose Hibernate.

(That lead to a serious bug later involving conflicts in the asm jar file, which I’ll also describe later.)

I also used Java 5 annotations to do the mappings, as in:


@Entity
@Table(name="locations")
public class Location {
    @Id  @GeneratedValue
    private int id;

    private String city;
    private String state;
    private double latitude;
    private double longitude;

    // ... etc ...
}

I also used Spring’s @Transactional attribute in order to build a service layer that interacted with the CourseDAO. That was seriously easy, especially when I had the excellent Spring in Action book to use for reference. Since I already planned to use Spring’s dependency injection to manage the DAO classes into the service layer (i.e., I had Spring inject the transaction manager, the data source, the entity manager factory, and whatever annotation capabilities I needed), I let Spring manage as much as possible.

Just for completeness, I wrote my DAO tests in Groovy, too. 🙂

The process was all kinds of fun, actually. As soon as I decide the code is good enough, I’ll describe all the pieces here. In the meantime, I’m just rather insufferably pleased with myself.

WebSphere Portal isn’t as horrible as I thought…

I remember several years back I was flipping through the pay cable channels and lucked into a stand-up show by Paul Rodriguez at San Quentin prison.

Through the magic of Google, here’s a link to the DVD. The concert was in 1995, apparently, so I guess it really was a while ago.

As I recall, he did a fantastic job. Unlike a lot of comedians visiting prisons, he came across as quite comfortable, neither overly nervous nor condescending. It was great.

He did one excellent routine in particular about getting older and having to visit the doctor for a, shall we say, rather invasive test. He talked about how he had no choice but to try to be a man about it, rooting for them to go deeper, but then came the best part:

(paraphrasing from vague memory) “Just then, the worst possible thing in the world started to happen.”

(dramatic pause)

“It started to feel good.”

As you might imagine, that cracked everybody up.

I’ve been thinking about that routine a lot this week. What triggered such an odd memory? This week I just finished teaching a class in Portlet development in IBM’s Rational Application Developer (RAD6).

I was sorely tempted to blog about the class last week, but my comment might not have been diplomatic given that one of the students this week might stumble across my blog. Last week I wound up blowing two full days just installing RAD6, then updating it, then installing the WebSphere Portal Server 5.1 test environment. As I discovered, I had to do the multi-hour installs in that order, too, or the server wouldn’t start.

I mean that literally, by the way. I lost two full days just to the installation and diagnosing bizarre errors. Then, I got to my class this week, only to find that the installed test server in RAD6 wouldn’t start either. That basically meant all of Monday was going to be shot, even assuming I could get the thing to work at all. As Bill Simmons would say, not good times.

Fortunately (?), half the class (okay, two of the four, and maybe a third also) didn’t have the proper background for this course. Therefore I had a fallback position for Monday. I could spend the day in a good, solid Java review, complete with a discussion of server-side concepts, web applications, and so on, and use the actual courseware just for the background motivation and product description sections. I’ve been doing this stuff for a while now; I knew I could do something very productive for this group of students for one day of a five day class. That’s about all the slack I had, though.

All the while, I was uninstalling, downloading, and installing the software, and swearing that I would never, under any circumstances, ever be stupid enough to agree to deal with this horrible, buggy, massive IBM software again. My frustration with IBM has been building up for months now, and this was the worst possible situation for me.

As it turned out, the students really did need the background and were glad for the review, not to mention the examples I went through. I made it as interactive as possible, even though I didn’t have actual workshops for them to do. We got through it.

Then they left, and it was time to start the install/update process. Other circumstances were forcing me to leave by 5 pm, but I could get everything started and come back later in the evening to babysit the install and switch disks when necessary.

There were some bumps along the way, but finally, at about 1:30 am, everything worked. I at least had a working product, so the course could continue. I think the good image was successfully distributed to the student machines by 2:30 or 3 am, so I could crash until class started again at 8.

We then worked our way through the materials. I did a lot of hand-holding on the labs, doing them with the students interactively in many cases. That re-claimed some time, and helped the students see the forest for the trees.

By about Thursday afternoon, though, the strangest thing started to happen. Maybe it was the fatigue, or maybe I’d worked through the exercises just enough times for the concepts to really sink in, but just like Paul Rodriguez above, I had a bizarre reaction.

For the first time, I started to actually like WebSphere portlets.

The code involves a complicated combination of API calls, JSP custom tag libraries, and XML configuration files, not to mention working with services in the portlet container. The whole system has a nasty learning curve. But suddenly I just kind of “got it” and it didn’t all seem so bad any more.

I’m still blown away by this. I now thinking it might be worth it to install RAD7 and WPS 6 and really dig into the JSR 168 spec and write a portal for my own site. I may actually do that, too, despite the fact that there isn’t yet a good redbook available describing the process. I can almost see the benefits of working with what I would have described last week as a frustrating, dead-end technology.

As I tell my students, I’m wrong a lot, but I don’t stay wrong.

I haven’t decided on the details. I may experiment with JBoss portal server instead, or even the Sun app server. But a week ago you couldn’t have forced me to deal with portlets, and certainly not with IBM. Now I’m thinking about freeing up some time in July to see what I can do with them.

First I have to get used to the horrible feeling that this stuff is starting to feel good. 😉

The Spring Framework outranks private

I’ve been using the Spring framework for about a year now (or maybe more — it’s amazing how fast time goes by these days). I’ve also been teaching courses in it using Capstone Courseware materials.

As is normal with Capstone materials, they tend to skip quickly through the “Hello, World!” version of whatever technology they’re discussing, preferring to go on to applications that much more closely represent the real world. That way they can discuss subtleties and best practices while still communicating the basics.

A simple example is the way Spring can enforce the Singleton design pattern or not, regardless of the way the underlying Java bean is written. Say we have a Java bean that looks like:

public class MyBean {  private static final MyBean INSTANCE = new MyBean();

  private MyBean() {}

public static MyBean getInstance() {

    return INSTANCE;

  }

}

MyBean is a classic example of a Singleton. It has a private constructor, a static attribute to hold the shared instance, and a public static getter method to return it. As far as Java code is concerned, there will never be more than one instance of this class.

Spring gets along with singletons quite well. In fact, by default all Spring-managed beans are singletons. The fun part, though, is when we tell Spring that this bean is to use scope=”prototype”, implying that it should return a separate instance each time a bean is requested.

<beans xmlns=…>
<bean id=”MyBean” class=”cc.beans.MyBean”
factory-method=”getInstance” scope=”prototype” />
/>

The question is, what happens in the code when factory.getBean(“MyBean”) is called twice? Does Spring return two references to the same object (rejecting the “prototype” designation) or does it return two separate instances (rejecting the private constructor)? Who wins?

Spring does, which probably doesn’t come as much of a surprise to anyone who has played with reflection before. All you need to do is to get the Class reference for the bean, retrieve the private constructor, and call setAccessible(true) on it and it’s yours. Spring does what it’s told to do, working around any supposed limitations in the Java code.

That’s either troubling, or pretty cool, depending on your point of view. What I can say is that it comes as quite a surprise for most students in class.

Of course, my real point is that the Capstone materials discuss this case in detail, which is not necessarily the sort of issue you’d expect to see in a training course.

The materials talk about a wide range of Spring issues, including major sections on the web (MVC) framework, the DAO layer (with templates), and a bit about integrating with ORM tools.  The bottom line is that after having taught that class probably a dozen times in the past eight or nine months, I felt I had a pretty good handle on the framework.

Well, yes and no.

(Or, as I tell my students, “that turns out not to be the case.”  The phrase “that turns out not to be the case” is the most diplomatic way to tell your boss he’s completely wrong.  You can even preface it with “I can see why you might think that, but” if you like.  Try not to roll your eyes while doing so.)

The other day, I attended a meeting of our local Connecticut Java Users Group.   The meeting featured a presentation by Mark Fisher, a consultant with Interface21, the creators of the framework itself.  I knew I wanted to see that, because even if he spent all his time talking about areas I’ve already used, I knew he’d say lots of things I didn’t know.

I’ll say more about that soon.  This post is getting rather long.

%d bloggers like this: