Welcome to JoshLong.com, home of my personal blog
<< Last | Next >>
December 28, 2009

So Much to Do, So Little Time!

Spring 3.0's out (you didn't get the memo?), and there's a lot of interesting stuff. This release has been long in coming due in no small part to the specifications it tracks and to the intense furvor and emphasis placed on quality assurance and testing. One target platform - JEE6 (and with it the final versions of JSR330) - also just recently went final, and you'll find support for these technologies, as well, where appropriate. Now that it's out, you can start certifying applications in production on it. I've found that - aside from dealing with the new Maven imports - the upgrade process has been flawless. I've taken complex applications and merely fixed the jars and they continue to work. You will find, however, that there are a lot of reasons to go through and start selectively enabling new features, and namespaces.

In our book Spring Enterprise Recipes, my co-author Gary Mak and I discuss a lot of the new, exciting Spring 3.0 features. Spring 3.0 debuts slightly more streamlined scheduling / TaskExecutor / thread pool support. The idea is that you can more readily model asynchronous, repeating (at a scheduled time, rate, or both), and concurrent programming problems using these facilities and - in some cases - do so while leveraging more advanced facilities underlying a given target platform, like the WorkerJ implementations, the Java5 task executors, and thread pools and more.

I won't go into much of that here as the book ablely covers most of it, but one thing I did want to cover (which we couldn't cover in time in the book as the feature was not ready as the book went to press) was the very elegant task namespace.

Background

It should be noted that these features are not, exactly, novel. Spring has shipped with a Quartz scheduling framework integration for years. Among many other niceties included therein was (and still is, for what it's worth) a MethodInvokingJobDetailFactoryBean that allowed you to schedule future executions of a method on a Java bean using Quartz.

A few years later, EJB 3 debuted support for a limited form of scheduling using the Timer mechanism. One major limitation was the lack of support for CRON-like expressions and for asynchronous methods. Naturally, you could use JMS to acheive the same effect, in a way...

The JBoss gang debuted JBoss Seam support for scheduled and asynchronous method execution on a Seam component as well as a proprietary mechanism to do the same with EJB 3. In Seam, using these features was simply a matter of adding the appropriate configuration (as we do in Spring) to enable the executor (they have a few, including one based on the EJB3 Timer and one based Quartz.) The usage here is familiar to what has recently been debuted in Spring 3.0.

Clearly, the need for such features is common enough that they've both been fully incorporated into JEE6 and EJB3.1. There, you can specify CRON expressions as well as defer the invocation of a method using the @Asynchronous or @Schedule annotations. A simple example looks like:

package com.joshlong.ejb.timer ; 
import java.util.Date; 
import java.util.logging.Logger; 
import javax.annotation.Resource; 
import javax.ejb.Schedule; 
import javax.ejb.Asynchronous; 
import javax.ejb.Stateless; 
import javax.ejb.Timeout; 
import javax.ejb.Timer; 
import javax.ejb.TimerService; 
@Singleton 
public class PeriodicGreeter { 
 // you could use this to schedule things manually 
 @Resource TimerService timerService; 
 // or use the annotations to do so automatically 
 @Schedule (minute="*/3", hour="*") 
 public void sayHelloPeriodically () { 
   System.out.println ( String.format ( "Hello, world, at %s" , new 
Date ()) ) ; 
 } 
 @Asynchronous 
 public Future<String> sayHelloAsynchronously () { 
   System.out.println ( String.format ( "Hello, world, at %s" , new 
Date ()) ) ; 
   // ... 
 } 
}

Spring 3.0 Implementation

The task namespace let's you declaratively configure a TaskScheduler and a TaskExecutor instance using XML. From here, you can configure beans that have scheduled, or asynchronous, executions using the XML or - my personal favorite if you can get access to the code - via Java annotations.

Here's an example Spring application context featuring this namespace and configuring a scheduler and executor with default-ish settings:

 
<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:task="http://www.springframework.org/schema/task" 
   xmlns:context="http://www.springframework.org/schema/context" 
   xsi:schemaLocation=" 
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
       http://www.springframework.org/schema/lang 
       http://www.springframework.org/schema/lang/spring-lang-3.0.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.0.xsd 
       http://www.springframework.org/schema/task 
       http://www.springframework.org/schema/task/spring-task-3.0.xsd"> 
 <context:annotation-config/> 
 <context:component-scan annotation-config="true" 
       base-package="com.yourbasepackage.scheduling" /> 
 
 <task:scheduler id="scheduler" pool-size="10"/> 
 <task:executor id="executor" pool-size="10"/> 
 <task:annotation-driven scheduler="scheduler" executor = "executor" /> 
 
</beans> 

What you do from here is up to you. You could simply start defining tasks inline with your XML. That approach certainly has its redeeming qualities, not the least of which is that your code is more readily "documented" and conceivably adjustable at runtime with some refresh trickery... sure.. you could.

 
<task:scheduled-tasks scheduler="myScheduler"> 
 <task:scheduled ref="greeter" method="sayHello" fixed-delay="5000"/> 
 <task:scheduled ref="greeter" method="sayHello" fixed-rate="5000"/> 
 <task:scheduled ref="greeter" method="sayHello" cron="*/5 * * * 
* MON-FRI"/> 
<task:scheduled-tasks/> 

...In practice, however, the annotation approach just FEELS soo much better! So, here is how you might write a scheduled or asynchronous bean in Spring.

package com.joshlong.spring.timer ; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.scheduling.annotation.Scheduled; 
import org.springframework.stereotype.Component; 
import javax.annotation.PostConstruct; 
import javax.annotation.Resource; 
import java.util.Date; 
@Component 
public class SpringPeriodicGreeter { 
 // you can do everything you normally would using Spring, obviously 
 @Autowired CustomerService customerService ; 
 // this runs once every 5 minutes 
 @Scheduled (fixedRate = 1000 * 60 * 5) 
 public void sayHelloEveryFiveMinutes () { 
   System.out.println ( String.format ( "Hello, world, at %s" , new 
Date ()) ) ; 
 } 
 @Scheduled (cron="*/5 * * * * MON-FRI") 
 public void sayHelloOnlyOneWeekdays () { 
   System.out.println ( String.format ( "Hello, world, at %s" , 
new Date ()) ) ; 
 } 
 @Async 
 public void doSomething (String s) { 
  // this will be executed asynchronously 
 } 
 @Async 
 public Future<String> returnSomething (int i) { 
   // this will be executed asynchronously, but you can get the 
   // result by blocking on Future.get 
 } 
} 

Thus, this is nothing too strange - very simialar in fact to what's in JEE6. Obviously, I've not mentioned every permutation of the features from the various technologies, but hopefully this gets you past the initial cognitive "hump" of adapting a new technology. It helps that - at least in the Spring case - it's dead simple to start using it if you're already using Spring. I wonder if there will be support for working with the JEE6 annotations that describe the same things? The major takeaways are that you can get this simply by updating your version of Spring, which should be painless if you're not tied to Java 1.4. You can get the JEE6 functionality by updating your version of the platform and server, if the platform/server are ready (Glassfish is!).

Use

Now, as to where this stuff might be used, well, I can only think of a few thousand things...

  1. Quartz is probably still more powerful, but the implementation and usage are hackneyed - this new approach will feel much more elegant. You could probably get away with removing the old Quartz code and using this for most of your implementation needs.
  2. Because Spring's implementations are swappable, you could back this functionality with varying TaskExecutors/TaskSchedulers of your own implementation, if you wanted.
  3. The obvious use case is that you can now remove CRON, Autosys, Flux and any number of other third-party, dedicated middleware schedulers from your architecture (if you're only using them to run Java services.)
  4. As with Spring itself, this abstraction is useful because you can deploy it inside of a web applicatior or any other place you can imagine Spring running, so you don't need to install a scheduler if you just want something run periodically inside your web container
  5. If you have a Spring Batch job, this might be an ideal way to kick the jobs off periodically. You need to start processing the billing batch every night at 2am, but only on weekdays? This is a match made in heaven! How you get a Batch job to start running is left mainly as an exercise to the user. I recommend using an ESB (like Spring Integration) to react to events, or using a scheduler like this task namespace (or Quartz) to kick the jobs off.
  6. Spring Integration has a gateway mechanism that lets you front what is essentially a send (and/or) recieve operation on a channel (think: JMS queue/topic) with a method on an interface. I love this feature and use it a lot because I don't want to surface JMS queues / topics to the client (that's a little too loose and decoupled an API!). I also use it because it allows me to model fire-n-forget messaging using Java interfaces, which is exactly what the @Async annotation does. The other benefit of the Spring Integration feature is that the processing leaves the VM and goes somewhere to finish (ostensibly, wherever the consumer for the topic/queue lives) the job and then return the result. This provides scalability benefits to both the client and the server, whereas the @Async annotation would only increase the thoroughput of the client, in this case: processing still takes place on the node with the @Async annotation, it's simply deferred... Deferment is a valid way to increase capacity while decreasing thoroughput.
November 29, 2009

My Tweet Cloud

Waiting for a long running process to finish up. Started screwing around on the internet and found a useful little application called TweetCloud. It generates a neat looking image-based cloud of your tweets. Here's my tweet cloud. I'm @starbuxman, if you're on that busy network and wanna chat.

November 28, 2009

Spring Batch's MultiResourceItemWriter

If you've ever had to do batch processing, then you know how tedious it can be to write all the infrastructure code surrounding retries and error recovery and usefully handling long running processing and all the other tedium that surrounds a typical batch application. For these types of applications, I use Spring Batch, a batch processing framework from Dave Syer and the fine people at SpringSource.

The basic idea is that you setup jobs that have steps, that have tasklets. This the normal use case, but by no means the only one. You use jobs and steps to string together sequences of processing input and writing to output via a reader and a writer. Spring Batch has implementations for both reading and writing that will likely meet most of your needs: XML, files, streams, databases, etc. There's so much interesting stuff here, so of course I humbly recommend you take a crack at the documentation or read my book, Spring Enterprise Recipes.

That said all said, there's no obvious way to read from an input source and then write to multiple files. The use case here, in my case, is Google's Sitemaps. These are XML files that describe the pages on your site. You list every URL possible. If you have more than 50,000 links, then you must create many files and list those files in a Sitemap index file. So, I wanted to read from a database and derive all the URLs possible for content, and then write those to sitemap XML files, where each sitemap could not exceed 50,000 entries. Spring Batch ships with an adapter writer that serves exactly this purpose. It's called org.springframework.batch.item.file.MultiResourceItemWriter. You define it just like you might any other writer, except that you wrap another writer with it.

Here's the salient bits from my configuration. Most of this is boilerplate. I don't include the configuration of the Spring Batch environment, or the configuration of the reader, because those are pretty typical. Note that here we configure the writer for the job and in turn configure its delegate property, where we have the real writer implementation. In this case, there's no need to configure the delegate writer's resource property.

 
<beans:beans xmlns="http://www.springframework.org/schema/batch" 
             xmlns:beans="http://www.springframework.org/schema/beans" 
             xmlns:aop="http://www.springframework.org/schema/aop" 
             xmlns:tx="http://www.springframework.org/schema/tx" 
             xmlns:p="http://www.springframework.org/schema/p" 
             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/batch 
http://www.springframework.org/schema/batch/spring-batch-2.0.xsd 
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> 
    <beans:import resource="batch.xml"/> 
    <job id="batchForCreatingSitemaps"> 
        <step id="sitemap"> 
            <tasklet> 
                <chunk reader="reader" writer="writer" 
commit-interval="${job.commit.interval}"/> 
            </tasklet> 
        </step> 
    </job> 
    <beans:bean id="siteMapLineAggregator" 
class="com...sitemapscreator.SiteMapLineAggregator"> 
        <beans:property name="domain" value="${sitemaps-domain}"/> 
    </beans:bean> 
    <beans:bean 
class="com...sitemapscreator2.ResourceSuffixCreator" 
id="resourceSuffixCreator"/> 
    <beans:bean id="writer" scope="step" 
class="org.springframework.batch.item.file.MultiResourceItemWriter"> 
        <beans:property name="resource" 
value="file:#{jobParameters[outputResourcePrefix]}"/> 
        <beans:property name="resourceSuffixCreator" 
ref="resourceSuffixCreator"/> 
        <beans:property name="saveState" value="true"/> 
        <beans:property name="itemCountLimitPerResource" value="50000"/> 
        <beans:property name="delegate"> 
 
            <beans:bean 
class="org.springframework.batch.item.file.FlatFileItemWriter"> 
                <beans:property name="encoding" value="UTF-8"/> 
                <beans:property name="shouldDeleteIfExists" value="true"/> 
                <beans:property name="lineAggregator" 
ref="siteMapLineAggregator"/> 
            </beans:bean> 
 
        </beans:property> 
    </beans:bean> 
    <beans:bean id="siteMapUrlRowMapper" 
class="com...sitemapscreator.SiteMapUrlRowMapper"/> 
    ... 
</beans:beans> 
November 26, 2009

Thanksgiving

I have a lot to be thankful for. This year saw my wife and I move to Los Angeles, where we've been well received in new jobs and by family. I've experienced success speaking at various conferences, and this year saw the publication of my first book, Apress' "Spring Enterprise Recipes." Recently, I was in a pretty bad accident (a big-rig rear-ended me) and I emerged alive. I have a wonderful wife who has always supported me, and I have made good friends. I am thankful for the readers of my blogs. I am thankful for my loving friends and family.

I hope you have a long list of things for which you're thankful, too. Happy Thanksgiving!

November 21, 2009

'Spring Enterprise Recipes,' from Apress

Warning: Shameless Plug

I am pleased to announce that, after a long time and a lot of work, my first book Spring Enterprise Recipes (which I co-authored with the indefatigable, epic and extraordinary Mr. Gary Mak, author of - among many other things, Apress' Spring Recipes) has been released and is now purchasable. It should be hitting book stores soon, but in the meantime, you can buy the e-book at Apress.com, or you can pre-order it on Amazon.com.

The book discusses Spring 3, but also accounts for the many "modules" surrounding Spring with an eye towards building elegant, scalable systems with a minimum of fuss. Many of these modules have come from SpringSource, and some are independent third party projects that integrate well with Spring. Spring Enterprise Recipes introduces concepts like business process management (BPM), enterprise application integration (EAI), distributed computing and messaging and then grounds these introductions with real-world examples using Spring and lead open source frameworks.

This book discusses both the why and the how. It starts with a discussion of the usual suspects, exploring the quintessential tools in any developer's toolbox: RPC (RMI, Hessian, Burlap, Web Services, HTTP/Invoker, EJB 2 and 3, and more), messaging (via JMS), database access (JdbcTemplate, and a few of Spring's numerous supported ORM abstractions), transactions (e.g., various transaction abstractions supported by Spring), and numerous services like e-mail, JMX, worker pools, and scheduling infrastructure.

Then, we progress into more advanced solutions. This book includes the first-in-print or most updated coverage of a lot of technologies, including Spring Integration (a lightweight ESB-like integration framework for EAI), Spring and jBPM 4 for business process management, GridGain for grid computing, Terracotta for clustered state managment, Spring Batch for batch-processing solutions and OSGi to bring modularity to your application.

In the large, this book is a gentle, but comprehensive introduction to the best-of-breed solutions for tomorrow's architecture using Spring and other lightweight, powerful tools. Having said all that, I hope you'll consider it for your next purchase and that it helps you solve some interesting problems and build even more interesting solutions!

November 17, 2009

Understanding Go

Go, a new language from Google, has created quite a stir. It has a great pedigree, owing to renowned experts like Rob Pike (a member of the Unix team, and a creator of the Plan 9 OS from Bell Labs.) The language is a procedural language (like C, or Python) which offers a strongly typed, but flexible type system (not centered around object-oriented facilities as we know them from languages like Java and Ruby). The syntax is a strange mix of C and Python. Honestly, it feels like C when you read it, but it writes more like Python - lots of features in the syntax that are designed to be consistent, predictable.

One blog entry prompted a very lively discussion of the language: it made the comparison that Go seemed awfully similar to Algol 68, a language 40 years past irrelevance. The blog entry said that while Algol 68 was a nice language, Go might be considered an efficient language. It claimed that efficient languages are the ones that - ultimately - propagate. Witness COBOL, C, C++, and Java, for example. Go, thus, may very well be a very efficient language, but it's not even close to a nice language. It's a lost opportunity.

Programming languages tend to come and go, but they all advance basing their innovation in some small part on their predecessors. Programming languages have to evolve slowly. Languages do not exist in a vacuum. They must respect the work that's preceded them, while innovating. They must strike a careful balance, never alienating the existing community, the legacy base, and always advancing the state of the art. Doing so incorrectly can be the biggest sin a language can make. Kowtowing to the legacy of C crippled the evolution of C++, leaving it a confusing mix of phantom requirements and artificial features. Conversely, Java achieved meteoric propagation because it looked and felt like C++ without many of the warts. This made the transition to Java easy. Compatibility is a double edged sword.

Most recent languages look and feel like C/C++. They've innovated ever so slightly, inducting into the syntax features formerly handled by libraries. Or, the language is flexible enough to support requirement-specific DSLs. You can see this with Scala and Groovy, Ruby and C#. They're all fairly familiar, but offer advantages in their grammar over their predecessors. C#, for example, introduced LINQ, while Scala surfaced its concurrency facilities as an Actors DSL. The idea of a language syntax as a differentiators is even more relevant of late. The .NET runtime popularized the idea of a multi-language run time. It meant that choosing a language did not mean forsaking libraries. The JVM has matured, and there are many languages implemented atop it, as well. Other infrastructure VM projects have emerged, like the LLVM.

So, I don't blame Go for looking so much like its predecessors. That's the cost of doing business. It's intended to be a general purpose language, after all. It does have a few unique features surfaced as language constructs, like intrinsic concurrency facilities, which it calls gorountines.

I don't understand why they have built another virtual machine. If Go is going to innovate, it will be in its Virtual Machine. Why not the CLI, JVM, or LLVM? The language has strong support for interop - easily wrapping native code much like you might using C++. The .NET CLI supports this sort of thing, though. I understand the language needed to run on Unix (at the moment, you can't run it on Windows!), and perhaps Mono wasn't sufficiently advanced. Why not the JVM? Would building that kind of infrastructure be that hard? What about the LLVM? It seems well suited to working on Unix and to handling interop. Perhaps interop is not the only concern. The implementation of the goroutines seems to have been a priority. The language does not yet have assertions or exceptions specifically because doing so would be awkward with goroutines. This language, as Mr. Pike explained it, was created for Google to build servers. Cheap, and efficient threading was priority #1. This piques my curiosity. Why could the JVM - which hosts Scala and Clojure - not be used to build goroutines. Is there some fundamental flaw that makes concurrency on the JVM a non starter? I don't understand.

I would agree that the language is not particularly novel. What I don't understand is why the VM is novel. Clearly there are requirements I don't understand, and this is why I think Go will be worth paying attention to, in much the same way Erlang is.

There is also something refreshing about a genuinely new language. New platform, new libraries, new syntax. Programs written in a language like that represent advances. Shortly after the debut of the language, a command line Twitter client emerged. The example is promising - by definition the implementation was from-scratch. It was quick, and the result is imminently readable.

Perhaps I'm over thinking this. Perhaps the language will be successful because it's simple, and efficient. Perhaps the VM is some how unique and better served by a custom implementation. Only time will tell.

November 12, 2009

The Last 2 Crazy Months

What a busy couple of months!

I started last month (from October 2nd to the 11th) at the Java2Days conference in Sofia, Bulgaria. I gave three talks on Spring and JSF, Spring and jBPM, and Spring Integration (the Spring ESB-like framework). I think the slides will be available there in shortly. Meanwhile, here are some photos of the event below, though you're encouraged to log in to Facebook and check out the full galeries there.

The name of the gentleman on the far left escapes me, but that's John Lewis, Emo, and yours truly on the right

From left to right: Ivo Penev, Gisele Consoline, Rob Harrop, yours truly, John Willis, and Heath Kesler

I had a great time at the conference. The audience was great the discussions great, too. The drinking was good, too! :-)

At some point, I got some sort of stomach bug (perhaps in Greece?) and when I returned home, I was severely dehyrdated. I spent a little time hooked up to an IV and then spent the subsequent week pounding antibiotics, gatorade, and soup. There's a thousand ways to get sick, only one way to get better!

After that, I got deep into the final edits for my book "Spring Enterprise Recipes." Really enjoyed that process - it's fascinating to see what goes into writing a book. Trust me, the book is far better for the effort of the amazing editors at Apress! :-)

I spoke at the Pasadena Java User Group on using Spring Integration - that crowd was very cool and the discussion that ensued was also good.

Recently, my sister got married. I wish her, and her husband, many happy days together.

I think that wraps up the highlights. I'll start chiming in more frequently. A lot has happened of late, including the debut of Google's Go programming language, The Motorola Droid, the continued standoff between Sun/Oracle and the European Union over objections to Oracle's accquisition of MySQL, and more. Exciting times...

September 10, 2009

CRUD's Not The Answer

I was really glad to see Udi Dahan's, "Don't Delete. Just Don't." I wholely agree with the main premise - that deletion is rarely, if ever, a valid business state and that care should be taken in dealing with it. He cites various examples, saying, "The real world doesn't cascade." His example is of a marketing department that deletes an item from the catalog. Should all orders containing that item then be unlinked? Should they redo the company's profit and loss statments?

His example's a perfect illustration of a valid case where care needs to be taken both in modeling the case and dealing with it in code. I fear a lot of people have gotten hooked on instant-models or CRUD "frameworks." The idea that you can annotate a few entity classes and suddenly you have a model and business logic all taken care. A lot of this became popular with Ruby on Rails and has only gotten worse in the JEE world. It's now common to expose EntityManagers to the web tier (both the Seam and Spring Web Flow examples, not to mentino the Open Session in View pattern itself, speak to this) and to let web frameworks handle the lifecycle of entities and committing transactions on that EntityManager to persist those entities. We now think of record creation and managment as so mundane that we've automated it and surrounded it in scaffolding.

Unfortuntately, this misses the true value. Objects in a system have state that has dependencies. Just because an entity has a (required) no-args constructor, it doesn't mean that you should not write a constructor with dependencies. A lot of this stems from the "active objects" or "naked objects" pattern, where objects are open books whose state can be mutated on the UI tier directly and those changes propagated directly. We tell ourselves that we can apply Hibernate validations (or validations in any other ORM framework) and that we'll guarantee valid business constraints thus, but it rarely works out that way. Prescribing the valid creation and destruction of an object is critical.

The most insidious part of this abuse is that it rarely ever occurs in the first iterations of a project, only in maintenance. People "forget" how an object is created, or destroyed. They forget details. Consistancy with other parts of the system is forsaken because, after all, how much could there be to it? This happens more often than you'd expect: new people come on to the team and are assigned to rework an existing feature and screen in a system. Institutional knowledge is important but it's not always easily transferred, so safe-guards need to be taken.

Plus, as business evolves, object creation is often only part and parcel with a larger process. If a new customer is added to a database, and nobody does anything with it, did it really get added? Put another way: if a new customer gets added to a database, there's an implied lifecycle that customer must follow. Perhaps a trial period window and then a follow up email? Perhaps a monthly subscriptio fee? Who knows, but the act of instantiating a Customer object and then issuing entityManager.persist ( customer ) will rarely, if ever, be enough.

Indeed, I've seen many projects build their models using only a GenericDao<T> variant. This is dangerous. Transitions from one state to another for an entity can often cost money.

Do things the old fashioned way, building services that handle the business operations, not merely Create, Read,Update and Delete objects. Using Dao's in a view tier is almost as ghastly a sin as making JDBC calls from the view, and encourages the same kind of copy-n-paste code reuse we prided ourselves on having moved away from.

While the services approach isn't exactly code-generation friendly, it can pay off in the long run. As soon as you decide to use your services in a phsically separated tier, you'll be glad. It's easier to build services that express every dependency as a method parameter. There are several reasons why this works out. While web service support is getting better, object marshalling is still the number one headache. Most toolkits make interoping with primitives a brease, though. It may seem like your losing ground by not taking advantage of the POJO you have floating around in the view tier, but in point of fact it's rarely that big a burden to unmarshal the relevant fields and use those instead. On the services side, reloading the relevant record is painless because the entity's usually cached and thus refetching it is cheap.

Take for example the idea of a shopping cart which surfaces methods for adding line items to orders, orders to shopping carts and shopping carts to customers. A clean version of this might look like:

 
 public interface ShoppingCartService { 
     ShoppingCart createShoppingCartForCustomer ( long customerId, 
                                                 Date 
whenShoppingSessionStarted ) ; 
     Order createOrderForShoppingCart ( long shoppingCart ) ; 
     LineItem createLineItemForOrder ( long orderId, long productId, 
int quantity) ; 
     void removeLineItemFromOrder ( long orderId, long lineItem ) ; 
     void startOrderFulfillment ( long orderId ) ; 
     /*  other methods for loading and removing the various 
         objects, as appropriate 
     */ 
  } 

In these methods, you can do sanity checks, care for business cases, handle the state of the various objects and not worry about having a transactional resource like an EntityManager or Hibernate Session open in the client thread. In this example, you might imagine the Order won't officially be fulfilled until it's paid for, at which point it'll move to the PAID state. Simialarly, adding a LineItem might require a check to an inventory, decrementing how many of those Products are in stock. The same is true of the inverse operation: removeLineItemFromOrder should appropriately restore the inventory count and update the totalPrice field on the Order.

This requires one interface method declaration's work more than if you had simply obtained the EntityManager from your Seam backing bean and executed the logic there, except now the logic's codified and reusable.

September 3, 2009

Setting Up jBPM 4's XSD File In Eclipse

I've recently been playing with jBPM 4.1 and, while I haven't quite gotten into it, I did manage to break an Eclipse setup of my "old" jBPM 4.0 code. This is definitely a user error. So, trying to ensure I have a reproduciable baseline, I start setting everything up again (I don't have the jBPM plugins or anything installed -- I keep it mean and lean, if possible. )

I got to the point where everything was running fine again from the IDE, but I noticed I no longer had code completion for my jBPM .XSD file. I'm not sure if I ever did, or if I did, then I've forgotten how. So, I stumbled through getting it working with the Eclipse Resource Catalog. Here are the steps to reproducing it if you have the same issue.

  1. You'll need a copy of the .XSD itself. For me, the simplest option was to just download the source jar and use the XSD file therein.
    mkdir ~/xsds; cd ~/xsds ; 
    wget http://repository.jboss.com/maven2/org/jbpm/jbpm4/jbpm-api/4.0/jbpm-api-4.0-sources.jar 
    ; 
    jar xvf jbpm-api-4.0-sources.jar ; 
    
  2. In Eclipse, go to Window > Preferences
  3. Search for "XML Catalog," under the "XML" node.
  4. Click "Add..."
  5. Fill out the dialog, using the values below.

I hope this spares somebody some pain. Once you've got it working, go check out the awesome new jBPM 4.1!

August 29, 2009

My Christmas Wish, OR How the JVM Will Outlive the Cockroach, and .NET

It started with a Tweet from Miguel De Icaza. Miguel's the leader of the Mono project, whose goal's to bring .NET to Linux. He's also the former leader of the Gnome project. Generally, he's whip smart and not usually prone to flame baits. So, I tend to read his words carefully, as it usually pays off. He said: "I wish Java tried to compete with .NET, but they seemed to have given up a long time ago: http://tinyurl.com/mfxmqm"

At this point I wanted to write him a terse letter stating my point of view, stating how he had clearly missed the obvious. I resisted, hugged the wife, cried a little, sat on the beach with candles, attended a book club meeting, found Jesus, and then came back and reconciled that I was just sad because he was right. He was also pointing out the obvious. (There, at least I can say that! in the anonymity of my blog, far, far away from where he might see it...)

The link points to integrations in Project Coin, a project that's taken the JDK and aggressivey evolved the language to try certain features out in an isolated fork. In general, I'm supportive of the movement, but it's a sad truth that any final edition of JDK 7 is already late, and will likely not incorporate many of those integrations in Project Coin, or even many of the originally announced - big ticket changes coming straight from Sun. JDK7 is the Windows Vista/Longhorn of the JDKs.

You remember Longhorn, right? It was the code name for Windows Vista for a few years. If I recall, there was talk of integrating 4 pillars or waves of technology into the then-hyped next generation of Windows, including WinFS (Am I wrong in thinking that it was called something else, then? Avalon? Or am I thinking of the now-defunct Java DI container?) Indigo, and a slew of others. As the roadmap slipped further and further, more things were dropped. In fairness, in 2009, some of those pillars have subsequently shipped, sort of, as parts of .NET 3.0-3.5x. Some are lost to the annals of history.

With a heavy heart I proceeded to code, ignoring what he said. I'm tougher than that. I can handle having the rug yanked out from under me. "Why would he say that about my precious Java??" I thought, typing as I thought it. "I wish I could come up with something to refute his claims!", I moaned. Something elegant, quick, crazy fast, and future proof. Something's got the best of C#, F#, Python, JavaScript and more. I tend to ignore skills I've built up over years of use and revert to primitive, conveniently blog-friendly samples from tutorials when I'm stressed (don't you?). And boy was I stressed! I looked at my screen. I was really in a tizzy at this point, thrashing away at the keyboard! (Like in those movies where they feature somebody running their hands along the home row and suddenly they've infiltrated the FBI's secret-most files.)

Here's what I had typed:

object Maps { 
 val colors = Map ("red" -> 0xFF0000, 
 "turquoise" -> 0x00FFFF, 
 "black" -> 0x000000, 
 "orange" -> 0xFF8040, 
 "brown" -> 0x804000) 
 def main (args: Array[String]) { 
 for  (name <- args) println ( 
 colors.get (name) match { 
 case Some (code) => 
 name + " has code: " + code 
 case None => 
 "Unknown color: " + name 
 } 
 ) 
 } 
} 

It was a Christmas miracle! A language on the JVM that already had most of the proposed changes in Project Coin and great deal otherwise and was very fast and that worked on all platforms, just like Mono! Errr... that is, just like Java!

This language, Scala, has gained a great deal of traction in the Java community and even people you'd expect to offer otherwise have endorsed it. People like James Strachan, creator of Groovy, and James Gosling, creator of Java.

I just hope that other people can find out about this wonderful language. Why, wouldn't it be nice if -for Java 8 (will we ever get to have a Java X? How cool would that be??) - we just shipped Scala?

And that, boys and girls, is how Java outlived the cockroach, in our hearts.

The End!

<< Last | Next >>