Sunday, June 22, 2008

Some notes on web services, REST & Fluent Interface. Theoretically we can make use any language to write web service client, & of course that's the exact reason web service was invented offering loose coupling for implementing distributed computing environment for businesses. But there were many requirements (schema definition/validaion, security,performance, service discovery, SLAs,BLAs, language etc..) to achieve high cohesion, hence SOAP, XML, UDDI & WSDL were necessary. I guess for most of integrations these technologies make developer's life un-necessarily tougher & are forced to learn/unlearn these vocabulary.They are all XML-RPC in disguise & may not be much better than the existing binary RPC solutions (RMI,CORBA, COM...). I am leaning towards REST proponents who are arguing that this complexity is not really worth of benefits it offers & is really waste of time, bandwidth & finally money. These are looking similar to EJBs as I am going through this book (considered as first printed book on REST)
If we see the existing web service landscape (I am referring WSDL, SOAP only), most of them are giving SDK for different languages (eBay SDK, Google Data API...) proving that SDK is more important than the WSDL. SDK always beats the SOAP toolkit hands down.

SOAP prevent independent evolution of client & server. For exampleSOAP toolkits provide (Jax-ws,Axis) code generation with strongly typed APIs, even adding new optional parameter, system will break until we generate thte stub again,Which basically diefies the logic of loose coupling.

With REST,HTML forms provide default & hidden variables,Service end point change is effortless, we can have re-directs based on situation & also partition, scale well depending on the requirements.Means don't have redeploy & test specifically for this.

separating reads from writes. SOAP has no inherent support for this, although we can design.
caching GET requests including hardware solutions, Caching @ HTTP always yields better results.
compression: Since REST uses HTTP, you can use compression such as gzip.
No need for additional jars or library
explorability -clicking around a RESTful API in their browser & use right away.
REST architecture serves as the basis for the most biggest and most successful information system the world has ever seen

Cons of REST
security: Though, security considered as weakest area of REST not sure why (HTTPS, authentic)
Tools will make working with SOAP just simple, IDE & tools cannot provide same kind features as SOAP to REST.
(Anyway we had same arguments for using EJB in the past as well)


Here is a sample Java APIs for web service APIs to help out developer community to directly working java instead of WSDL. I noted following points from going through the code.

  • Contains 28 methods & 768 lines


  • Expects user to update the Source code or use the properties file to inject startup values (Namely username, password, AccountID so on & so forth) & is not easy to pass/change these values @ runtime.


  • Uses Exception, RemoteException providing little recovery options from service faults & forcing client code to become ugly, clearing suggesting RuntimeExceptions are better suited here to use.


  • One single class for many APIs, making shpping client API size bigger if we want to deal with single API only


  • No way to see the SOAP XML files that get handshaked b/w client & server.


  • Uses Axis for marshalling/unmarshiling, We have Sun benchmarks suggesting latest jax-ws API/implementaion beat Axis/xfire hands down.


  • The API is not fluent (or user friendly) & does not make use latest JDK1.5 APIs


  • Uses lot of Array values as input/output params making client code uglier
Before providing my solution for this I do understand that I don't have much knowledge of the context (of client applications) using the APIs. So please be adviced I might have over-looked many issues.

I generated stub code using jax-ws APIs & netbeans. JAX-WS is the successor to JAX-RPC. It requires Java 5.0, and is not backwards-compatible to JAX-RPC.Netbeans has amazing plugins for about everything! I also wrote some wrappers around the campaign service API & here is how client code looke in the JUnit test case. (BTW JUnit4 has amazing features with POJO annotations & I guess this unit testing library is the best testimonial of effective usage of the java annotations.)

Now JDK6 users can turn their normal POJO in to web services and deploy it with ease without getting to deal with different web services stack. Before JDK6 one had to download some webservices toolkit and learn how to use

@Test
public void testGetCampaigns() {

List<Campaign>campaigns = new CampaignServiceTemplate() {
@Override
public YAccount getYAccount() {
return YAccount.builder.userName("uyiui")
.password("test123")
.license("uyiuu7687687gg")
.masterAccountID("988533")
.accountId("2086880350")
.build();
}
}.getCampaigns(13897897l,797897l, 89678l);
Assert.assertNotNull(campaigns);
}

Above code definately looks much cleaner easy to use. It makes use of generics, varargs, SOAPHandler java-ws interceptor,template pattern & fluent interface to make code look simpler & robust by validating all the inputs that takes care of all the issues I listed above sample code.

One task which I wanted to avoid was generating the source using tools Axis/jax-ws, if I want to write some adhoc testing I don't think doing in java make really sense. Ruby, Groovy where dynamic class reference options are amazing solutions here.

For stock quote client Groovy code looks something like this.

import groovyx.net.ws.WSClient
proxy = new WSClient("http://www.webservicex.net/stockquote.asmx?WSDL", this.class.classLoader)
quote = proxy.GetQuote('YHOO')
print quote

We, Java programmers are unable to make use of Groovy APIs like this, we will be the losers. Coding can't be simpler/easier than this :-)

But don't get me wrong, Java has a place & will continue to occupy the major portions of software development as Joshua Bloch says "One thing that makes Java such a pleasure to use is that it is a safe language."

So when we stick to Java,fluent interface or easy to use APIs have lot of importance.A fluent interface is a DSL embedded in a language,it consists of a set of classes that have been organized to allow you to write code that nearly reads as English essay. Beautiful Code is often associated with essay-writing.

Reference:

Immutable objects improves the code reliability.

Joshua bloch discusses about the design consideration

Jax-ws faster than Axis - Benchmarks

Java options for writing web service clients

SoapUI has wonderful set of applications & plugins to make web service testinf very easy task. I tried out their NetBeans plug in , It's simply amazing.SoapUI is a great tool for any developer who wants to test web services to verify that they are working correctly.

Good DZone link explaining functional testing using these APIs. I will update my experience after trying these out.

GoAPI -> Good for searching APIs.
Restas Architecture - "
Simpler is better, and REST is generally simpler than SOAP"

Sunday, June 08, 2008

Java Logging Frameworks - why to use sl4j?
One of my friend was asking why should I with sl4j over log4j & java logging. My answer was "because it was written by the same author who wrote log4j & is now adopted by finest java framework authors (Tapestry & Wicket)" sl4j is the best available way to solve logging problems. It's latest & hence best suited for any new projects. This way some decisions are easy & safe to make. Logging is one of the most boring & non-debatable topic. At least for issues like this it's best to follow the best minds. During my initial days of coding I have seen mindless java wrappers over existing logging frameworks without any value addition. Log4j is definitely superior option to standard java logging both in terms of speed & availability of appenders. But when we write client apps or want to make our jar size compact & cannot afford to include log4j.jar java logging might be still better option which is rare case anyway. With log4j , in order to bypass the expensive string concatenation if statement was necessary. It would have been nice if APIs to provide some features that would alleviate things like this, and maybe make it easier to toggle the display of log statements for code readability.
if (log.isDebugEnabled()){
log.debug("Logging " + String.valueOf(a) + "some information :"+someBigEntity.toString());
}

I never liked double if conditions. Less if conditions directly proportional to good code quality.
sl4j utilizes parameterized messaging (like logger.debug("The new value {} is replacing {}.", newValue, oldValue);) & does'nt have class loader & memory leak problem. As JVM is becoming smarter & smarter with every new version, micro bench marking knowledge are becoming totally irrelevant. The experience is becoming baggage & anti pattern most of the time as for micro bench marking is concerned.

Here is one experiment I did with latest JVM with decompilation .

public class JavaLogTest {
// Get status from Logger.isDebugEnabled();
private static final boolean DEBUG=false;
public static void main(String[] args) {
if(DEBUG) {
System.out.println("Performance issue");
debug("Some Big"+"Concatenation here"+"& also creation of objects.... "+new java.util.Date()+" which is not good for performance");
}
debug("testing"+" ! testing again");

debug("testing"+new Integer(10).toString() +new java.util.Date());
}
public static void debug(String str){
System.out.println(str);
}
}

I decompiled the class with decompiler & here is the result what I got;

import java.io.PrintStream;
java.util.Date;
public class JavaLogTest{
private static final boolean DEBUG = false;
public JavaLogTest() { }
public static void main(String args[]) {

debug("testing ! testing again");
debug((new StringBuilder()).append("testing").append((new Integer(10)).toString()).append(new Date()).toString());
}
public static void debug(String s) {

System.out.println(s);
}
}

& the results were interesting;
1. It doesn't make sense to use StringBuffer for appending, JVM is intelligent to make use of StringBuilder which is not synchronized also
2. When we append strings only there is no need to use if statement even with log4j
3. We can take out the code from the byte code (pre-processor directive DEBUG) which can reduce the total jar size
I found scala solution for this was interesting. Dynamic languages indeed bring lot of paradigm shift in thinking!
Bookmark and Share