Sunday, 4 February 2007

Complex expectations in EasyMock made easy using JSP EL

Setting up expectations in a mock framework like EasyMock is usually straightforward when dealing with simple types like integers or strings. But from time to time I run into situations when things become more complicated. Consider the following example.

We have a class Customer that has properties like name and address, but also a bunch of other things. We now want to test a method that populates the phone number field from some phone number directory. This test code could look something like this.


public void testPopulatePhoneNumber() throws Exception {
Services services = createMock(Services.class);
Customer loadedCustomer = new Customer();
loadedCustomer.setUserId("alb");
loadedCustomer.setFirstName("Al");
loadedCustomer.setLastName("Bundy");
// Set other properties
Customer saveCustomer = new Customer();
saveCustomer.setUserId("alb");
saveCustomer.setFirstName("Al");
saveCustomer.setLastName("Bundy");
saveCustomer.setPhoneNumber("555-SHOE");
// Set other properties
expect(services.loadCustomer("alb")).
andReturn(loadedCustomer);
expect(services.lookupPhoneNumber("Al", "Bundy")).
andReturn("555-SHOE");
services.saveCustomer(saveCustomer);
replay(services);

CustomerManager customerManager = new CustomerManager();
customerManager.populatePhoneNumber("alb");
verify(services);
}


(For simplicity I have a single interface for all sorts of good stuff, which of course wouldn't happen in a real system. Don't start building your own enterprise CRM system based on this. :-) )

The problem here is how you verify that the correct customer object is being passed into saveCustomer(). In this example EasyMock would use the equals() method of the Customer class to compare the expected object with the actual object. This means that to make all sorts of test cases work you would have to make the equals() method compare every single field in the class. Maybe this is not what you want. Maybe you want two customer objects to be considered equal if they have the same user id. But in this way the test cases have sort of hi-jacked the equals() method. Also you have to set up a lot of properties in the test cases and you get big equals() and hashCode() methods.

So I came up with the idea that you could use JSP EL (expression language) to write expressions that will make an assertion that the object is as expected. Writing an argument matcher for EasyMock that does this turned out to be pretty easy. Using this the expectation for saveCustomer() would become like this:


services.saveCustomer(assertBean(
"${bean.phoneNumber == '555-SHOE'}",
Customer.class));


Also you don't need the saveCustomer object any longer and the only properties that you have to set in the test case are those that actually has something to do with the test.

A small problem with this approoch though is that refactorings of the objects that are referenced within the EL expression will break the tests.

I have put up a small web page with the source code if you want to try it out at http://www.nilin.se/java/beanassert/.

Saturday, 20 January 2007

Platform for Internet based desktop applications

Lately some people have been predicting that applications that are installed locally on a user's computer are on their way out and will be replaced by online applications. When someone wants to e.g. write a document he surfs off to his favourite word processing site instead of starting MS Word.

There are obviously benefits with this approach.

  • No need to install local copies and keep them updated and functional.

  • Easier to switch between vendors when you don't have to make an upfront investment in a sofware package. (Although I don't doubt that vendors will do everything they can to lock users in..)

  • Software piracy should become more difficult


Currently the best example is probably Google Docs & Spreadsheets. It's an impressive piece of Javascript. But is Javascript really the platform we want to use for implementing quality online software? These sorts of things were clearly not the intended use for the language.

Maybe it's time to bring back Java applets from the dead and brush it up a bit? If online applications are going to be a success I think we need something better than a scripting language on steroids.

Saturday, 13 January 2007

Configuring a webapp

One thing I miss in J2EE webapps is a good way to configure the application outside the .war file. I want to be able to ship a .war file together with a properties file that the user can edit without having to unpack and re-pack the .war file. I also want to be able to deploy multiple instances of the same webapp in a container. Each having its own properties file.

There are a number of ways for a webapp to access properties.


  • A file under the web application root using ServletContext.getResource(AsStream)(). The problem with this is obviously that the file is inside the .war file.

  • Through the class path using Class.getResource(AsStream)(). Here you can access files outside the .war file. But there is a problem finding out what file to actually load in a particular webapp. At least if you use the init() method of a servlet. If you deploy several instances of the same webapp the thing that will be different is the context path that they are deployed under. And this information is only available in the HttpServletRequest object, not in the ServletContext.

  • Through system properties. This has the same problems as using the classpath and it may also not always be possible to set system properties parameters when starting the jvm.



I have installed a number of web application where I have had to find a property file deep inside the application server's deployment directories and edit it. Is there really no better way?

Saturday, 30 December 2006

Why WebMethods sucks

This is my very first blog post, ever. I feel I need to do some public complaining and get some thoughts out of my system that has been nagging me for a while. Maybe I'll continue to write some more posts, maybe even some positive ones. :-)




The future is bright, the future is SOA

In the last project for my previous employer I was unfortunate enough to be doing some development in WebMethods. WebMethods is a so called EAI platform, Enterprise Application Integration. It is riding the SOA storm trying to be the magic glue that will connect all the different systems in a company by drawing some bubbles and connecting them with some arrows.


The thing is that to connect different system and making them talk to each other you need business logic. And that business logic needs to be developed. That means WebMethods is actually an application server with a built in development environment. And in this development environment they have taken SOA to places it should never have gone.


Over the years a lot of people have done a lot of thinking on how to develop complex business logic. There is a lot of knowledge out there on how to use object oriented design to make software that is maintainable, understandable, testable, scalable, you name it. Well, WebMethods think they have a better idea. Let's throw all of that overboard and use services instead.




At your service

In WebMethods all code lives in services, which is analogous to functions or methods in programming languages. These services take one input parameter, a document, and returns one output parameter, another document. Or so it seems.. what actually happens is that you get a bunch of name/value pairs (where the value can be sub documents, arrays etc so it kind of maps to an xml document) in a bucket called ”the pipeline”. In your service you modify the pipeline, add and drop fields, and whatever is there when you're finished is the output document. The best thing is that there is one single pipeline that travels around from service to service so what you really have is a big set of global variables. (I learned in school that global variables is a bad thing, but that must have changed since then..) On more than one occasion in my team we were experiencing mysterious bugs because some data from some service that didn't clean up after itself properly popped up. You thought you were sending in a null parameter (by not assigning anything to a field) but there was old data there with the same name.


A service can be written in different ways. One way is in Java. So isn't that object orientation for you..? Well, not really. You don't get to write your own classes. You get to write the body of a static method that will be put in a class together with other static methods. And you still have to use the pipeline. So, sorry, no encapsulation of functionality into different classes.


The WebMethods way to write a service however is to use their own little toy language, Flow. It's one of those languages that a non programmer is supposed to be able to use by just dragging and dropping stuff with the mouse. Making something complex easy that way has failed before and it's not working now either. You have the same constructs as in a real programming language (if, while statements etc), just not as flexible and with little pictures instead of text. Writing even the simplest things gets complicated and hard to read. And since making and calling sub services is so complicated you get a massive amount of code duplication. Adding to the bad maintainability of the code.


And don't start thinking about things like automated unit testing or other good practices. You're locked in WM land now, and there are no such things.

Ok, so we have a development environment where it's just horrible to develop. But a development environment is more than just writing code. You also need things like version control, build and release management. The way that you want to work is that you start by getting the latest version of the code base you're going to work on. Do your changes, test it and then commit things back to the version control system. When it's time for release you check out the latest code and build yourself a release. (At least that's the way I want to work) Well, that's not the WebMethods way..


The WebMethods way is that you have a development environment where you develop. Then when you want to put what you just developed on some other environment you use the WebMethods Deployer application. No need for version control here.. All developers are supposed to be working on the same development environment, which of course leads to all sorts of chaos. If you still insist on putting something into version control you can export packages (the things that services are organized into) and check them in. They are however binary packages so forget about merging, branching etc. You also need to keep track of what actually needs to be checked in yourself. Since all of this is too cumbersome it didn't happen very often in my team that things were actually checked in.


The Deployer application we didn't really use either because it was extremely slow and buggy. We ended up exporting/importing packages between environment resulting in all sorts of confusion on what version was where. And WebMethods itself didn't help since it had a tendency of messing things up in an environment when importing packages.



Models

So is there nothing good in WebMethods? They actually have one pretty nice idea in something they call “Models”. A Model is where you define a business process. A process that takes a long time to run. And with “long time” I talk about days and maybe even weeks. The operational staff needs to be able to monitor each process, for example when a customer calls customer service and wonders why the ADSL connection he ordered a week ago isn't working yet. Maybe they need to phone up some other department or company to ask why the installation guy hasn't been to the telephony station to connect the cables yet. Maybe they need to re-execute some part of the process. With Models they get a GUI where they can see the process and do stuff with it.


A model consists literally of bubbles and arrows that you draw up. Each bubble is a step in the process and consists of a service that holds the code for the step. The arrows has conditions that dictates which step in the process to execute next. You can also define events that must happen for a step to execute (for example that an answer has been received from some external system). Events are actually documents that you “subscribe” to from a system wide message broker. A pretty crappy (and very error prone) event dispatcher.


So Models is a nice idea but the implementation of it, together with the rest of the WebMethods nonsense makes it a nightmare to work with. Is there nothing like this for the Java/J2EE platform? I can envision a pretty nice framework where you implement a special interface to make classes that are process steps. In the process you pass around some JavaBeans container that is easy both to persist and to edit in a GUI when needed. Someone must have written something like this??


That will be the end of my whining session. I'll skip talking about how buggy and unstable the system is, how much resources it uses and stuff like that. And I really don't want to talk about the Workflow module.. brrr...