Andy Piper wrote an excellent blog post
(http://dev2dev.bea.com/blog/andypiper/archive/2006/07/spring_20_and_m_1
.html) about using Spring for the equivalent of EJB Message Driven
Beans. Worth checking out if you're looking at dropping EJB from your
Spring app entirely.
You read blogs. You must do because you’re here. So if you can spend 5 minutes reading a blog post why not spend the same amount of time reading a classic piece of literature. DailyLit is a service that breaks up free books into digestible chunks and feeds them to you through RSS or email. Genius!
A few weeks ago I blogged about Spring and EJB integration, but something just did not sit well with me. Why would you want to do this at all?
I like Spring. Its myriad components make my life simpler. I can write the business code I need to faster without worrying as much about the plumbing aspects. The Spring contributors have put a lot of thought into reducing the lines of code that I as an application developer need to write. Brilliant! My stuff can be easily tested by applying DI principles and this makes me happy as it takes less effort to make the end client happy.
I have access to all of the services on the JEE platform, including transactions, naming and management and can use it as is appropriate to the task at hand. EJB is also a way of doing the same thing. If two things do the same thing, then why would you want to use them both?
I have read a lot of opinions on this question (actually, most have been on which is better, which is meaningless in this context), and have come to the conclusion that I don’t. The problem space is such that you get no additional benefits in tying the two together.
Spring is a platform, an over-arching container, a way of structuring applications and a tool set. EJB is a component model for developing the business tier that ties in directly into your JEE server. Where they cross over is that they allow your application to access the underlying services in such a way that you don’t deal with them when you write your business code.
You would use Spring to manage your business tier when you want to write a Spring application - ORM templates, Webflow, Web services, Remoting API. You would use EJB when you want to write something like a Seam application - JSF, tying in directly to a business tier that manages your persistence, jBPM for process management etc.
The question is what Style of application are you building - is it multi-tier with clear delineation of function (web tier, business tier, data access tier, anemic model), which is what Spring excels at, or do you want a tighter relationship between your tiers with a framework that manages everything in a much more integrated way (not saying that you can’t achieve this with Spring).
This is what I would term a soft decision - it’s less about technical merit and more about the vibe. Where software design meets gut feel.
Sticking EJB into a Spring app is clunky. It does not sit well. Even the stuff that you may have considered EJB for in that past have equivalents in this new world. Remoting (largely out of favour in preference to WS), listening on the end of JMS queues (which I like MDBs for) have nicer corresponding elements that sit better in Spring.
The application style is up to you at the end of the day. Whether you like the full prescribed JEE stack using EJB, or mix and matching the frameworks that you are productive in with Spring, run with it. Just keep in mind the problems that each piece of your application is trying to solve, and don’t double up. It will only make your applications unnecessarily complex.
As a side note, my current project has dropped EJB3 from the rest of the (Spring) stack.
Coinciding with our work on the IJTC conference, scheduled for early November, the Dublin JUG will soon be moving off Meetup. This is in order to provide a more complete service to our group members, such as blog rolls, wiki, conference content and group planning. New logo, site, content… An exciting and busy time. Watch this space.
I have worked with a number of different employer-provided UML tools in the past and have often been left underwhelmed. Rational Rose is a complex memory-hogging beast, ArgoUML seems clunky (although I’m happy to work with it at home since it’s free), and older versions of Visio have needed Pavel Hruby’s stencil to provide good, if fairly basic UML support.
Which is why I have been so pleasantly surprised using Visio 2003’s native UML Model Diagram - it has the CASE like features of the others (Java code generation excluded - surprise, surprise) and it “Just Works”. Within half an hour I was happily churning out structure and collaboration diagrams. The defaults are pretty intuitive (4/5) and standard actions such as moving methods between classes/interfaces, and repackaging classes are as simple as drag and drop. Change the structural details of your classes in the Model Explorer and all your diagrams update just the way you expected them to.
Java support is non-existent out of the box (it supports VB, IDL, C# and C++), but the C# native types are close enough that I’m not that fussed.
Credit where credit is due - any tool that makes me this productive also makes me very happy.
The Spring guys have released version 1.0 of their web services framework. The framework contains:
- simplified methods to create contract-first web services (Java classes from XML schemas)
- a clean client-side API
- standardized access to O/X (object to XML) mapping tools like Castor, XMLBeans and JiXB that allow you to marshal and unmarshal XML easily
As we have come to expect, all of these components can be mixed and matched and used as standalone components. After my first look, I’m really impressed. Java web services don’t get much easier than this.
I recently purchased a Pimsleur Spanish language course on audio bookchip. I figured, hey, rather than buying CDs and then ripping them to my hard disk through iTunes and then putting them on my iPod or phone’s MP3 player, I’d save some time by getting it all on a chip and copying what I need. Big mistake.
Everything on the chip is saved in a proprietary DRM format. If I want to listen to the stuff on the chip, I have to use the proprietary player that comes on it. If I want to copy the stuff to iPod, it comes with a converter that automatically puts it onto there through iTunes - converting it all first. The process takes ages! Then, to add insult to injury - when I next plug my iPod in, the stuff I copied will be deleted! Umm, did no one think that maybe, just maybe, I might want to put more mp3s on there while I’m going through ALL 16 HOURS of a language course!?
Want to learn a language on your snazzy mp3 mobile. No can do. There’s no way to get the stuff on there.
Want to use it with your girlfriend? One person at a time. If you had the CDs, you could at least break it down by sharing a CD at a time. On this bookchip, you get 16 hours and no granularity.
I am kicking myself that I bought this rubbish! Buying it on a CD would have given me far more flexibility with how I consume it. I hope that the decision of some of the biggest record companies to release DRM free songs heralds a change in how they treat their customers. This sort of stuff does nothing but tick honest consumers like me off.
I’m so glad that someone has finally come up with a robot that does something constructive. Now if only it didn’t keep chatting away in an annoyingly chirpy Japanese voice while it did it. I can also see a few other problems with the design, but hey, who am I to begrudge genius
Now with tounge out of cheek, every time I see something like this, I get really ticked off. Mostly because this stuff has to get disposed of at some stage, and already there are problems with consumer waste such as TVs, computers etc. Whatever about recycling it at the end of its life (I give it about two weeks before the novelty wears off - almost as long as Billy Bass the singing fish), but this stuff has a huge carbon footprint in its manufacture.
How many {dead dinosaurs|trees} does it take to pour a beer?
Stuff is a lot like food. Once we had very little, so having it was something desirable. Now we have far too much. Paul Graham has written a fantastic essay on this topic.
When I moved countries, it was with one large backpack, a suit bag and one piece of hand luggage that contained a camera, an mp3 player, my laptop and travel documents. Free yourself. Avoid stuff.
In early November, the Dublin Java Users Group along with IrishDev will be hosting the first of what I hope will be many major Java events here in Dublin. The one day Irish Java Technologies Conference aims to deliver the same caliber of content as the larger Java conferences, with an Irish slant, right to our doorstep here in Dublin.
We are currently putting out a call for speakers, so if you are interested in hearing any particular speakers, or talks covering specific topics or technologies related to the Java platform, email myself “jakub _ korab at yahoo dot com dot au” or “info at irishdev dot com”.
Since the advent of dependency injection (DI) as a staple of enterprise development using tools such as Spring or Guice, your code has become a lot easier to test. You no longer need to code up voodoo such as plugging in dummy resource locators or the like based on some random environment variable to tell your code to switch into “test mode”. Everything is a POJO with interfaces as dependencies rather than classes, which means that it can be easily tested as a POJO. Nevertheless, it still surprises me as to how many people don’t know how to do this. Perhaps it is the perception that you need to have a running back end to test a service tier, or that you need the rest of the system to test a web front end. Not so.
Enter the mock object. According to Wikipedia - “mock objects are simulated objects that mimic the behavior of real objects in controlled ways”. And thanks to freely available Java toolkits such as EasyMock and jMock, making them available to your tests is as easy as plugin in a Jar file into your IDE. I’m a heavy user of EasyMock, so what follows is a simplified example of a jUnit test testing the middle tier of your typical DI-based application.
The following example deals with the following classes:
- WorkItem - a simple value object
- WorkItemException - an exception
- WorkItemService - an interface of a middle tier class
- WorkItemDao - an interface to the data layer of our application. This is what we are going to mock up.
- WorkItemServiceImpl - an implementation of that class. This is what we are going to test.
- WorkItemServiceImplTest - our test class
First, let’s get the uninteresting classes out of the way. Our WorkItem is just a bean that gets passed between the layers:
package jkorab.example.mock;
public class WorkItem { int workItemNo;
public int getWorkItemNo() { return workItemNo; }
public void setWorkItemNo(int workItemNo) { this.workItemNo = workItemNo; }}
The WorkItemException is an exception that gets thrown:
package jkorab.example.mock;
public class WorkItemException extends Exception { private static final long serialVersionUID = 1L;}
Now we come to the class that normally sits in the business tier of our application:
package jkorab.example.mock;
public interface WorkItemService {
/** * Trivial method. Given a workItem number > 0, returns a workItem instance. * Used to show how you might test the wrapping of an exception. * * @return WorkItem or null. */ public abstract WorkItem generateWorkItem(int workItemNo);
}
Let’s take a look at the interface of the class it uses to do its work:
package jkorab.example.mock;
public interface WorkItemDao {
/** * Given a workItem number > 0, returns a workItem instance. * @param workItemNo workItem number * @return WorkItem if workItemNo > 0. * @throws WorkItemException if workItemNo <= 0. */ public WorkItem getWorkItem(int workItemNo) throws WorkItemException;
}
Our example is, as is the spirit of most tutorials, pretty contrived. The top tier of our application wants to load a WorkItem, so it passes a work item number to the service tier. The service tier gets the work item, and if it cannot find it, returns null. The DAO on the other hand, gets a work item number and it the number is less than or equal to 0, it throws an exception, otherwise it loads the WorkItem.
Here’s the implementation of the WorkItemService:
package jkorab.example.mock;
public class WorkItemServiceImpl implements WorkItemService { private WorkItemDao workItemDao;
public void setWorkItemDao(WorkItemDao workItemDao) { this.workItemDao = workItemDao; }
/* (non-Javadoc) * @see jkorab.example.mock.WorkItemService#generateWorkItem(int) */ public WorkItem generateWorkItem(int workItemNo) { WorkItem workItem = null; try { workItem = workItemDao.getWorkItem(workItemNo); } catch (WorkItemException workItemException) { // log and continue. we’ll return null. } return workItem; }}
The class here is doing what the interface “said on the tin”. In addition it has a setter so that the DI container can supply it with a DAO implementation. That’s where our hook is that will enable us to test the service without an actual DAO implementation.
The first thing we need in order to write a test class is a mock DAO. This is the component that the service class will call. In addition we will also need a mock control. Think of this as a component that instructs your DAO as to how it should behave - kind of like a way of programming your Tivo/Set top box/VCR (for those who still have one ;)).
MockControl control = MockControl.createControl(WorkItemDao.class);WorkItemDao mockDao = (WorkItemDao) control.getMock(); WorkItemServiceImpl service = new WorkItemServiceImpl();service.setWorkItemDao(mockDao);
The MockControl class is used to get an instance appropriate to the interface we are mocking up. From this, calling getMock() will return to us an implementation of our DAO interface which we then set on the instance of the class we are testing. This would normally be done in the setUp() method of your jUnit test class, so that each of your tests is guaranteed to get a mock instance in a fresh state, which you can then play with.
In our test method, we can then get on with doing some work. First, we tell our DAO exactly how we would like it to behave:
// set the methods that you expect to be calledmockDao.getWorkItem(1); // set the return valueWorkItem returnedWorkItem = new WorkItem();returnedWorkItem.setWorkItemNo(1);control.setReturnValue(returnedWorkItem); // reset the control object to play back our scriptcontrol.replay();
The last line tells the mock control object that the mock DAO is now in a state where the test can be run on it.
WorkItem workItem = service.generateWorkItem(1);assertNotNull(workItem);assertEquals(1, workItem.getWorkItemNo()); // verify that the methods we expected to be called on the mock object// were actually calledcontrol.verify();
The last line tells the control object to check itself to ensure that all the methods that we told it would be called were in fact called. It will throw an Exception if they weren’t causing our test to fail.
The behaviour described above can be used to test the behaviours of your service class under any circumstances. We can mock up the throwing of an Exception, unexpected behaviours, whatever we want. Here’s the full test class:
package jkorab.example.mock;
import jkorab.example.mock.WorkItem;import jkorab.example.mock.WorkItemDao;import jkorab.example.mock.WorkItemException;import jkorab.example.mock.WorkItemServiceImpl;
import org.easymock.MockControl;
import junit.framework.TestCase;
public class WorkItemServiceImplTest extends TestCase { private MockControl control; private WorkItemDao mockDao; private WorkItemServiceImpl service;
public void setUp() { control = MockControl.createControl(WorkItemDao.class); mockDao = (WorkItemDao) control.getMock();
service = new WorkItemServiceImpl(); service.setWorkItemDao(mockDao); }
/** * Checks that a WorkItem will be returned if the class receives a workItem * number greater than 0. * * @throws WorkItemException */ public void testGenerateWorkItem() throws WorkItemException { // set the methods that you expect to be called mockDao.getWorkItem(1); // set the return value WorkItem returnedWorkItem = new WorkItem(); returnedWorkItem.setWorkItemNo(1); control.setReturnValue(returnedWorkItem); // reset the control object to play back our script control.replay();
WorkItem workItem = service.generateWorkItem(1); assertNotNull(workItem); assertEquals(1, workItem.getWorkItemNo());
// verify that the methods we expected to be called on the mock object // were actually called control.verify(); }
/** * Checks that a null will be returned if the class receives a workItem * number equal to 0 rather than throwing an exception. * @throws WorkItemException */ public void testGenerateWorkItemNullValue() throws WorkItemException { // set the methods that you expect to be called mockDao.getWorkItem(0); // set the control to throw an exception control.setThrowable(new WorkItemException()); control.replay();
WorkItem workItem = service.generateWorkItem(0); assertNull(workItem); }}
This is a great way to test, not only because of its simplicity, but also it being future proof. Let’s examine another way of writing the same tests without using mock objects:
WorkItemDao mockDao = new MockDao() { public WorkItem getWorkItem(int workItemNo) throws WorkItemException; WorkItem returnedWorkItem = new WorkItem(); returnedWorkItem.setWorkItemNo(1); }};
WorkItemServiceImpl service = new WorkItemServiceImpl();service.setWorkItemDao(mockDao);
WorkItem workItem = service.generateWorkItem(1);assertNotNull(workItem);assertEquals(1, workItem.getWorkItemNo());
At first glance, coding up an anonymous class looks like less work, but consider the following:
- if your class is more complex than this (and to be honest, most are) then you will end up with potentially dozens of anonymous implementations.
- if the DAO has more than one method, you will end up with a lot of code that does nothing.
- if the interface on your DAO changes then you will end up with a lot of tests that won’t compile, because your classes no longer match the interface.
This just isn’t the case with mock objects. Mock objects are created at runtime, and you only have to define the behaviours that you are interested in. The technique can also be used to test existing code - refactor your dependencies to an interface, use DI or a constructor if this isn’t an option, and voila, a testable class. 100% code coverage, and future-proof. No more excuses.
If you are interested in more info on mock objects check out the MockObjects blog.