Search This Blog

Friday, January 30, 2009

Spring JmsTemplate WebLogic

In an earlier blog, I had expressed my concern regarding the JmsTemplate from the Spring Framework and that it promotes a bad design pattern, i.e., where JMS artifacts are created and closed across every send/receive.

Spring's SingleConnectionFactory class pools a single connection for every template nicely and tends to alleviate the problem. However, it fails to pool Session, Producer and Consumer artifacts. As mentioned by James Strachan and others, the same can lead to performance degradation.

With the SingleConnectionFactory, Spring definitely started off on the right foot, however, the same is not enough. The other artifacts derived from javax.jms.Connection bring their own penalty and the cost of the same is probabaly different depending on the JMS Provider used.

When using WebLogic, I found that clearly the most performant way to send messages is without using the JmsTemplate, i.e., obtaining a Connection, Session, Producer/Consumer and re-using the same across multiple sends or receives. Using the JmsTemplate does impact the performance even though Spring's SingleConnectionFactory re-uses the Connection object, there seems to be a penalty that is encountered due to Session and Producer/Consumers not being re-used.

Is it is possible to re-use the Session and Producer/Consumers via the JmsTemplate ? Sure, a simple custom implementation of the Connection Factory that proxies and re-uses the Session and Producer/Consumer artifacts can lead to a performance gain.

Using the Dynamic Proxy pattern, one can create a custom ConnectionFactory that wraps the connection factory that is obtained from the JMS Provider. The custom Connection factory like Spring's SingleConnectionFactory class maintains a single JMS Connection which is re-used across every send/receive. However, unlike Spring's SingleConnectionFactory, the connection returned is a Proxy that will attempt to re-use Session objects. The Session objects created by the Connection Proxy are also Proxies and will pool Producer/Consumer objects. Doing pooling all the way down allows for re-use of created JMS Objects. I created a simple example of the same that does the pooling. Nothing too exotic, just a simple, and most likely bug filled ;-) library as shown below:

Custom Connection Factory that Creates a Single Connection:



public class SingleConnectionFactory implements ConnectionFactory, QueueConnectionFactory,
TopicConnectionFactory, DisposableBean {

private final ConnectionFactory delegate;
private Connection singleConnection;

private String clientID;
private ConnectionInvocationHandler dynamicConnectionProxy;

public SingleConnectionFactory(ConnectionFactory delegate) {
this.delegate = delegate;

}

// Create the sole connection
private synchronized Connection createSingleConnection() throws JMSException {

if (singleConnection != null) {
return singleConnection;

}

Connection conn = delegate.createConnection();

if (clientID != null) {
conn.setClientID(clientID);

}

List<Class<? extends Connection>> classes = new ArrayList<Class<? extends Connection>>(3);

classes.add(Connection.class);

if (conn instanceof QueueConnection) {

classes.add(QueueConnection.class);
}

if (conn instanceof TopicConnection) {

classes.add(TopicConnection.class);
}

dynamicConnectionProxy = new ConnectionInvocationHandler(conn);


singleConnection = (Connection) java.lang.reflect.Proxy.newProxyInstance(delegate.getClass()

.getClassLoader(), (Class[]) classes.toArray(new Class[classes.size()]),
dynamicConnectionProxy);

return singleConnection;
}

public Connection createConnection() throws JMSException {

return createSingleConnection();
}
....
.....
public void destroy() throws Exception {
synchronized (this) {

JmsUtils.closeConnection(singleConnection);
dynamicConnectionProxy.destroy();
}

}
}





Connection Invocation Handler that factories Session Proxies:



public class ConnectionInvocationHandler implements InvocationHandler, DisposableBean {

private Connection delegate;
// WSession is a custom interface that extends Session, QueueSession
// and TopicSession
private Pool<WSession> sessionPool;

public ConnectionInvocationHandler(Connection delegate) {
this.delegate = delegate;

this.sessionPool = new Pool<WSession>();
}

public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {

if (isSessionCreationMethod(method)) {

return sessionPool.take(new Creator<WSession>() {

public WSession create() {
try {
Session sessionDelegate = (Session) method.invoke(delegate, args);

if (sessionDelegate == null) {
throw new RuntimeException("Unable to Create Session Delegate");

}

WSession s = (WSession) Proxy.newProxyInstance(Session.class.getClassLoader(),
new Class[] { WSession.class }, new SessionInvocationHandler(sessionDelegate,
ConnectionInvocationHandler.this));

return s;
}
catch (Exception e) {

throw new RuntimeException("Error creating", e);
}
}

});
}
else if (method.getName().equals("close")) {

// Do not close delegate here.
return null;
}
else if (method.getName().equals("setClientID")) {

// Client ID is for the single connection only.
String currentClientId = this.delegate.getClientID();

if (currentClientId != null && currentClientId.equals(args[0])) {

return null;
}
else {
throw new javax.jms.IllegalStateException(

"setClientID method is not allowed on the proxy. Set it explicitly on the Factory instead. ");
}
}

return method.invoke(delegate, args);

}

void releaseSession(WSession session) throws Exception {

sessionPool.give(session);
}
....
....
/**
* Shut down all open Connections, Sessions, Producers and Consumers.
*/

public void destroy() throws Exception {

sessionPool.destroy();
}
}





Session Invocation Handler that Proxies Producer and Consumer Proxies:



public class SessionInvocationHandler implements InvocationHandler {

private Session delegate;
private ConnectionInvocationHandler connectionProxy;
private Pool<WSender> producerPool;

private Pool<WConsumer> consumerPool;

public SessionInvocationHandler(Session delegate, ConnectionInvocationHandler connectionProxy)

throws JMSException {
this.delegate = delegate;

this.connectionProxy = connectionProxy;
this.producerPool = new Pool<WSender>();

this.consumerPool = new Pool<WConsumer>();
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (isSenderMethod(method)) {
return getSender(method, args);

}
else if (isReceiverMethod(method)) {

return getConsumer(method, args);
}
else if (method.getName().equals("close")) {

// Set object's closed flag to true
try {
connectionProxy.releaseSession((WSession) proxy);

}
catch (Exception e) {
JmsUtils.closeSession(delegate);

}

return null;
} else if (method.getName().equals("destroy")) {

producerPool.destroy();
consumerPool.destroy();
JmsUtils.closeSession(delegate);

connectionProxy = null;
return null;
}

return method.invoke(delegate, args);
}

// Assume duplicate of this code for Consumer
WSender getSender(final Method method, final Object args[]) throws Throwable {

return producerPool.take(new Creator<WSender>() {
public WSender create() {

try {
MessageProducer producerDelegate = (MessageProducer) method.invoke(delegate, args);

WSender s = (WSender) Proxy.newProxyInstance(MessageProducer.class.getClassLoader(),
new Class[] { WSender.class }, new ProducerInvocationHandler(producerDelegate,
SessionInvocationHandler.this));

return s;
}
catch (Exception e) {

throw new RuntimeException("Error Creating Sender", e);
}
}

});
}
....
....

void release(WSender sender) throws Exception {

producerPool.give(sender);
}
...
}




The Production Invocation Handler (Consumer is similar):



public class ProducerInvocationHandler implements InvocationHandler {

private MessageProducer delegate;
private SessionInvocationHandler sessionProxy;

public ProducerInvocationHandler(MessageProducer delegate, SessionInvocationHandler sessionProxy)

throws JMSException {
this.delegate = delegate;

this.sessionProxy = sessionProxy;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (method.getName().equals("close")) {

try {
sessionProxy.release((WSender) proxy);

} catch (Exception e) {
JmsUtils.closeMessageProducer(delegate);

}

return null;
} else if (method.getName().equals("destroy")) {
JmsUtils.closeMessageProducer(delegate);

sessionProxy = null;
return null;
}


return method.invoke(delegate, args);
}
}




A Sample Unit Test:



@Test
public void testWithoutSpring() throws JMSException {

Connection conn = connectionFactory.createConnection();
conn.start();

Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

MessageProducer producer = session.createProducer(queue);
StopWatch w = new StopWatch();

w.start();
for (int i = 0; i < MAX_MESSAGES; i++) {

producer.send(messageCreator.createMessage(session));
}

w.stop();
System.out.println("Sans Spring Jms Template:" + w.getTotalTimeMillis());

}


@Test
public void testSpringJmsTemplate() {

System.out.println("Spring Jms Template Without Single Connection Factory:" + executeTemplateTest(connectionFactory));
}


@Test
public void testSpringJmsTemplateSingleConnFactory() {
org.springframework.jms.connection.SingleConnectionFactory f
= new org.springframework.jms.connection.SingleConnectionFactory(connectionFactory);

System.out.println("Spring Jms Template with Single Connection Factory:" + executeTemplateTest(f));
}


@Test
public void testPoolingFactory() throws Exception {

SingleConnectionFactory singleConnectionFactory = new SingleConnectionFactory(connectionFactory);
System.out.println("Spring JmsTemplate With Pooled Custom Factory:" + executeTemplateTest(singleConnectionFactory));

singleConnectionFactory.destroy();
}

private long executeTemplateTest(ConnectionFactory connectionFactory) {

JmsTemplate template = new JmsTemplate(connectionFactory);
template.setDefaultDestination(queue);


StopWatch watch = new StopWatch();
watch.start();

for (int i = 0 ; i < MAX_MESSAGES; i++) {

template.send(messageCreator);
}

watch.stop();

return watch.getTotalTimeMillis();
}




Each of the above tests clears the JMS Queue of all messages before starting. In addition, the cost of obtaining JMS Resources like Connection Factory and Queue are abstracted to the "before" method of the test. When I ran tests across my local WebLogic installation, I found the following results with all time measured in milli seconds:

100 Messages Sent:
Sans Spring Jms Template:109
Spring Jms Template Without Single Connection Factory:1763
Spring Jms Template with Single Connection Factory:1025
Spring JmsTemplate With Pooled Custom Factory:207

1000 Messages Sent:
Sans Spring Jms Template:1239
Spring Jms Template Without Single Connection Factory:18049
Spring Jms Template with Single Connection Factory:6135
Spring JmsTemplate With Pooled Custom Factory:2326

5000 Messages Sent:
Sans Spring Jms Template:6618
Spring Jms Template Without Single Connection Factory:52916
Spring Jms Template with Single Connection Factory:25944
Spring JmsTemplate With Pooled Custom Factory:8894

So here lies my take on using JmsTemplate with WebLogic. Try not to use it but instead obtain Connection, Session, Producer/Consumers and reuse them. If you have to use JmsTemplate and are not sending many messages, then use the SingleConnectionFactory provided by Spring in conjunction with JmsTemplate.

If many messages are being sent in succession then creating a custom factory that pools Session and Producer/Consumer objects would be the way to go IMO.

The sample code that I have does not handle idle time out for the JMS artifacts. Building the same into the proxies should be a trivial effort. In addition to the above optimization, one can easily build into the Proxies, re-connect logic for Connection and Session, Producer/Consumers. WebLogic transparent reconnect logic, in the event of failure of a Server in a Cluster, cannot always be guaranteed (look at the OTN forums).

I would be interested to know how the JmsTemplate performs with other JMS Providers. In addition, if my bearings are totally off, I would like to know that as well ;-)..An please I am talking of this Blog only ;-)

wljmshelper is the library that represents the code for the above and can be downloaded from HERE The project is a Maven 2 project and one should be able to compile the same as it references the JMS API. For compilation there are no WebLogic specifics. However for running the tests, one would require the WebLogic Client, i.e., wlfullclient.jar. Further you would need a weblogic installation :-) in order to run the tests.

Disclaimer:
The above mentioned code is an experiment. It has not undergone testing and is not even open source and is created purely for the intent of demonstration.

Saturday, January 24, 2009

Spring Jms Support

My year at Overstock.com has been just superb from a learning front. I have had the oppurtunity to work RESTful Web Services, Maven, Hibernate and in general be a part of a super architecture and development team at play.

I have also been able to contribute in the selecting of a JMS provider/architecture for reliable messaging at Overstock. The provider that we have selected is Oracle WebLogic.

As we enter the world of WebLogic JMS, I find that there are items that are best abstracted away such that developers of an application can easily utilize the provider without having to repeat code. Spring's JMS support feels ideal for the same.

Obtaining JMS Artifacts from JNDI:



Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
p.put(Context.PROVIDER_URL, "t3://localhost:8000,localhost:8002");
p.put(Context.SECURITY_PRINCIPAL, "weblogic");
p.put(Context.SECURITY_CREDENTIALS, "weblogic");

JndiTemplate template = new JndiTemplate(p);

QueueConnectionFactory connFactory = (QueueConnectionFactory)
template.execute(new JndiCallBack() {
public Object doInContext(Context ctx) {
return (QueueConnectionFactory) ctx.lookup("connectionFactory");
}
});
....




JmsTemplate:
Spring Framework provides a Template class called JmsTemplate much like HibernateTemplate for Hibernate DAO. The class provides many convinience methods for sending recieving messages by providing an abstraction layer over the JMS API. There are methods such as send/receive or methods that accept Call Backs. I like some of the safety these methods provide where Connections, Sessions, Producers and Consumers are gracefully closed after use of them. WebLogic documentation explicitly states that Connection objects must be closed after using them.

That said, I also fear that this class is very open for misuse. James Strachan has mentioned some of the PIT falls that one needs to be aware of when using JmsTemplate. The primary concern that surfaces with the JmsTemplate creating a Connection/Session/Producer or Consumer across every send/receive/callback. This can easily be misused and in the case of WebLogic, attempting to use the template with the default Connection Factory degrades the performance of operations. I fear that directly using the JmsTemplate can lead to code like:



jmsTemplate.send(new MessageCreator() {
public Message send(Session session) throws JMSException {
return session.createTextMessage("Order Submited");
}
});

... do some stuff..
jmsTemplate.send(new MessageCreator() {
public Message send(Session session) throws JMSException {
return session.createTextMessage("Order completed");
}
});



For each of the send operations above, a Connection, Session and Producer will be created. If the above sequence is being called many times over, this would present a performance problem.

With CallBacks like Connection/Session or Producer, re-use has more of chance as within a call back one could send multiple messages thus re-using the jms objects. However, if these operations are many, than these too can suffer misuse and cause performance degradation. JmsTemplate works I guess when you send a message once in a while.

James observation regarding the use of JmsTemplate is very astute and using JmsTemplate might not be best of options unless "Pooling" is introduced into the mix.

Spring Message Container:
Spring offers support for Message Driven POJOs (MDP) in the form of MessageListenerContainers. The Container is responsible for retrieving a message from a JMS destination and then notifying the listener associated with the Container. One nice feature of the Container is that it provides for re-connect logic in event of failure of a server in a Cluster by allowing transparent reconnect to different server in the cluster. Look at this POSTING about a Reconnecting Message Listener. The Spring Message ListenerContainer's tend to Pool Jms artifacts as well. In particular the DefaultMessageListenerContainer provides XA support as well. Using a Container to receive messages is as simple as:




SimpleMessageContainer container = new SimpleMessageContainer();
container.setConnectionFactory(connectionFactory);
container.setDestination(queue);
// Set how many concurrent consumers
container.setConcurrentConsumers(10);
consumer.setMessageListener(new javax.jms.MessageListener() {
public void onMessage(Message m) {
..do some stuff...
}
});
container.start();




Message Converters:
I feel that the SimpleMessageConverter class has some nice convinience methods for converting from POJO's to JMS Messages and vice versa. Message Converters are IMO a great concept for message translation. No whining here.

All in all, I think using Spring's MessageContainer is advisable considering it has all the logic for reconnect, multi-threading, XA etc all build in. Using the Converters has benefit and the JndiTemplate serves to abstract away boiler plate code. However, using Jms Template needs to be done with great care with Pooling almost a must. Jenks might be an option.

Tuesday, December 16, 2008

Unable to RIP, my foundations are shaky..

"Oh No! Not REST again. Can't you post something else? Don't you see that you are blogging about something that is only a blip in the CS Continuum which will soon be rendered immaterial?For heaven sake, there are more important things to write about!..."

That my friends, was my split SOAP personality coming forth for a few brief moments ;-)..Down boy, down! This ain't one of those bashing blogs, its got nothing to do with you, it's more of a house keeping blog. I need to get my thoughts in order. We shall have our little death match soon, I promise..By the way, this blog has more to do with HTTP than REST.

As I work with REST and HTTP, there are some fundamental concepts that I need to absorb and document for my reference or anyone else who might find it useful. For anyone getting into the REST web services, one book is a must read, RESTful Web Services by Richardson and Ruby.Most of this blog is summarizing and discussing what is written in the book in addition to my 2c.

Some Definitions:

Side Effects in Programming:
A side effect free operation is one which when invoked, should not result in the "hidden" and "unexpected" change of some other state. Maybe a better definition can be obtained from Wiki Pedia. From a broad case, calling a method add(int a, int b), should not blow up my system ;-) or take money out of someone's bank account and credit it to mine :-)))

Idempotency:

An operation is said to be idempotent, when multiple invocation of the same operation by the same or different consumers, results in the leaving the operation in the same state always. When working with Resources, quoting the Web Services book, "An operation on a resource is idempotent, if making one request is the same as making a series of identical requests. The second and subsequent requests leave the resource state in exactly the same state as the first request."

Http Methods that I am unclear about:

1. GET:

GET method is used to retrieve whatever information is available at a particular Request URI. The W3C documentation states "If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process. "

A GET request is issued to obtain information. It is not meant to change the any state on the server. "No Change" seems to be the buzz word. Safety is of the utmost importance. If one executes, "/orders/order/23", 0 or more times, it should be the same every time. Executing the request, should not result in the consumer concerned regarding the state of the resource. Now, "same" does not mean that the result obtained is the "same" across all the calls over time. For example, it is possible that during the 1st request made, the order with number 23 was non-existent, when the 2nd request was made, the order was returned (maybe a PUT occured that created the resource), when the third request was made the same order was returned but had different content (maybe due to a PUT that changed the resource).

What is the "idem potency" part here? Are we leaving the resource in the same state across multiple requests?

What about cases like "HIT-Counters", should these resources be a GET operation? The Web Services book seems to say that GET requests CAN have side effects and states that HIT counters are a candidate for GET operation. If we go back to the W3C definition of GET, it states that if the GET operation invokes a URI that is a data producing process, the data will be returned as part of the response. For example, on every GET request, we might be changing server state due to some logging occurring. In the case of HIT counters, or lets say a service that generates UUID's, via, GET "/uuidgenerator", state is being changed from request to request. Side effects are occurring, and majorly so. So what's all this stuff we stated above regarding GET's not changing server state that is visible and creating a substantial impact? Isn't a call to increment the HIT counter really a "Increment and get the next value?"

The authors of the Web Services book state "A client should never make a GET or HEAD request just for the side effects, and the side effects should never be so big that the client might wish it hadn't made the request". When a client invokes a GET on a hit counter, if the client does not expect it to have a side effect of incrementing the counter, what is the point in making the request? I understand if the call was a GET "/hitCounter/currentCount", then the request is not changing the count. However, auto incremented GETs is definitely a major side effect IMO. The same would apply to the UUID which would create a new one on every call. This BLOG has an interesting discussion on GET and idempotency.

A document from the W3C attempts to address when it is appropriate to use GET. Again, I do not feel the document finds me my answer.

I am rather torn as GET for a UUID seems so natural, "Get me a new UUID". I am also unsatisfied with explanations from the Web Services book. However, in light of all the above, my take on items like hit counters, uuid generators etc, are better handled via a "POST" operation. We are changing the state of the resource definitely and with "INTENT" of doing so from the Client's perspective, so is it not better better to use a POST and consume the response? Am I totally wrong. here...?

2. PUT:

A PUT operation is typically used to create or update a resource. From the W3C, "The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI"

What the above tells me is that use PUT to create a resource that can subsequently queried with a GET request to the created resource URI.

For example, a PUT to "/orders/order/23", when there is no resource at the URI, the PUT operation results in the creation of an Order with Id = 23. Invoking PUT to "/orders/order/23" when an order previously existed at the resource, equates to updating the order. After either of the above PUT calls, a call of GET "/order/order/23" will obtain a resource, i.e., the Order with Id=23.

From the above, if creating a new resource, I would only use PUT if I have all the information required to create/update the resource before the call is made such that a subsequent GET operation can be executed with the information I possessed to obtain the newly created Resource. I do not expect the Resource code present on the server at the URI to supply any additional data that then allow me to locate the resource based of the server provided data. What I create with, I should be able to GET.

PUT indicates a call where the client is in control of exactly where and how the Resource will be identified. Further more PUT is idempotent, multiple calls with the same information has the same result on the operation. So in the case of the order example, before creating the resource, I would ask a UUID service to obtain a unique identifier and then use that identifier to uniquely identify the resource I create. Note that in the case of the "Order" example, one is actually creating a "sub-resource" of the orders resource, so is PUT an acceptable operation to do the same? Yes, the book is a good read for details.

3. POST:

POST, IMO is one of the HTTP methods that is most flexible to use. The W3C documentation on POST states "The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line". Another interesting line from the W3C documentation is "The action performed by the POST method might not result in a resource that can be identified by a URI."

From the above, POST should be used when creating a "Sub-Resource" of a resource. For example, a line item under a particular order such as POST "/order/23/lineItems/" . In other words POST is used to create a Resource without priorly knowing exactly where the Resource will be available upon creation. After the call to POST, the newly created line item resource might be available at "/order/23/lineItems/lineItem/2" or at "/order/lineItems/lineItem/3" or at some other identifier. The client that made the call to POST the data has no way of knowing the URI where the Line Item can be obtained from, prior to performing the call.

POST, IMO, is a great candidate when creating a resource whose Id will be generated when the resource is created, for example, when creating a line item that is a sub resource of the order.

What about using using POST for NOT creating a Resource that can be identified by a URI? This is total room for RPC style of programming. A Resource can be used as a RPC style processor by interrogating the request and performing different operations based of the same. The Web Services books terms the same as Overloaded POST. Uses of POST for "myresource?method=save" or "/myresource?method=archive" are uses of POST that are more RPC oriented.

Using POST for something like, "/calculateCost", IMO is a valid use of POST where a request is submitted and the response provides the result. As mentioned before, I am of the opinion that POST is the better candidate for HIT Counters, Id Generators etc.

One problem that plagues URI's is the allowed length. Although the HTTP Standard does not define a limit on URI length, clients and servers do. I like the example from the Web Services book, a GET "/numbers/11111..........", represents a problem. However, performing a POST on a resource by specifying a "method" seems a reasonable way to overcome this problem, ex: POST "/numbers?method=GET" where the number "11111....", a very long number, is in the body of the POST.

In other words, is it OK to bend the rules of REST in cases where URI length is a concern? This seems to me an architectural and design compromise one needs to suffer when URI length breaks the underlying system. Overloaded POST needs to be used judiciously. If URI length is NOT a concern, I recommend not having to use overloaded POSTs at all.

What about algorithms or singular methods available at a resource? Is POST the right HTTP method for the same?

When to use Query Variables?

One finds cases where representing Resource via fully qualified paths sometimes feels rather verbose. Do I need to create a resource for every path possible? Scoping a Resource sometimes does not sound right, in some other cases, it is just painful when very deep :-).

The authors of the Web Services book prefer to avoid query variables where possible. Quoting the authors, "..including them (query vars) in the URI is a good way to make sure that URI gets ignored by tools like proxies, caches and web crawlers". The same are great arguments, but making Resource URI's of resources that will not necessarily be used from one call to another, is pretty steep. The authors especially acknowledge the value of Query variables when they apply to searches or what they generalize as "algorithms".

I totally agree with the authors regarding the appropriate use of Query variables when a search is involved. Rather than having an individual URI path for every possible criteria and sub-criteria, the use of query variables are more apt for the problem.

Consider the Yahoo API, http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf

Note the use of the "webSearch" at the end of the URI prior to the Query Variables that follow. It is my opinion that the above is a great example of how a URI for search should be developed.

So in the same light, "/orders/search?createDate=20081127&containsItem=XBox.." is a great use of Query Variables.

Conclusion:

I hope I have understood the "basics" properly. If not, as always, I would appreciate insight in the matter. I am back to re-reading the book. At the very best, I find that HTTP specifications are rather nebulous. My take on the methods and query variables:

  • Use PUT when you know that you can GET the Resource based of the information you have when you will be PUTting the Resource.
  • For algorithms such as HIT counters, use POST.
  • Use POST when creating a sub resource, especially when working with generated database identifer that will define your resource URI.
  • Query Variables are a great use when performing searches. In particular, let the resource where the search begins be denoted as such, i.e, ".../.../foo../bar../search?...". Or in other words, qualify till applicable before resorting to search.
  • Do not overload POST and make it an RPC call. SOAP personality, please relax..its not personal :-)

Finally,

  • "/orders" - POST to create a new order seems correct
  • "/orders/123" - PUT to update order 123 seems correct
  • "/orders/123" - DELETE seems correct to delete order 123
  • "/orders" - GET seems correct to get all orders.
  • "/orders/123" - GET seems correct to get order 123
Resources:

Tuesday, December 9, 2008

jvmti, jni - Absolute Power

Its a snowy day..I am sick, for those who jump to say "I've known that for years!", chill! :-) I am definitely under the weather and to add to the same, I have a snowy landscape to view. I am also suffering from really erratic sleep patterns. Sometimes I am unable to sleep until 5:45 a.m and other times where I wake up at 4:45 a.m. For one reason or another, I always land in state that has snow. Maybe it's destiny. Maybe one day when I move back to Bangalore, it will snow there as well, due to global warming or a nuclear winter, what have you. Immediate concerns, why could I not be in Florida? All ye Florida recruiters, ping me ;-) I apologize for the brief frustration release.

Anyway, that is enough for introductions. As always, I do not really know what to do with my precious time and instead choose to waste it. I have been interested in java class instrumentation and the esoteric world of java under the covers ever since I attended a presentation by Mr.Ted Neward. In particular, I have been wanting to play with JVMTI. Doing so meant, I would need to enter the world of C programming, something I have seem to have forgotten since working with java. So what am I trying to do? I am wishing, what if during developing unit tests, I could:
  • Force a Garbage collection of the JVM
  • Check to see if the objects I allocated are cleaned out
  • Determine what objects are on the heap
  • Determine what the state of the different threads on the VM are...
  • Determine what objects are reachable
  • And More...
Sure you can, just use a profiler like JProbe, YourKit or whatever. But how do they do it? JVMTI is the answer.

What is JVMTI? "The JVM tool interface (JVM TI) is a standard native API that allows for native libraries to capture events and control a Java Virtual Machine (JVM) for the Java platform"...That is the official statement, mine is "Power Baby, Power!". Read more about JVMTI, JVMPI and how agents work in this fantastic article by Kello O'Hair and Janice J.Heiss.

In particular, the folder JDK_HOME/demo/jvmti of your JDK has multiple demonstrations of JVMTI features. I spent quite sometime running the same and would recommend taking a look at the demo's for my fellow enthusiast.

So what am I looking for? What I would like to do is load a libary using JNI and use JVMTI to print debug information regarding my application state. In particular, I am looking to see whether or not my code cleans up after itself.

I have a class Foo that is rather plain and does the following. Note that the same could easily be replaced by a JUnit test:



public class Foo {
Bar b;

private static Bar BAR = new Bar();

public Foo() {
b = new Bar();
}

public static class Bar {}
public String sayHello() {

ProgramMonitor.dumpHeap();
return "Hello World";
}

public static void createFoo() {
ProgramMonitor.forceGC();

ProgramMonitor.dumpHeap();
new Foo().sayHello();

}

public static void main(String args[]) {

Foo.createFoo();
ProgramMonitor.forceGC();
ProgramMonitor.dumpHeap();

}
}



My code for the ProgramMonitor class is rather simple and uses JNI as shown below:



public class ProgramMonitor {
public static native int getNumberOfLoadedClasses();

public static native void dumpHeap();
public static native void forceGC();

static {
System.load(System.getProperty("jvmtilib"));

}
}


So what I am trying to accomplish. When an object of the "Foo" class is created, it results in the creation of the "Bar" class as well. In addition, when Foo.class is loaded, it creates a static reference to Bar as well. When the program is done with the "Foo" object that is instantiated, the Bar object should be gone, i.e., GCed. However, the static reference to Bar in the Foo class should still be available.

What if I could view this same happening and assert the same ?

As shown above, the ProgramMonitor.java invokes native methods. One can create a C header file from the class definition by executing the following command:

>javah -jni -classpath . ProgramMonitor

The above call results in the creation of a C header file called ProgramMonitor.h that looks like:

....
/*
* Class: ProgramMonitor
* Method: getNumberOfLoadedClasses
* Signature: ()I
*/

JNIEXPORT jint JNICALL Java_ProgramMonitor_getNumberOfLoadedClasses

(JNIEnv *, jclass);

/*
* Class: ProgramMonitor
* Method: dumpHeap
* Signature: ()V
*/

JNIEXPORT void JNICALL Java_ProgramMonitor_dumpHeap

(JNIEnv *, jclass);

/*
* Class: ProgramMonitor
* Method: forceGC
* Signature: ()V
*/

JNIEXPORT void JNICALL Java_ProgramMonitor_forceGC

(JNIEnv *, jclass);
.....



The above generated header file defines the JNI functions that one needs to implement. An C file that implements the JNI header functions is created, i.e., ProgramMonitor.c. Shown below are only some parts of the C file, ProgramMonitor.c:



...
#include "jni.h"
#include "jvmti.h"
#include "ProgramMonitor.h"

/* Check for JVMTI error */
#define CHECK_JVMTI_ERROR(err) \
checkJvmtiError(err, __FILE__, __LINE__)

static jvmtiEnv *jvmti;

.....
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {

jint rc;
jvmtiError err;
jvmtiCapabilities capabilities;

jvmtiEventCallbacks callbacks;

/* Get JVMTI environment */
jvmti = NULL;

rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION);

if (rc != JNI_OK) {
fprintf(stderr, "ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc);

return -1;
}

CHECK_FOR_NULL(jvmti);

/* Get/Add JVMTI capabilities */
.....
/* Create the raw monitor */
err = (*jvmti)->CreateRawMonitor(jvmti, "agent lock", &(gdata->lock));

CHECK_JVMTI_ERROR(err);

/* Set callbacks and enable event notifications */
....
return JNI_VERSION_1_2;

}

JNIEXPORT jint JNICALL Java_ProgramMonitor_getNumberOfLoadedClasses(JNIEnv *env, jobject obj){

jclass *classes;
jint count;

(*jvmti)->GetLoadedClasses(jvmti, &count, &classes);


return count;
}

void dump() {

// Dump information....
.....
}

JNIEXPORT void JNICALL Java_ProgramMonitor_dumpHeap

(JNIEnv *env, jclass jclass) {
dump();

}

JNIEXPORT void JNICALL Java_ProgramMonitor_forceGC
(JNIEnv *env, jclass js) {

printf("Forcing GC...\n");
jvmtiError err = (*jvmti)->ForceGarbageCollection(jvmti);

CHECK_JVMTI_ERROR(err);
printf("Finished Forcing GC...\n");
}




The point to note from the above are that JNI_OnLoad method is called, a reference to the JVMTI environment is obtained and interest on jvmti capabilities are established. Note the forceGC call.

Now that we have the implementation of the library, we can build the same. The resulting library is called libProgramMonitor.so. So what we have now is a C library that obtains a handle to JVMTI and provides for methods to force garbage collection and provide information on the heap at any given time.

We are now ready to execute our Foo class and witness the output.



>java -Djvmtilib=/home/sacharya/jvmti-examples/libProgramMonitor.so -classpath . Foo
Forcing GC...
Finished Forcing GC...
Number of loaded classes 353
Heap View, Total of 35688 objects found.

Space Count Class Signature
---------- ---------- ----------------------
8 1 LFoo$Bar;
---------- ---------- ----------------------

Number of loaded classes 353
Heap View, Total of 35690 objects found.

Space Count Class Signature
---------- ---------- ----------------------
16 2 LFoo$Bar;
16 1 LFoo;
---------- ---------- ----------------------

Forcing GC...
Finished Forcing GC...
Number of loaded classes 353
Heap View, Total of 35679 objects found.

Space Count Class Signature
---------- ---------- ----------------------
8 1 LFoo$Bar;
---------- ---------- ----------------------



From the above, notice that the instance of Bar that was transiently created was reclaimed. The static reference to Bar however lingered as expected.

Conclusion:
We can easily add more methods to the ProgramMonitor class to provide information such as References, Threads etc. The ProgramMonitor library is not displaying all the loaded classes and is filtering out the ones that begin with "java" or "sun".

Using JVMTI can be so valuable in validating code and ensuring it behaves as expected at the Unit test level. I am aware that there are commercial software that do the same :-)...You can't blame me for playing ;-). JVMTI is powerful stuff and I am only feeling the temperature of the water here. I don't want to enter the "C" though ;-)! If Linux is for geeks, then so is C. I have reached the conclusion that Java is equivalent of Windows OS for the C programmer.

I am not quite sure whether the "ForceGarbageCollection" is indeed a gurantee of Garbage collection. I am curious regarding promotion of objects across different GC spaces and how the ratio effects the code.

Source:
The code shown above was developed on JDK1.16.X and run on a Linux OS. Easily made compatible though by looking at the examples in the standard jdk demo. In addition, the majority of the code is based of the heapViewer demo code. This example is only an "example".

As always, my source can be obtained from HERE

Running the Example:
Enusre you have JDK 1.6 installed and you are on Linux OS. Export JDK_HOME to your jdk home. Run javac to compile your sources. Run the makefile by typing "make" to build "libProgramMonitor.so". Finally run ">java -Djvmtilib=/home/sacharya/jvmti-examples/libProgramMonitor.so -classpath . Foo" replacing jvmtlib value with the location of the libProgramMontior file in your file system. I know I should have made a maven project, I should have also had the .java file compiled from the make file. Oh well! In addition, why couldn't I have used System.loadLibary() to load the JNI library file? I couldn't, as it didn't work even though I have LD_LIBRARY_PATH defined correctly and am too lazy to figure out why ;-) Also, a better test would have been have a more busy case where the CPU is really occupied to view the GC.

Ping me if you cannot run this example. I have tried the same on Suse 11 and Mandriva Spring.

Resources:
JVM Tool Interface (JVMTI): How VM Agents Work
Java Forum inspiration
Garbage Collection Forcing documentation
Heap Analyzer Tool - Worth checking out
Creating and Debugging a Profiling Agent with JVMTI