I did a silly thing last week. I’ve been avoiding being given a task for the last nine months, and then all of a sudden I ended up volunteering to do it, for all sorts of reasons. The task: work out how to use WebLogic Workshop as a real tool, in conjunction with our other standard practices (like, oh, source control unit tests command-line builds and daily/continuous builds And I’m realizing why I tried so hard to avoid it.
I wrote about WebLogic Workshop in my very first real blog entry, and suffice to say I wasn’t overly impressed with it then. I’m even less impressed with it now. There are some things that I want to be able to do that it just makes bloody hard.
Let’s take them from the top:
Flashback here to the early ’90s. It’s got extremely rudimentary source control integration; commit, add, update, remove. No queries to let you see what needs to be committed, no status indicators in the UI to show changed files, no way to see what’s been updated on the server. I haven’t used an IDE with such a poor level of source control integration since I was doing development in Visual Studio 4.
It gets worse. My preferred way of knowing what needs to be checked in is to do a ‘clean’, then check everything left over. Except that in Workshop, ‘clean’ doesn’t delete everything. Generated artefacts are scattered all over the place; some are generated in every build, others are just a one-off and should be committed. Fortunately, BEA do list what should be left out of source control, deep in the bowels of their documentation; it’s just that it’s a pain to do. And it will be a pain for every project using this.😦
Well, there’s no JUnit support in the IDE. Unusual for a Java IDE; heck, even JBuilder got the message a while back (though it’s still not in their free version). Supposedly that’s coming in the next version (though I won’t hold my breath).
I got all excited because I found this article on Unit Testing WebLogic Workshop 8.1 Applications Very promising title. Too bad the author doesn’t realise what unit testing actually _is_. Still, I file it away as a possible method of doing integration testing. Instead, I focus on an old fall-back: running unit tests via Ant build scripts. Which gives us a lovely little segue into the next section.
Command line builds
I’m a big fan of repeatable builds, triggered from a command line. As Jon Eaves points out there isn’t really any excuse not to be able to do this. My personal goals are simple: check the project out, then run one (simple) command to build the damn thing. Oh, and have it work.
The aim here is to produce a lowest-common-denominator for builds. IDE-triggered builds are fine for individuals working largely by themselves, but for teams, it’s too fragile an approach. In general, IDE-triggered builds are extremely sensitive to IDE options. Not a problem with a simple command line build.
Being a Java guy, my command-line-build tool of choice is Apache Ant”:http://ant.apache.org/. Now, a while back I got “really excited about Ant 1.6. Now, Workshop does have Ant support; in fact, it uses Ant extensively internally. Unfortunately, it uses Ant 1.5.3 (in 8.1SP2, anyway… SP3 uses Ant 1.5.4). sigh So much for the lovely common build scripts we’d built up over the last six months. Who says that reuse is important anyway (besides my manager, usually in my performance reviews)?
Still, Ant 1.5 isn’t the kiss of death, and I can live with it. So I configure my Workshop application to first:
- “export” the build script
- tell Workshop to use the exported build script, instead of auto-generating one each time.
I go and run the application build script from the command line and it works. Woo-hoo. Little do I know the trouble ahead…
Now, a Workshop “application” consists of several “projects” (really, sub-projects). It’s an advised “best practice” to have a sub-project for each aspect of the application, separated by architectural layers. So one sub-project for POJO code, another for the EJBs, another for the web app side, and so on. The POJO project is the one I’ve got a lot of interest in, because I would like to see the normal standards and practices we have for Java projects apply to the POJO project. In particular, this is the one I want to have unit testing around (I’m willing to settle for integration-level testing of the other parts).
So… first, I fire up the POJO project in Eclipse (Workshop is reasonable as a pure Java IDE, but I can’t work without decent refactoring support these days). This I can do quite happily, though my machine is nearly groaning under the memory load. I add a couple of simple unit tests, run them in Eclipse, and see the green bar. Fine. I then replace the rather ugly build script that Workshop generated with a simpler one (just doing compile and package at the moment), test it in Eclipse, duck back to Workshop, and test it there. So far so good. And I do it from a command prompt to make doubly-sure. Things are looking good for now.
I add a <junit> task. Works fine in Eclipse. Works fine from the command line (after wrapping it in a batch file to set the classpath to include junit.jar). Barfs all over the place in Workshop.
So, I say to myself: just need to put JUnit on the classpath for the Workshop builds. Should be easy, right? There’s even a section in the property page, back where I set up the use of the build script in the first place, where I can tell it what JARs to put on the classpath. Except it doesn’t bloody work. It doesn’t transfer the JARs to the Ant classpath when it runs. And it’s doing something really weird, because I couldn’t even create a customised version of the JUnit task, with a correct classpath.
In the end, I said “stuff it”, put in a check to make sure JUnit was present before doing the unit tests, and moved on. I’ll have unit tests from the command line, but not from inside Workshop. No biggie.
So, now I go back to the “application”-level build, and run that script (remember, I was working on the POJO sub-project just then). Damn… same problem; it doesn’t see the JUnit library, so it doesn’t run the tests. But JUnit’s on the system classpath for the build (thanks to another wrapping batch script). It turns out, after a lot of digging, that the custom Weblogic task (*wlwbuild*) forks a new Ant process per sub-project, using a new environment without the system classpath I had so carefully setup.
Let’s tackle this from a different angle
The custom WebLogic task doesn’t add too much value; it builds the various sub projects (in the right order), and packages. I think I can do those by hand. Because the application-level build script isn’t reused by Workshop, I can use Ant 1.6 and the ‘subant’ task, so I whip that up quickly. POJO project builds fine… EJB project barfs.
After a bit of exploring, I find out that the EJB project uses the WebLogic ‘ejbc’ task. This needs weblogic.jar on the classpath… except it is, as part of the taskdef AND as part of the task invocation. It even gets most of the way through the build, only to end up complaining that it can’t find a resource bundle in order to display a log message. Uh???
If you want to see this, it’s simple: create an EJB project in a Workshop application, export the build script, then run it from the command line (with a blank classpath).
Now I could solve this by putting weblogic.jar on the system classpath for the build. But Ant 1.6 and WebLogic don’t co-exist on the same classpath very nicely, thanks to BEA’s approach of including everything including the fragging kitchen sink in the JAR. I ended up solving it by stripping the i18n resources it wants out into another smaller JAR and putting that on the classpath. Okay, now the EJB project builds, both by itself and from the application build script. But the Web project is broken.
And oh boy is it broken. A lovely “Exception in initializer” error message. A quick check shows that this occurs under Ant 1.5 as well, so it’s not something special. Again, you can see this for yourself by creating a Web project inside a Workshop app, exporting the build script, and running it from the command line. I have no idea how to fix this one.
In the end, I gave up. My application build script now has a call to the POJO build script (so I get the unit tests running), plus a call to the ‘wlwbuild’ Weblogic task that can wave the right rubber chicken over the project to get it to build. It’s a little redundant, but this was just too draining an experience. I’ll save my passion for venting on the poor unsuspecting BEA support resource assigned to the defect report (aka ‘support case’) that I lodged. At least I’ve got a command-line build.
The daily builds, at least, were easy. CruiseControl is a doodle to set up if you’ve got a decent Ant script, which by now I had something vaguely resembling the same.
So where was I?
After two days hammering at this problem on and off, I had a solution. It’s not one I even remotely like (the mojo of the ‘wlwbuild’ task isn’t too my taste), and there’s too much uncertainty for me in exactly what is going on behind the curtains, but at least it does cover the bases. Now all I have to do is document how to do this for the next unsuspecting project to come along…
What I would really like to do, however, is find the BEA engineer or marketing person who decided that “exporting” ant scripts that don’t bloody work when you use them from outside of Workshop was a good idea. I’m going to have a fond daydream for a while of educating their developers on the meaning of the word “export” with a copy of the expanded Oxford English Dictionary, attached to the end of a piece of 4×2.
It’s rather ironic, you know. Suncorp is interested in using Workshop to make it easier for programmers not overly experienced in Java to build apps. Somehow, making life harder for programmers who are experienced in Java solves that problem, but I need someone to explain exactly how to me.
Anyway, tomorrow’s another day… I get to tackle the workflow designer tomorrow! Fun stuff.
 The project-level build scripts are reused by Workshop if you tell it to. The application level build script can not be reused by Workshop. I guess consistency would have been too hard to manage. Still, it meant I could use Ant 1.6