java hosting


JavaRanch Journal
Volume 6, Number 1 (September, 2007)
Managing Editor: Ulf Dittmer

Inaugural 2007 Issue!

JavaRanch Newsletter Articles in this issue :
GPL Java Marcus Green
Printable Version
Better Enterprise/Network Monitoring with Component Diagnostics Paul Wheaton
Printable Version
Web Services Authentication with Axis 2 Ulf Dittmer
Printable Version
Dependency Injection and Unit Testing Christophe Verré
Printable Version
Top Book Reviews Jeanne Boyarsky,
Jason Menard
Printable Version
Interesting stuff elsewhere on the Ranch Ulf Dittmer
Printable Version

WIRE
GPL Java

GPL Java

by Marcus Green

In June 2006 Sun announced that it would be releasing the Java source code under the Gnu Public Licence. Java has always been freely available to download but it has come under Suns own licence. This meant it could not be freely bundled with Linux distributions and it added a slight overhead to any ideas of simply giving it away. There had been considerable debate as to what licence Sun might use and the choice of GPL caused some controversy. The key to the GPL is that anyone can give away or sell the software but the person they give away or sell it to receives the same rights, i.e. they too can sell or give the software away. Of course, actually selling free software is quite a difficult task, but the GPL does not actually forbid the commercial sale of software.

The GPL announcement was as much about a change in mindset as about the practicalities of obtaining Java. It means that in the future Java will almost certainly be bundled with every complete Linux distribution and it will be possible to give it away just about as you please. This new licence adds to the reality of portability of Java. In the past, although Java was available for free download it required a little expertise and understanding for it to be usable under Linux. I have wasted several hours of my life attempting to get Java configured to use Applets with Netscape and then Firefox under various Linux distributions and I'm a relatively expert Linux user. Previously, when a programmer was choosing a language for Linux development they might choose Perl or C/C++ because they could be safe in the knowledge it would be "available out of the box", in the future they will be able to make that assumption about Java.

Although the GPL announcement promises great things in the future the current and near term reality is a little different. Even though the announcement was over a year ago there is still no binary version of GPL Java for you to download. The source that you can download is effectively the same as Suns JDK 7 and the feature set for that is not even close to having been finalised. According to one estimate, Java 7 and thus the GPL version of Java might be available at the start of 2009. I suspect that the new features of Java 7 will be fairly minimal as Sun and the other developers will be concentrating on the work necessary for the GPL code.

On reading that you might be asking yourself why, if Sun has the source code they don't just compile it up right now and make the GPL version available as a binary download. Part of the problem is that certain parts of Java come from third parties and cannot be released under the GPL by Sun. As a result a significant amount of work has to be done to re-write these bits of code and to test and integrate them into the main Java distribution. I downloaded the openjdk source code and building it is not for the faint hearted. Under windows it appears to require Microsoft Visual Studio .NET 2003 Professional plus the Cygwin utils to create a Unix like environment. In the meantime you can download "snapshot" builds of JDK from http://download.java.net/jdk7/binaries/. It's probably an indication of just how early these builds are in that the readme.html file that ships with the snapshot is actually the same file as in JDK 6.

Despite the delay between announcement and availability of GPL binaries the use of the GPL licence changes the playing field, it sets down a market that says "Java will be everywhere". If that sounds a little unlikely it is worthwhile looking at the broader picture of the world of Java. It's tempting to think that Java is an important programming tool, but just one of many. If you treat Java as the platform itself, in the same way as people look at operating systems, Sun can spin the story in a very interesting way.

Java Everywhere

According to Jonathan Schwartz of Sun "Few folks, at least outside of Sun, understand how pervasively successful the Java platform, and the community supporting it, have been over the past decade. But Java runs on more devices than Microsoft Windows, Linux, Solaris, Symbian and the Mac combined. Nearly 4 billion devices at this point, from smart cards to consumer devices, DVD players to set top boxes, medical equipment, all the way up into the majority of the world's transactional systems and 8 out of every 10 cellphones sold. The Java platform is, already, a global standard."

Read that again, "more devices than Microsoft Windows, Linux, Solaris, Symbian and the Mac combined". Even allowing for industry hype and plenty of those machines being very low spec systems you are unlikely to program for it is still a very impressive piece of market share. Think of that if anyone tells you that C# or python is the future. The GPL announcement also makes some of the other Java players feel a little more relaxed. It is widely rumoured that IBM has more programmers working on Java than Sun, but they have always been a little nervous that Sun seemed to have control over its direction and development. Under the new GPL licence Sun will still have considerable control over Java because they will control the ability to use the name Java. Thus if you "fork the code", i.e. create a new version based on the GPL code that differs from Suns version you will be able to give it away, sell it and use it as you can any other GPL code, but you won't be able to call it Java. You will have a tough time getting people to adopt your forked version as people are used to the comfort and security of the Sun version for the last 10 years. However if push comes to shove a big organisation like IBM has a greater comfort zone with the GPL and less reliance on the goodwill of Sun.

Java may no longer be the shiny new technology but it is the entrenched standard, and is likely to remain so for a long time.

Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Better Enterprise/Network Monitoring with Component Diagnostics

Better Enterprise/Network Monitoring with Component Diagnostics

by Paul Wheaton

And when I say "Enterprise" I do mean a collection of servers and application components, although the "U.S.S. Enterprise" does have a cameo!

Most server based applications installed today have no system monitoring. The way to tell if the system is down is when the phone calls start coming. Sometimes at home. This sort of thing can really put a damper on the pay raise department.

And this topic gets richer - when you have to do an emergency upgrade, how do you know something you changed didn't screw up the production system in a whole different way? Phone calls again? More pay raise dampening.

A collection of simple system monitors and diagnostics can help you to be sure that your application is installed correctly and currently functioning correctly. And when there is a problem, not only can you be notified immediately, you can view the information to find out where, exactly, the problem is. If the problem is fixed quickly, or fixed before anybody notices, this bodes well for the pay raise stuff.

Nagios is a popular tool for doing a variety of system monitoring, but in my experience, Nagios is used almost exclusively for monitoring hardware. So if your application can no longer talk to the database, nagios thinks everything is just fine. The solution is to add some simple stuff to your app that you and nagios can use to make sure everything is okay.

A simple servlet is a great way to go for this sort of thing. A diagnotic can return something like "OK" or "FAIL" so any web browser can run a diagnostic on a component. Plus, nagios (and similar products) are able to exercise web pages too.

In "Star Trek: The Next Generation", Picard will tell somebody to run a "Level 3 diagnostic" for some part of the Enterprise. It turns out that the writers of this show have worked out what, exactly, that means. The following is an attempt to use their terminology to fit the needs of server development. Please note that level 1 and level 2 diagnostics require shutting down the application. I think that this sort of thing is better represented by testing, so I've left those out.

Level 5 Diagnostic

    Select a few things to do that can complete in two seconds or less.
    Configure nagios to exercise this diagnostic about once every two minutes.
    The first line of text returned must be "OK" or "FAIL" for nagios.
    Additional human readable text would be nice.
    Some things that might be exercised:
      read from the database (verify that communication with the database is funtioning)
      ability to put a NO-OP message into a JMS queue (verify that JMS is functioning)
      make sure all JMS queue sizes meet expected parameters
      verify that app can read and write to the file system (testing for permission problems and file handle problems)
      number of objects in memory meets a threshold
      number of objects in the file system meets a threshold
      certain files (logs?) are not getting too large
      certain recent activities are within "normal operating parameters"
      HTTP server is serving a tiny web page
      recently logged error or warning
      is data current?

Level 4 Diagnostic

    select a rich list of things to do that can complete in 30 seconds or less.
    Configure nagios to exercise this diagnostic about once every two hours.
    The first line of text returned must be "OK" or "FAIL" for nagios.
    Additional human readable text would be nice.
    Some things that might be exercised:
      exercise the Level 5 Diagnostic for this component
      check something in the Level 5 diagnostic list above that could not fit into 2 seconds
      ping components the app depends on (verify that the network is functioning between the two components)
      exercise all JMS queues
      FTP read/write
      exercise EJB interface
      exercise MDB interface
      exercise SOAP interface
      exercise RMI interface
      examine JDBC driver version
      exercise a sophisticated algorithm

Level 3 Diagnostic

    select a rich list of things to do that can complete in 5 minutes or less.
    Configure nagios to exercise this diagnostic about once every day.
    The first line of text returned must be "OK" or "FAIL" for nagios.
    Additional human readable text would be nice.
    Some things that might be exercised:
      exercise the Level 4 Diagnostic for this component
      check for when licenses expire for third party products
      exercise a workflow.

Needs of the real world are a bit more than in star trek. A few more diagnostics for the repertoire:

Ping

    Configure nagios to exercise this diagnostic about once every 30 seconds.
    Just return "OK".
    This shows that the network and most systems are functioning and that the component is not locked up.

Installation Diagnostic

    Called by the person installing the component (not by nagios) immediately after installation.
    Recycle stuff from the level 3, 4 and 5 diagnostics.
    Check to make sure jar file code can be exercised.
    Called as needed by developers and system operators (not by nagios).

Status page

    Called as needed by developers and system operators (not by nagios).
    This might show:
      a detailed list of which systems are functioning correctly and which are not so good
      log data
      the version number for the jdbc driver, the app server and the java version
      the current sizes of JMS queues
      the number of servlet requests

If you implement this servlet only with ping, you have made a big leap. Calling this ping, even manually, will verify that your component is not locked up and that the network is functioning at least in part. If you later connect nagios to the component ping, you can probably find out about a problem with your component long before you get that first call from a user of the component.

Overall, implementing all aspects of this servlet would probably take less than a day. Connecting it to nagios would take about an hour. And then ... if there ever is a problem, you should be able to resolve the problem about 20 times (maybe 100 times) faster than without it.

Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Web Services Authentication with Axis 2

Web Services Authentication with Axis 2

by Ulf Dittmer

Last year I wrote an article on Web Services authentication. At the time Axis 1.x was used for the examples, but by now Axis 2 has been released, and I want to talk about the changes that this new version brings about. The first article is referenced repeatedly, so you may want to skim it at least before proceeding with this one.

An important improvement in Axis 2 is that WS-Security is now more tightly integrated with it. It used to be that the WSS4J library (which implements WS-Security) was a separate project, and needed to be added manually to an Axis installation, but no more. An Axis module called Rampart wraps the WSS4J functionality, and can be added to a base Axis installation with little effort.

Because WS-Security is so readily available now, it should be the preferred method of authentication. HTTP authentication as described in the first article can still be used (since Axis is implemented as a servlet in a web app), but it should be considered obsolete and be phased out. I will not discuss it here. Nor will I address the Tomcat Realm integration, because nothing has changed in that regard.

I will present two kinds of WS clients, one using the SAAJ API which was also discussed in the first article, the other one using Axis own API. Axis 2 no longer supports JAX-RPC, so that client is missing here (JAX-RPC is being replaced by JAX-WS, but that's not yet supported by Axis).

Preparation

A couple of steps need to taken before we can experiment with authentication.

The example files discussed in this article can be downloaded here: axis2-auth.zip

Axis 2 needs to be installed and 'happy'; this can be checked on the Axis installation home page (http://localhost:8080/axis2/) under the Validate link. Also, the AXIS2_HOME environment variable needs to set to the directory where the Axis distribution is installed.

Next, the WS-Security module Rampart needs to be installed. For this, copy the rampart-1.1.mar and addressing-1.1.mar files that are part of the example download to the WEB-INF/modules directory and restart the Axis web app. Now Rampart should be listed on the Axis Admin page (http://localhost:8080/axis2/axis2-admin/, default username is 'admin' with password 'axis2') under Available Modules.

Finally, the example web service must be installed. Copy the FibonacciService.aar file into the WEB-INF/services directory and once more restart Axis. FibonaciService should now be listed under Available Services, and it should report that rampart-1.1 is an engaged module for it. (Alternatively, the service archive file can also be uploaded through the Upload Service link on the Admin web page.)

Example

Now we're ready to play. Open a command prompt in the directory containing the examples, and start the tcpmon application by typing ant tcpmon. This will show the SOAP requests and responses in a convenient way.

Then run the SAAJ client by typing ant test-saaj -Dn=15 -Dport=8079. The 'n' parameter is the input to the Fibonacci function. You can choose a different one, but then the result will not be 610. The port 8079 is the one used by the tcpmon tool; use 8080 if you want to go straight to the Axis web app, thus not monitoring the call. (Note that the SAAJ client also logs the request and response to the console; I've not found a way to turn that off.)

All the interesting WS-Security information is in the wsse:Security element that's part of the SOAP header. It can have several child elements; in this case, wsu:Timestamp and wsse:UsernameToken are present. Why these, and what do they mean? WS-Security can perform 4 different actions: Timestamping, Authentication, Encryption and Signature. Here, the first two are used. A timestamp is used to indicate how long the supplied credentials (here: the username/password) are valid, and the service is supposed to reject them if it thinks that they are too old. Since we're focusing on the authentication, I'll not address timestamps in any more detail. They're optional in any case.

The username token essentially consists of the username and the password, which is digested in this case (meaning it can't be recovered should the message be intercepted).

The actual body is rather short, carrying the calculateFibonacci call with parameter 15. The response carries no WS-security information, just the calculateFibonacciResponse with result 610.

<?xml version='1.0' encoding='UTF-8'>

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
        <wsse:Security
            xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
                    oasis-200401-wss-wssecurity-secext-1.0.xsd"
            soapenv:mustUnderstand="1">

            <wsu:Timestamp
                xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
                        oasis-200401-wss-wssecurity-utility-1.0.xsd"
                wsu:Id="Timestamp-6557466">

                <wsu:Created>2007-04-30T18:29:15.687Z</wsu:Created>
                <wsu:Expires>2007-04-30T18:34:15.687Z</wsu:Expires>
            </wsu:Timestamp>

            <wsse:UsernameToken
                xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
                        oasis-200401-wss-wssecurity-utility-1.0.xsd"
                wsu:Id="UsernameToken-4055741">

                <wsse:Username>wsuser</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/
                        oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
                    YaVaSHBtqjGDWoHEdB1zuB3CR68=</wsse:Password>

                <wsse:Nonce>E62qDYhYVoUkJSukJGrvdA==</wsse:Nonce>
                <wsu:Created>2007-04-30T18:29:15.665Z</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>

    <soapenv:Body>
        <ns1:calculateFibonacci xmlns:ns1="http://fibonacci/xsd">
            <in0>15</in0>
        </ns1:calculateFibonacci>
    </soapenv:Body>
</soapenv:Envelope>


<?xml version='1.0' encoding='UTF-8'>

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>

    <soapenv:Body>
        <ns:calculateFibonacciResponse xmlns:ns="http://fibonacci/xsd">
            <ns:return>610</ns:return>
        </ns:calculateFibonacciResponse>
    </soapenv:Body>

The WS-Security options are controlled by the OutflowSecurity element the client config file conf/axis2.xml. The relevant section is this:

<parameter name="OutflowSecurity">
    <action>
        <items>UsernameToken Timestamp</items>

        <user>wsuser</user>

        <passwordCallbackClass>
            fibonacci.PWHandlerClient
        </passwordCallbackClass>

        <!--
        <passwordType>PasswordText</passwordType>
        -->

        <!--
        <timeToLive>10</timeToLive>
        -->
    </action>
</parameter>

It specifies that a UsernameToken and a Timestamp should be generated (the Timestamp being optional, as stated above). Furthermore, it tells Axis which username to use, and which class will supply the password that goes along with this username. Other options (commented out here) include the use of a cleartext password (instead of the digested one that is created by default), and how to specify a longer time-to-live for the timestamp (10 seconds instead of the default 5). The remainder of the file contains the non-WS-Security setup of Axis.

In addition to the conf/axis.xml file, both the Addressing and Rampart Axis module need to be available on the client side. The two APIs differ slightly in how to tell the application where to find these. For the SAAJ client, two system properties (axis2.repo and axis2.xml) must be set, while for the Axis API, these can be set programmatically (and thus are passed in via command line parameters). The build.xml file shows how to do that for both.

The server side config file (resources/META-INF/services.xml) has a similar section that specifies which WS-Security actions to perform, and which class to call to check the password:

<parameter name="InflowSecurity">
    <action>
        <items>UsernameToken Timestamp</items>

        <passwordCallbackClass>
            fibonacci.PWHandlerServer
        </passwordCallbackClass>
    </action>
</parameter>

The Axis API client produces the same request and response; it is run via ant test-axis2 -Dn=15 -Dport=8079.

Files in the examples download

axis2.log - log file written by the Axis client classes

build
    classes - where the compiled Java classes are kept
    FibonacciService.aar - service archive for deployment, created by ant generate.service
    FibonacciService.wsdl - WSDL description of the service, created by ant generate.wsdl

build.xml - Ant build file

conf
    axis2.xml - client side deployment descriptor

log4j.properties - log4j config file

modules
    addressing-1.1.mar - Axis module that implements WS-Addressing
    rampart-1.1.mar - Axis module that implements WS-Security

    (These versions are appropriate for Axis2 1.1; if you're using a different version,
    you should download its associated module files from the Axis2 web site.)

resources
    META-INF
        services.xml - server side deployment descriptor, goes into FibonacciService.aar

src
    fibonacci
        Axis2Client.java - WS client using the Axis API
        FibonacciService.java - the class implementing the service
        PWHandlerClient.java - handles passwords on the client
        PWHandlerServer.java - handles passwords on the server
        SAAJClient.java - WS client using the SAAJ API. It has a commented-out
            section that shows how to set and use arbitrary SOAP headers.

tcpmon.jar - standalone Swing app that can act as a proxy for web service
    requests and responses, and shows those in a structured way
Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Dependency Injection and Unit Testing

Dependency Injection and Unit Testing

by Christophe Verré

In recent years, Dependency Injection may have buzzed into your ears quite often. You may already know that it has nothing to do with drug addiction, but with some cool object-oriented concept. You may also have heard of the Spring Framework, a so-called Dependency Injection container. You might be under the impression that Dependency Injection equals Spring. But no, Dependency Injection is a simple concept which can be used anywhere, without any Dependency Injection container, and especially useful in unit testing. In this article, we will see

  • what Dependency Injection is
  • how to make a class Dependency Injection friendly
  • why Dependency Injection can ease unit tests

Ladies and gentlemen, start your engine !

A simple car

Let's consider a simple example, using engines and cars. We'll leave classes and interfaces empty for clarity. A car has an engine, and we'd like that car to be equipped with JavaRanch's famous MooseEngine™.


We've got engines:
public interface Engine {
}
public class SlowEngine implements Engine {
}
public class FastEngine implements Engine {
}
public class MooseEngine implements Engine {
}
And we've got a car:
public class Car {
	private MooseEngine engine;
}

This is a great car, but it cannot have any other kind of engine, although there are other brands available on the market. We say that the Car class is tightly coupled to the MooseEngine class. There's nothing wrong with it, the MooseEngine™ is great, but what happens if we finally decide to equip it with another engine ?

Programming with interfaces

You may have noticed that the MooseEngine™ was implementing the Engine interface. Other brands are also implementing the same interface. Let's think about it. When we designed our Car class, we thought that a "car" was equipped with an "engine". So let's rewrite the Car class to use the Engine interface instead:
public class Car {
	private Engine engine;
}

Programming with interfaces is an important concept in Dependency Injection. I can already hear you screaming, "wait a minute! That's an interface you're using here, where is the concrete class? Where do you set it? I want my MooseEngine™ in my car". We could set it the following way:
public class Car {
	private Engine engine = new MooseEngine();
}
But would that be useful ? It doesn't look much different from the first example. Our car is still tightly coupled to our beloved MooseEngine™. So? Where do we set (or inject) our car's engine ?

Introducing Dependency Injection

As its name says, Dependency Injection is all about injecting dependencies, or simply said, setting relations between instances. Some people refer to it as being the Hollywood principle "Don't call me, we'll call you". I prefer calling it the "bugger" principle: "I don't care who you are, just do what I ask". In our first example, a Car depended on an Engine's concrete class called MooseEngine. When an class A depends on another class B, and that B's implementation is set directly in A, we say that A is tightly coupled to B. As we've seen in the second example, we have decided to use the Engine interface instead of the MooseEngine™ concrete class to make the Car more flexible. Moreover, we decided not to define the engine's concrete implementation. In other words, we have made our Car class loosely coupled. The Car doesn't depend on any concrete class of Engine anymore. Where do we indicate which Engine to use then ? That's where Dependency Injection comes. Instead of setting the concrete Engine class in the Car class, the concrete Engine class is injected from the outside. How do we do that?

1. Using constructor based injection

One way to set dependencies is to pass the concrete implementation of the depending class to the constructor. Our Car class would become:
public class Car {
	private Engine engine;

	public Car(Engine engine) {
		this.engine = engine;
	}
}
We could then create a Car using any kind of engine. For example, one car using the great MooseEngine™ and another one using the crappy SlowEngine:
public class Test {

	public static void main(String[] args) { 
		Car myGreatCar = new Car(new MooseEngine());
		Car hisCrappyCar = new Car(new SlowEngine());
	}
}

2. Using setter based injection

Another common way to set dependencies is to use setter methods. Using setter methods is recommended instead of the constructor when many dependencies need to be injected. Our car class would then be written that way:
public class Car {
	private Engine engine;

	public void setEngine(Engine engine) {
		this.engine = engine;
	}
}
It looks very similar to the constructor based injection, doesn't it? We would then implement the same cars we have used above the following way:
public class Test {

	public static void main(String[] args) { 
		Car myGreatCar = new Car();
		myGreatCar.setEngine(new MooseEngine());
		Car hisCrappyCar = new Car();
		hisCrappyCar.setEngine(new SlowEngine());
	}
}

Using Dependency Injection for Unit Testing

If you compare the first example of the Car class, and the one using setter based injection, you might think that some extra steps were needed to make the Car class using Dependency Injection. That's right, you had to write a setter method. But you can feel how rewarding this extra work is when unit testing. If you are not confident about what unit tests are, I recommend this Campfire Story on Evil Unit Tests. Our Car example is so simple that it does not illustrate well how useful Dependency Injection is for unit testing. We'll leave cars, and consider the example provided in the forementioned Campfire Story, especially the part on using mocks for unit testing. We have a servlet class using a remote EJB to register animals in a farm:
public class FarmServlet extends ActionServlet {

	public void doAction( ServletData servletData ) throws Exception {
		String species = servletData.getParameter("species");
		String buildingID = servletData.getParameter("buildingID");
		if ( Str.usable( species ) && Str.usable( buildingID ) ) {
			FarmEJBRemote remote = FarmEJBUtil.getHome().create();
			remote.addAnimal( species , buildingID );
		}
	}
}

You have already noticed that FarmServlet is tightly coupled to the FarmEJBRemote instance, which was retrieved via a call to "FarmEJBUtil.getHome().create()". It makes it very hard to test. When unit testing, we don't want to use any database. We don't want to access an EJB server either. That would make unit tests both difficult to execute and slow. So in order to unit test the FarmServlet class smoothly, we'd better make it loosely coupled. To remove the tight dependency between FarmServlet and FarmEJBRemote, we could use a setter based injection:
public class FarmServlet extends ActionServlet {
	private FarmEJBRemote remote;

	public void setRemote(FarmEJBRemote remote) {
		this.remote = remote;
	}
    
	public void doAction( ServletData servletData ) throws Exception {
		String species = servletData.getParameter("species");
		String buildingID = servletData.getParameter("buildingID");
		if ( Str.usable( species ) && Str.usable( buildingID ) ) {
			remote.addAnimal( species , buildingID );
		}
	}
}

In the real deployment package, we will make sure that an instance of FarmServlet's remote member will be properly injected via "FarmEJBUtil.getHome().create()". In our unit test, we will use a dummy mock class to act like a FarmEJBRemote. In other words, we will make a mock class implementing FarmEJBRemote:
class MockFarmEJBRemote implements FarmEJBRemote {

	private String species = null;
	private String buildingID = null;
	private int nbCalls = 0;

	public void addAnimal( String species , String buildingID )
	{
		this.species = species ;
		this.buildingID = buildingID ;
		this.nbCalls++;
	}

	public String getSpecies() { 
		return species;
	}
	public String getBuildingID() {
		return buildingID;
	}
	public int getNbCalls() {
		return nbCalls;
	}
}

public class TestFarmServlet extends TestCase {

	public void testAddAnimal() throws Exception {
		// Our mock acting like a FarmEJBRemote
		MockFarmEJBRemote mockRemote = new MockFarmEJBRemote();
		// Our servlet. We set our mock to its remote dependency
		FarmServlet servlet = new FarmServlet();
		servlet.setRemote(mockRemote);
            
		// just another mock acting like a ServletData
		MockServletData mockServletData = new MockServletData();  
		mockServletData.getParameter_returns.put("species","dog");
		mockServletData.getParameter_returns.put("buildingID","27");

		servlet.doAction( mockServletData );
		assertEquals( 1 , mockRemote.getNbCalls() );
		assertEquals( "dog" , mockRemote.getSpecies() );
		assertEquals( 27 , mockRemote.getBuildingID() );
	}
}

That's it! We've got an easy to test FarmServlet.
To sum up some important points:
  • Use interfaces instead of using concrete classes to illustrate a dependency.
  • Avoid to implicitly set the concrete implementation of a dependency in the class itself.
  • Concrete implementation of a dependency may be set in various ways, including constructor based injection or setter based injection.
  • Dependency injection makes unit testing very flexible.
Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Top Book Reviews

Top Book Reviews

by Jeanne Boyarsky and Jason Menard

It's been a while since the last Journal, so instead of a Book Review of the Month, we present those reviews that have scored a whopping 10 out of 10 horseshoes during the last year.

Mastering Regular Expressions by Jeffrey E. F. Friedl

"Mastering Regular Expressions" takes a great book and modernizes it to include the latest programming languages. The book starts out with assuming you know anything about Regular Expressions -- aside from the concept to be interested in picking up the book.

The author introduces regular expressions through examples and quickly introduces the constructs. The second third of the book goes into the details of how regular expressions are processed. This includes correctness and efficiency issues. The final third on the book goes over the syntax in Java, .NET, Perl and PHP. Tools like grep and awk are described in the text as well.

An alternate title for this book would have been "Thinking in Regular Expressions." Even if you think you know regular expressions, this book teaches you how much more there is to learn. It also teaches you some of the finer points of regular expressions in your favorite programming language along with cross references to the earlier part of the book.

The author uses good analogies to make the text understandable. After awhile, the concepts get so complicated that you have to read it many times to understand. A typically O'Reilly book. I've only had this book two weeks and I've already used it to make me a more effective developer!

reviewed by Jeanne Boyarsky

More info at amazon.com

Release It! by Michael Nygard

Many of the texts on software engineering discuss following some methodology to produce an ideal design. Working developers quickly learn that the ideal is rarely reality and things happen once we release software out into the wild. Michael Nygard's "Release It!" picks up where these other books leave off.

Nygard talks about all the things that can and will go wrong in the finely crafted software we were sure was ready for production. A full two-thirds of the book is focused on capacity and stability issues including patterns and anti-patterns for both. The remainder of the book deals with general design issues as well as maintaining health and status in an operational system. "Release It!" provides many first hand accounts to illustrate his points, beginning with the Exception that grounded an airline, and these stories serve as excellent motivators. It's better to learn from the mistakes of others, and I really appreciated the detail Nygard went into addressing some of these horror stories.

The Pragmatic Programmers have a few "must read" books and "Release It!" is another one. After reading it and heeding its advice, you'll feel a bit better knowing that your software is better prepared for the rigors of production.

reviewed by Jason Menard

More info at amazon.com

Continuous Integration by Paul Duvall, Steve Matyas and Andrew Glover

"Continuous Integration" is part of the Addison Wesley series. This series includes books like "Refactoring to Patterns". "Continuous Integration" definitely meets the standards of this series.

Each chapter describes CI related practices. There is a chapter dedicated to risks reduced by CI including anti-patterns like "It works on my machine." Each chapter ends with questions to get you thinking about CI in YOUR process. I particularly like how the authors address the "CI is good but my project is special" problem.

The authors give examples in different languages including Java, .NET and Ruby. The appendices on resources and tools are very useful. The book goes beyond CI and addresses continuous inspection and deployment. My only problem when reading the book is that I forgot I was supposed to be writing a review. It was so good, I just got caught up in the book!

Do check out the companion website integratebutton.com. It currently contains video examples of three practices described in the book. The materials are presented in slide and diagram format. It reinforced the book nicely because it was like a guru explaining his experiences. It also goes into much more detail than the book has room for on each topic.

This is an excellent book and the website adds to it!

reviewed by Jeanne Boyarsky

More info at amazon.com

WIRE
Return to Top
Interesting stuff elsewhere on the Ranch

Interesting stuff elsewhere on the Ranch

by Ulf Dittmer

Not all the good stuff is in these Journal articles. The Saloon sees lots of insight and wisdom all the time, and the various bloggers on the JavaRanch Radio are also busy turning out quality content. Plus, we've got book authors hanging out with us all the time. So here are a few nuggets you may have missed that should prove interesting to many folks.

Big Moose Saloon

In How do you interview?, ranchers discuss the perennially hot question of what you should ask in a techical interview to get an idea of how good a candidate really is, or whether he's faking it.

The Singleton pattern has a bad rep these days. In If the Singleton pattern is bad, how does Factory help?, members talk about whether Factory is really better, or if there's a greener pasture out there somewhere.

And since Dependency Injection is everywhere now, how does it relate to Factory? Why Dependency Injection is better than Factory? delves into this subject, and points out some differences.

JavaRanch Radio

Lasse talks about Testing for expected exceptions with JUnit. He promises that it's not just a plug for his book, but is actually a subject that has seen some changes in JUnit 4, so it has definite timeliness.

Gregg admits that he pieced together bits and pieces from all over the place in Session Timeout and AJAX, but since nobody seems to have put it all together before in one place, this is your chance to learn how to deal with it.

Finally, David O'Meara creates an image containing rotated text in a servlet on the fly, and streams it to the browser in Vertical text from a Servlet. Being from the upside-down country of Australia, we can forgive David for not reading left-to-right like most of us.

Upcoming Book Promotions

On September 18, we've got Chet Haase & Guy Romain talking about Filthy Rich Clients

On September 26, JavaRanch's Lasse Koskela introduces Test Driven

On October 2, the trio of Vivek Chopra, Sing Li & Jeff Genender dispense the Tomcat knowledge of Professional Apache Tomcat 6

On October 9, Michael Bowers presents Pro CSS and HTML Design Patterns

On October 16, Lynn Beighley covers the latest Head First book: Head First SQL

On October 23, Andrew Stellman & Jennifer Greene answer questions about yet another Head First book: Head First PMP

WIRE
Return to Top