Absolutely impressive…
The wind
October 21st, 2007 — General
TestNG 5.6 is out
April 26th, 2007 — TestNG
Yes, the 5.6 version of TestNG is finally out and contains several new features and a couple of bug fixes for both the core and IDE plugins. The complete list of these can be found here.
One of the noteworthy fresh features of 5.6 that I would like to talk about is the new XML reporter. This reporter provides additional TestNG-specific info that is not available in the JUnit-compatible report. It aims at helping automatic results reporting systems by promoting a consistent XML format, while also offering the foundation for obtaining user-friendly results.
The documentation for this feature along with a sample XML output is available here. You might have noticed that the XML is class-centric. This means, that no matter how you specify your test scenarios, you will always get the output built around the classes whose methods were the subject of unit testing.
As you might have expected, this reporter is included in the list of default listeners so you don’t have to enable it by hand. It’s output will be written in the same directory as the rest of the default reports (the TestNG output folder) in a file named testng-results.xml.
There are however a couple of settings and tweaks that can be used to fine-tune the reporter to best fit your needs, as you might have noticed in the docs. These properties are passed in a JavaBeans style as we will see later.
One of these properties that you might find useful is the fileFragmentationLevel integer. This property provides a way to control the structure of the generated XML files by allowing you to separate the files into smaller pieces if you consider that one single XML file is too big to chew at once.
For the beginning, if you have more than one suite in your tests, you can choose to have the results for each suite in a separate XML file (by setting fileFragmentationLevel to 2). This way, the main file will only reference the suite files, as you can see here:
<testng-results>
<suite url="Suite1/testng-results.xml"/>
</testng-results>
The suite file will only contain the <suite> element with the same structure as before:
<suite name="Suite1">
<groups>
...
</groups>
<test name="test1">
<class name="com.test.TestOne">
...
</class>
</test>
</suite>
If you want to go even deeper with this, you can have your suite test-cases written in separate files, for which you will have to set fileFragmentationLevel to 3.
In this case, besides the previous effects, you will also get the test-cases files referenced from the suite files:
<suite name="Suite1">
<groups>
...
</groups>
<test url="test1.xml"/>
</suite>
and as you probably guessed, test1.xml looks like this:
<test name="test1">
<class name="com.test.TestOne">
...
</class>
</test>
The next question would be “how the hell do I set fileFragmentationLevel and the other properties?”. The docs also mentions this stuff and you should read that before doing anything else. However, I can detail a little bit about the most common ways to configure this reporter.
The first thing you need to know is that in 5.6, along with the other changes, there is also a new method to inject custom report listeners providing fine-grained access to their behavior. The foundation of this is the new -reporter argument that can be passed from the command line. The docs about this are here. This will inject a reporter like -listener would, but it also allows you to set some properties on it.
In our case, if for example we would like to change fileFragmentationLevel and outputDirectory of the XML reporter, we would pass to the command line something like this:
-reporter org.testng.reporters.XMLReporter:fileFragmentationLevel=2,outputDirectory=/usr/temp/results
There is also an Ant equivalent for this type of configuration, and it can be achieved by using the inner <reporter> element, which in our case would be something like this:
<target name="test" depends="build">
<testng ...>
<reporter classname="org.testng.reporters.XMLReporter">
<property name="fileFragmentationLevel" value="2"/>
<property name="outputDirectory" value="/usr/temp/results"/>
</reporter>
...
</testng>
</target>
This kind of configuration can be used starting with TestNG 5.6 for any of your custom listeners, not just the XML reporter. There are however a couple of things here that must be considered. First of all, the types that are currently supported as reporter properties are limited to the following set: java.lang.String, int, boolean, byte, char, double, float, long, short. Besides, as you might have noticed, it might be a little tricky to pass strings containing commas as parameters, although it can be easily worked-around.
Another thing, strictly related to the XML reporter, is that the built-in reporter can only use the default settings, an issue also mentioned by the documentation. You can however inject a new instance of this reporter manually with one of the methods described above (yes, the above code will create a new instance, and it will not configure the default one). However, in order not to get into conflicts with the built-in reporter you have two options: one is to disable the default listeners and the other one is to change the output directory of the manually injected instance (they both worked for me).
Hope you find this useful.
Spring by examples – RMI
November 2nd, 2006 — Java
RMI is just one of the strategies that you can choose from when you want to implement remoting in your Spring application. At the moment, Spring provides support for Hessian, Burlap, RMI, Web services and an own HTTP remoting solution. All of these remoting strategies were designed so they can share a common configuration style allowing you to manage the exporting and accessing method from outside your business code, in the well known non-intrusive Spring manner. This means that Spring offers a POJO-based programming model for both your server and client, no matter which remoting solution you choose. The reference documentation regarding the remoting features of Spring is available here.
For now we will take a look at how Spring handles RMI while peeking into the code of a small demo application. Our example contains a simple delivery service exposed through a DeliveryServiceIntf interface that has two methods for handling Delivery objects. Below is some of the code for these objects.
public class Delivery implements Serializable {
private String requesterName;
private Date deliveryDate;
public Delivery(String requesterName, Date deliveryDate) {
this.requesterName = requesterName;
this.deliveryDate = deliveryDate;
}
...
}
public interface DeliveryServiceIntf {
void newDelivery(Delivery delivery);
List getDeliveries();
}
As you can see, the service interface does not need to extend the java.rmi.Remote in order to be used as an RMI service. Also, it’s remotely accessible methods don’t need to throw java.rmi.RemoteException. This is a Spring enhancement that applies to all it’s remoting solutions, not just to RMI. But this is no reason to get scared, because Spring will manage the invocation failure in it’s own fashion by throwing a org.springframework.remoting.RemoteAccessException. This is an unchecked exception so the client can decide if it wants to catch and handle this exception or just ignore it when it’s occurrence it’s considered fatal. This is however Spring’s recommended approach, but you can also expose traditional RMI implementations with Spring. Actually, this is an important issue that you should consider and analyze when remoting with Spring. While both traditional and Spring-managed RMI clients can access a traditional RMI server implementation exported through Spring, only a Spring client will be able to access a Spring exported RMI service that uses a POJO-based model.
Getting back to our example, we have below the implementation of our service which I tried to keep as simple as possible:
public class DeliveryServiceImpl implements DeliveryServiceIntf {
private List deliveries = new ArrayList();
public void newDelivery(Delivery delivery) {
deliveries.add(delivery);
}
public List getDeliveries() {
return deliveries;
}
}
After we have everything implemented on the server side, we need to configure Spring to export the service through RMI. The following Spring configuration snippet does just that.
<bean id="deliveryService" class="com.test.rmi.server.DeliveryServiceImpl">
</bean>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="delivery-service"/>
<property name="service" ref="deliveryService"/>
<property name="serviceInterface" value="com.test.rmi.common.DeliveryServiceIntf"/>
<property name="registryPort" value="1234"/>
</bean>
This is the point where we can choose which one of Spring’s remoting solutions we want to adopt. In our case we will use org.springframework.remoting.rmi.RmiServiceExporter which will also manage the RMI registry for us. The serviceName and registryPort properties are RMI specific settings that will constitute the information the client side needs to access our service. The URL for the service in this case will look something like rmi://hostname:1234/delivery-service. The serviceInterface property indicates the POJO whose methods will be the subject of RMI invoking and the service property references a bean implementing the business logic of the service.
At this point, having all up-and-running on the server side requires a small amount of effort and it only consists of classic Spring context initialization.
public class RmiServerTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/test/rmi/server/rmi-server-context.xml");
}
}
Now let’s see how does it work on the client side and how should we proceed to access the remote service. Here is actually a little bit easier because everything relies on the Spring bean configuration file, as seen below, while the rest of the code is pretty straightforward.
<bean id="deliveryService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1234/delivery-service"/>
<property name="serviceInterface" value="com.test.rmi.common.DeliveryServiceIntf"/>
</bean>
As you can see, we just need to define the deliveryService bean of class org.springframework.remoting.rmi.RmiProxyFactoryBean. This will indicate Spring that the deliveryService bean will actually be a proxy accessing the remote service at the URL rmi://localhost:1234/delivery-service, and that the business logic of the service will be used by the client through the methods of the DeliveryServiceIntf interface.
Accessing this bean will create a proxy that we can cast to the DeliveryServiceIntf interface and that will dispatch all the calls on this interface to the RMI service. Below is the pretty self-explanatory client-side code.
public class RmiClientTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/test/rmi/client/rmi-client-context.xml");
DeliveryServiceIntf deliveryService = (DeliveryServiceIntf) ctx.getBean("deliveryService");
deliveryService.newDelivery(new Delivery("John Doe", new Date()));
...
}
}
Therefore, the client will not be aware of the fact that the service is running remote and even less about the fact that its method calls are marshaled through RMI. The Spring bean configuration file takes care of these details, so the client code will not be affected if we change the remoting strategy or even if we choose to run the service in-process.
The code for this demo can be found here. The first step is to run ant run-server in order to launch the RMI server and afterwards you need to run ant run-client from another console to start up the RMI client.
Hope this post can give you a basic feeling about Spring’s RMI support. Please feel free to comment on any aspect of this article.
Spring by examples – method interceptors
October 16th, 2006 — Java
Spring is a great Java technology that has become a very popular application framework during the past few years. My intention is not to go through the whole concepts and architectural details of the framework, because that kind of information can be easily looked up starting at http://www.springframework.org. As the article title indicates, I intend to provide hands-on examples showing the minimal requirements to bundle certain Spring functionalities in your Java applications. So, because I will not go into the “what’s under the hood” approach unless absolutely necessary, most of the examples might require the knowledge of basic Spring concepts. Anyway, the basic idea is that you must RTFM before deciding if Spring is right for your application.
The first example is a short look at a simple method intercepting strategy. You can read all about this and the whole Spring AOP API here.The source code for this example can be found here. In the project directory run ant compile run to launch the application.
For the beginning let’s consider that we have the service MyService that that has a method doSomething() performing an operation which takes a long time to execute. Below you can see the (pretty dumb) code of this method.
public class MyService {
public void doSomething() {
for (int i = 1; i < 10000; i++) {
System.out.println("i=" + i);
}
}
}
In order to print out the performance statistics on the method call, we must first implement the interceptor that actually calculates the execution time for this method. To do this we need to implement the org.aopalliance.intercept.MethodInterceptor interface shipped with Spring. This is actually a callback providing access to the actual call of the methods of our service. The JavaDoc for this interface is here.
public class ServiceMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = methodInvocation.proceed();
long duration = System.currentTimeMillis() - startTime;
Method method = methodInvocation.getMethod();
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
System.out.println("Method '" + methodName + "' took " + duration + " milliseconds to run");
return null;
}
}
Next we need to proxy our service in order to obtain an instance whose methods are being intercepted by our ServiceMethodInterceptor. To achieve this, all it takes is a little magic in Spring’s bean configuration file, as you can see below.
<beans>
<bean id="myService" class="com.test.MyService">
</bean>
<bean id="interceptor" class="com.test.ServiceMethodInterceptor">
</bean>
<bean id="interceptedService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref bean="myService"/>
</property>
<property name="interceptorNames">
<list>
<value>interceptor</value>
</list>
</property>
</bean>
</beans>
The key in this XML snippet is Spring’s built-in class org.springframework.aop.framework.ProxyFactoryBean which provides the actual proxying of our service. In order to obtain the desired effect we must set the target and interceptorNames properties for this bean. The target property represents the name of the bean that we want to proxy, which in our case is the myService bean. The interceptorNames property holds a list of bean names that will be used as interceptors for the proxied bean. So, yes, you can define more than one interceptor for your bean.
As everything seems to be packed pretty nice, all we need to do now is to have our service instantiated using Spring and call itâs doSomething method.
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/test/applicationContext.xml");
MyService myService = (MyService)ctx.getBean("interceptedService");
myService.doSomething();
}
}
So we need to look up the interceptedService bean in order to get the proxied service, but if we choose to remove the performance monitor we can simply lookup the initial myService bean.
Normally, after the method doSomething has run, you should see, as the last output line, something like this:
Method 'com.test.MyService.doSomething' took 281 milliseconds to run
Except from the MethodInterceptor Spring also offers other method interception strategies. For example you can choose to handle a method execution right before or immediately after the actual call, or when an exception is thrown during the execution of your method. The reference documentation about these types of interceptors that Spring offers is available here.
Please note that basic performance monitoring can also be achieved by using Spring’s built-in PerformanceMonitorInterceptor. We used this logic just as a sample for method intercepting, but as your intuition might tell you, this is just one of the many things you can do with this feature of Spring. For example, if you need to implement a fine-grained security module, you might choose not to allow the method call to execute if the user does not have rights on the business method. So, basically, you will have to see for yourself how you can use this functionality in your application.
I hope you find this article useful.
Have a happy coding day
.