<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6625574524734878463</id><updated>2012-01-17T15:19:53.467-08:00</updated><category term='debug'/><category term='no attach in java.library.path'/><category term='VisualVM'/><category term='GlassFishESB OpenESB JBI BPEL4People WorklistManager'/><category term='no providers installed'/><category term='data mining'/><category term='asynchronous'/><category term='com.sun.attach Java profiling Javassist'/><category term='&quot;'/><category term='Clojure'/><category term='Java SE web service Endpoint Silverlight Flex crossdomain.xml'/><category term='UnsatisfiedLinkError'/><category term='JDI'/><category term='OO'/><category term='Java SE web service'/><category term='Java'/><category term='Prolog'/><category term='Hello World'/><category term='Haskell'/><category term='Endpoint'/><category term='Scala'/><category term='shared memory'/><category term='I/O'/><category term='Java performance profiling'/><category term='Ruby'/><category term='FP'/><category term='Java Debug Interface'/><category term='ClassPrepareEvent'/><category term='functional programming'/><category term='performance monitoring'/><category term='NetBeans 7'/><category term='automated testing'/><category term='PollHandler'/><category term='DWR'/><category term='Flex'/><category term='JAX-WS'/><category term='Direct Web Remoting'/><category term='Platform Manager'/><category term='maxWaitAfterWrite'/><category term='Io'/><category term='Getting Started'/><category term='Erlang'/><title type='text'>Wayne Adams' Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-459203390137524766</id><published>2012-01-04T22:00:00.000-08:00</published><updated>2012-01-17T15:19:53.538-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java SE web service'/><category scheme='http://www.blogger.com/atom/ns#' term='Endpoint'/><category scheme='http://www.blogger.com/atom/ns#' term='JAX-WS'/><category scheme='http://www.blogger.com/atom/ns#' term='asynchronous'/><title type='text'>Asynchronous Java SE Web Services:  1.  Implementation</title><content type='html'>A few years ago, I posted a how-to on &lt;a href="http://wayne-adams.blogspot.com/2009/03/java-se-based-web-services.html"&gt;Java-SE-based Web Services&lt;/a&gt;.  More recently, I've become interested in asynchronous web-service invocation, and, as it turns out, Java SE supports that, too.  This post, then, is the asynchronous version of that older post.  How I got to the structure of this post is a story in itself.  To make things simpler, I will first go through all the steps to deploy&lt;br /&gt;an asynchronous Java SE web service.  Then, I will explain the route I chose, and what I see as the positives and negatives of the results.&lt;br /&gt;&lt;br /&gt;Here's the outline:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a WSDL definition file&lt;/li&gt;&lt;li&gt;Using the WSDL file, generate server artifacts; implement the web service operations&lt;/li&gt;&lt;li&gt;Create an external JAX-WS binding definitions file&lt;/li&gt;&lt;li&gt;Generate client-side artifacts using the WSDL and binding definitions files&lt;/li&gt;&lt;li&gt;Demonstrate synchronous and asynchronous client-side invocations of the web-service operations&lt;/li&gt;&lt;/ul&gt;Let's cut to the chase.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Create a WSDL definition file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here I'll create a minimal WSDL file, describing a web service which returns the exchange&lt;br /&gt;rate of two currencies.  Here's the file, called &lt;span style="font-family:courier  new;"&gt;exchange-rate.wsdl&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&lt;br /&gt;          xmlns:wsp="http://www.w3.org/ns/ws-policy"&lt;br /&gt;          xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy"&lt;br /&gt;          xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"&lt;br /&gt;          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"&lt;br /&gt;          xmlns:tns="http://async.ws.adamsresearch.com/"&lt;br /&gt;          xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;          xmlns="http://schemas.xmlsoap.org/wsdl/"&lt;br /&gt;          targetNamespace="http://async.ws.adamsresearch.com/"&lt;br /&gt;          name="ExchangeRateService"&amp;gt;&lt;br /&gt;      &lt;br /&gt;&amp;lt;types&amp;gt;&lt;br /&gt; &amp;lt;xsd:schema xmlns:tns="http://async.ws.adamsresearch.com/"&lt;br /&gt;             xmlns:xs="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;             version="1.0"&lt;br /&gt;             targetNamespace="http://async.ws.adamsresearch.com/"&amp;gt;&lt;br /&gt;   &amp;lt;xsd:element name="getExchangeRate"  type="tns:getExchangeRate"&amp;gt;&amp;lt;/xsd:element&amp;gt;&lt;br /&gt;   &amp;lt;xsd:element name="getExchangeRateResponse"  type="tns:getExchangeRateResponse"&amp;gt;&amp;lt;/xsd:element&amp;gt;&lt;br /&gt;   &amp;lt;xsd:complexType name="getExchangeRate"&amp;gt;&lt;br /&gt;     &amp;lt;xsd:sequence&amp;gt;&lt;br /&gt;       &amp;lt;xsd:element name="arg0" type="xsd:string" minOccurs="0"&amp;gt;&amp;lt;/xsd:element&amp;gt;&lt;br /&gt;       &amp;lt;xsd:element name="arg1" type="xsd:string" minOccurs="0"&amp;gt;&amp;lt;/xsd:element&amp;gt;&lt;br /&gt;     &amp;lt;/xsd:sequence&amp;gt;&lt;br /&gt;   &amp;lt;/xsd:complexType&amp;gt;&lt;br /&gt;   &amp;lt;xsd:complexType name="getExchangeRateResponse"&amp;gt;&lt;br /&gt;     &amp;lt;xsd:sequence&amp;gt;&lt;br /&gt;       &amp;lt;xsd:element name="return" type="xsd:double"&amp;gt;&amp;lt;/xsd:element&amp;gt;&lt;br /&gt;     &amp;lt;/xsd:sequence&amp;gt;&lt;br /&gt;   &amp;lt;/xsd:complexType&amp;gt;&lt;br /&gt; &amp;lt;/xsd:schema&amp;gt;&lt;br /&gt;&amp;lt;/types&amp;gt;&lt;br /&gt;&amp;lt;message name="getExchangeRate"&amp;gt;&lt;br /&gt; &amp;lt;part name="parameters" element="tns:getExchangeRate"&amp;gt;&amp;lt;/part&amp;gt;&lt;br /&gt;&amp;lt;/message&amp;gt;&lt;br /&gt;&amp;lt;message name="getExchangeRateResponse"&amp;gt;&lt;br /&gt; &amp;lt;part name="parameters" element="tns:getExchangeRateResponse"&amp;gt;&amp;lt;/part&amp;gt;&lt;br /&gt;&amp;lt;/message&amp;gt;&lt;br /&gt;&amp;lt;portType name="ExchangeRate"&amp;gt;&lt;br /&gt; &amp;lt;operation name="getExchangeRate"&amp;gt;&lt;br /&gt;   &amp;lt;input wsam:Action="http://async.ws.adamsresearch.com/ExchangeRate/getExchangeRateRequest"&lt;br /&gt;message="tns:getExchangeRate"&amp;gt;&amp;lt;/input&amp;gt;&lt;br /&gt;   &amp;lt;output wsam:Action="http://async.ws.adamsresearch.com/ExchangeRate/getExchangeRateResponse"&lt;br /&gt;message="tns:getExchangeRateResponse"&amp;gt;&amp;lt;/output&amp;gt;&lt;br /&gt; &amp;lt;/operation&amp;gt;&lt;br /&gt;&amp;lt;/portType&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;binding name="ExchangeRatePortBinding" type="tns:ExchangeRate"&amp;gt;&lt;br /&gt; &amp;lt;soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"&amp;gt;&amp;lt;/soap:binding&amp;gt;&lt;br /&gt; &amp;lt;operation name="getExchangeRate"&amp;gt;&lt;br /&gt;   &amp;lt;soap:operation soapAction=""&amp;gt;&amp;lt;/soap:operation&amp;gt;&lt;br /&gt;   &amp;lt;input&amp;gt;&lt;br /&gt;     &amp;lt;soap:body use="literal"&amp;gt;&amp;lt;/soap:body&amp;gt;&lt;br /&gt;   &amp;lt;/input&amp;gt;&lt;br /&gt;   &amp;lt;output&amp;gt;&lt;br /&gt;     &amp;lt;soap:body use="literal"&amp;gt;&amp;lt;/soap:body&amp;gt;&lt;br /&gt;   &amp;lt;/output&amp;gt;&lt;br /&gt; &amp;lt;/operation&amp;gt;&lt;br /&gt;&amp;lt;/binding&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;service name="ExchangeRateService"&amp;gt;&lt;br /&gt; &amp;lt;port name="ExchangeRatePort" binding="tns:ExchangeRatePortBinding"&amp;gt;&lt;br /&gt;   &amp;lt;soap:address location="http://localhost:8282/exchangeRate"&amp;gt;&amp;lt;/soap:address&amp;gt;&lt;br /&gt; &amp;lt;/port&amp;gt;&lt;br /&gt;&amp;lt;/service&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/definitions&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The web service has a single operation -- &lt;span style="font-family:courier  new;"&gt;getExchangeRate&lt;/span&gt; -- which takes a &lt;span style="font-family:courier  new;"&gt;String &lt;/span&gt;representation of two currencies and returns a &lt;span style="font-  family:courier new;"&gt;double&lt;/span&gt;.  There's no need to flesh this service out with a lot of operations -- I just want to demonstrate the dev cycle required to deploy a web service with asynchronous operations.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Generate the service-side artifacts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next, we'll create a Java web-service project using Maven.  In a convenient directory, enter&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;mvn archetype:generate -DgroupId=com.adamsresearch.ws.async -DartifactId=AsyncService&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(substituting your values, of course) and accept all the default values.  This creates the skeleton of what will be our web service.  Next, we'll modify the POM file to read the WSDL file and generate the service-side artifacts.  For this, we will use the JAX-WS utility &lt;span style="font-family:courier new;"&gt;wsimport&lt;/span&gt; (found in the Java SE SDK; we will be using the Maven &lt;span style="font-family:courier new;"&gt;wsimport&lt;/span&gt; plugin, however).  First, we have to decide where to put the WSDL file.  We can put it anywhere we want, of course, but note from the &lt;a href="http://jax-ws-commons.java.net/jaxws-%0A%0Amaven-plugin/wsimport-mojo.html"&gt;&lt;span style="font-family:courier  new;"&gt;jaxws:import&lt;/span&gt; docs page&lt;/a&gt; that the default location is &lt;code&gt;${basedir}/src/wsdl&lt;/code&gt;.  I prefer to put mine in a directory &lt;span style="font-family:courier new;"&gt;src/main/resources/wsdl&lt;/span&gt;, so I'll need to specify that directory below, in the arguments to &lt;span style="font-family:courier  new;"&gt;wsimport&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Open the POM file in the top-level directory of the project and add the following, after the &lt;span style="font-family:courier new;"&gt;dependencies&lt;/span&gt; element:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&amp;lt;build&amp;gt;&lt;br /&gt; &amp;lt;finalName&amp;gt;ExchangeRateWebService&amp;lt;/finalName&amp;gt;&lt;br /&gt; &amp;lt;plugins&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;     &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;     &amp;lt;configuration&amp;gt;&lt;br /&gt;       &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;&lt;br /&gt;       &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;&lt;br /&gt;     &amp;lt;/configuration&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;     &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;     &amp;lt;artifactId&amp;gt;jaxws-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;     &amp;lt;executions&amp;gt;&lt;br /&gt;       &amp;lt;execution&amp;gt;&lt;br /&gt;         &amp;lt;goals&amp;gt;&lt;br /&gt;           &amp;lt;goal&amp;gt;wsimport&amp;lt;/goal&amp;gt;&lt;br /&gt;         &amp;lt;/goals&amp;gt;&lt;br /&gt;         &amp;lt;configuration&amp;gt;&lt;br /&gt;           &amp;lt;wsdlDirectory&amp;gt;${basedir}/src/main/resources/wsdl&amp;lt;/wsdlDirectory&amp;gt;&lt;br /&gt;           &amp;lt;keep&amp;gt;true&amp;lt;/keep&amp;gt;&lt;br /&gt;           &amp;lt;packageName&amp;gt;com.adamsresearch.ws.async.generated&amp;lt;/packageName&amp;gt;&lt;br /&gt;           &amp;lt;sourceDestDir&amp;gt;${basedir}/src/main/java&amp;lt;/sourceDestDir&amp;gt;&lt;br /&gt;         &amp;lt;/configuration&amp;gt;&lt;br /&gt;       &amp;lt;/execution&amp;gt;&lt;br /&gt;     &amp;lt;/executions&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt; &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;The first dependency is an acknowledgment that Maven defaults to 1.3.  For those of you without white hair, that's a really old version of Java.&lt;br /&gt;&lt;br /&gt;I've decided to override a number of &lt;span style="font-family:courier  new;"&gt;wsimport&lt;/span&gt; defaults, to create the service in the desired package and to drop the files in the desired directory.  Note that &lt;span style="font-family:courier  new;"&gt;packageName&lt;/span&gt; does  not have a default setting.  Now enter &lt;span style="font-family:courier new;"&gt;mvn install&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;from the project top-level directory.&lt;br /&gt;&lt;br /&gt;I now have an interface -- &lt;span style="font-family:courier new;"&gt;ExchangeRate&lt;/span&gt; -- as well as some additional supporting classes.  It is time to write our service implementation.  Here is my first cut:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;package com.adamsresearch.ws.async;&lt;br /&gt;&lt;br /&gt;import javax.jws.WebMethod;&lt;br /&gt;import javax.jws.WebService;&lt;br /&gt;import javax.xml.ws.Endpoint;&lt;br /&gt;import com.adamsresearch.ws.async.generated.ExchangeRate;&lt;br /&gt;&lt;br /&gt;@WebService(serviceName="ExchangeRateService", portName="ExchangeRatePort", endpointInterface="com.adamsresearch.ws.async.generated.ExchangeRate")&lt;br /&gt;public class ExchangeRateEndpoint implements ExchangeRate&lt;br /&gt;{&lt;br /&gt; public static void main(String[] args)&lt;br /&gt; {&lt;br /&gt;     if (args.length != 1)&lt;br /&gt;     {&lt;br /&gt;         System.out.println("Usage: java -cp &amp;lt;jarFile&amp;gt; com.adamsresearch.ws.async.ExchangeRateEndpoint publishURL");&lt;br /&gt;         System.exit(-1);&lt;br /&gt;     }&lt;br /&gt;     ExchangeRateEndpoint wsInstance = new ExchangeRateEndpoint();&lt;br /&gt;     Endpoint.publish(args[0], wsInstance);&lt;br /&gt;     System.out.println("Published endpoint at URL " + args[0]);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @WebMethod&lt;br /&gt; public double getExchangeRate(String fromCurrency, String toCurrency)&lt;br /&gt; {&lt;br /&gt;   if (fromCurrency.equals("AS1") &amp;amp;&amp;amp; toCurrency.equals("GMD"))&lt;br /&gt;   {&lt;br /&gt;     return 2.78;&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;     return 0.0;&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;I then run &lt;span style="font-family:courier new;"&gt;mvn install&lt;/span&gt; once more, then launch the web service with the following:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;C:\dev\AsyncWSDev\AsyncService&amp;gt;java -cp target\ExchangeRateWebService.jar com.adamsresearch.ws.async.ExchangeRateEndpoint&lt;br /&gt;&lt;br /&gt;http://&lt;/span&gt; &lt;span style="font-family:courier  new;"&gt;localhost:8282/exchangeRateService&lt;/span&gt; &lt;span style="font-family:courier  new;"&gt;Published endpoint at URL http://localhost:8282/exchangeRateService&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If we open a browser at the specified URL with "&lt;span style="font-family:courier new;"&gt;?wsdl&lt;/span&gt;" appended, we'll see the web-service WSDL file, verifying that we successfully deployed the service.  Note that the Java runtime cleverly extracts the XML Schema from the WSDL file and references it via import.  Both the WSDL file and the XML Schema file (as retrieved by the HTTP request in the browser) are dynamically generated by the Java runtime.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Create an external JAX-WS binding definitions file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Why are we performing this step?  To produce a more-fully-functional client-side API for  our to-be-created web service client.  You can provide two types of binding definitions files to  &lt;span style="font-family:courier new;"&gt;wsimport&lt;/span&gt; -- JAXB-related files, and a file that specifies some customizations of the web service (which is why it's called a binding customization).&lt;br /&gt;&lt;br /&gt;Here is our binding customization file:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bindings&lt;br /&gt; xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"&lt;br /&gt; wsdlLocation="http://localhost:8282/exchangeRateService?wsdl"&lt;br /&gt; xmlns="http://java.sun.com/xml/ns/jaxws"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!-- applies to wsdl:definitions node, that would mean the entire wsdl --&amp;gt;&lt;br /&gt; &amp;lt;enableAsyncMapping&amp;gt;false&amp;lt;/enableAsyncMapping&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!-- wsdl:portType operation customization --&amp;gt;&lt;br /&gt; &amp;lt;bindings node="wsdl:definitions/wsdl:portType [@name='ExchangeRate']/wsdl:operation[@name='getExchangeRate']"&amp;gt;&lt;br /&gt;     &amp;lt;enableAsyncMapping&amp;gt;true&amp;lt;/enableAsyncMapping&amp;gt;&lt;br /&gt; &amp;lt;/bindings&amp;gt;&lt;br /&gt;&amp;lt;/bindings&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Note that the outer envelope of the file is called &lt;span style="font-family: courier new;font-family:courier new;" &gt;bindings&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;, and that there is an inner element also called &lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;bindings&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;.   Not to go into too much detail, but elements can be applied at the global level, and at a &lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;portType&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; or even an &lt;/span&gt;&lt;span style="font-family: courier new;font-family:georgia;" &gt;operation&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; level.  In this file, I've disabled asynchronous mapping at the global level, &lt;/span&gt;&lt;span style="font-  style: italic; font-family:georgia;" &gt;but turned it on &lt;span style="font-style: italic;"&gt;just for the &lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic; font-family: courier new;font-family:courier new;" &gt;getExchangeRate&lt;/span&gt;&lt;span style="font-style: italic; font-family:georgia;" &gt; operation&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;.  This precaution prevents potential new &lt;/span&gt;&lt;span style="font-family: georgia;font-family:courier new;" &gt;operation&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;s from being inadvertently exposed as asynchronous operations.  More on the&lt;/span&gt; &lt;span style="font-family: courier new;font-family:courier new;" &gt;wsdlLocation&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; later.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Generate the client-side artifacts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We're going to create a new Maven project for the web-service client (more on this later), so next we'll create another project:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;mvn archetype:generate -DgroupId=com.adamsresearch.ws.async -DartifactId=AsyncClient&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As with the service-side artifacts, I will create a &lt;span style="font-family:courier  new;"&gt;resources&lt;/span&gt; directory, but I'll do this a little differently this time.&lt;br /&gt;&lt;br /&gt;Instead of referencing the WSDL file in the project filesystem, I'll point &lt;span style="font-family:courier new;"&gt;wsimport&lt;/span&gt; to it via URL.  Note this is what I did above in the binding customization file, since it also references the WSDL location.  In the client project directory structure, I'll create a &lt;span style="font-family:courier  new;"&gt;src/main/resources/jaxws&lt;/span&gt; directory and put the binding customization file (which I called &lt;span style="font-family:courier new;"&gt;async-bindings.xml&lt;/span&gt;) in the&lt;br /&gt;directory.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Here's the relevant section of the client-project POM file, modified to point to the binding customization file and to access the WSDL file from the service itself:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&amp;lt;build&amp;gt;&lt;br /&gt; &amp;lt;finalName&amp;gt;ExchangeRateWebService&amp;lt;/finalName&amp;gt;&lt;br /&gt; &amp;lt;plugins&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;     &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;     &amp;lt;configuration&amp;gt;&lt;br /&gt;       &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;&lt;br /&gt;       &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;&lt;br /&gt;     &amp;lt;/configuration&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;     &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;     &amp;lt;artifactId&amp;gt;jaxws-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;     &amp;lt;executions&amp;gt;&lt;br /&gt;       &amp;lt;execution&amp;gt;&lt;br /&gt;         &amp;lt;goals&amp;gt;&lt;br /&gt;           &amp;lt;goal&amp;gt;wsimport&amp;lt;/goal&amp;gt;&lt;br /&gt;         &amp;lt;/goals&amp;gt;&lt;br /&gt;         &amp;lt;configuration&amp;gt;&lt;br /&gt;           &amp;lt;wsdlUrls&amp;gt;&lt;br /&gt;             &amp;lt;wsdlUrl&amp;gt;http://localhost:8282/exchangeRateService?wsdl&amp;lt;/wsdlUrl&amp;gt;&lt;br /&gt;           &amp;lt;/wsdlUrls&amp;gt;&lt;br /&gt;           &amp;lt;bindingDirectory&amp;gt;${basedir}/src/main/resources/jaxws&amp;lt;/bindingDirectory&amp;gt;&lt;br /&gt;           &amp;lt;keep&amp;gt;true&amp;lt;/keep&amp;gt;&lt;br /&gt;           &amp;lt;packageName&amp;gt;com.adamsresearch.ws.async.generated&amp;lt;/packageName&amp;gt;&lt;br /&gt;           &amp;lt;sourceDestDir&amp;gt;${basedir}/src/main/java&amp;lt;/sourceDestDir&amp;gt;&lt;br /&gt;         &amp;lt;/configuration&amp;gt;&lt;br /&gt;       &amp;lt;/execution&amp;gt;&lt;br /&gt;     &amp;lt;/executions&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt; &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Let's do a first build, before we actually write a client, and see what we get:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  mvn install&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;span style="font-family:georgia;"&gt;Now take a look at the generated &lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;ExchangeRate&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; Java interface.  When we generated the artifacts for the server, we had a single method declaration for our one operation in this file:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; @WebMethod&lt;br /&gt; @WebResult(targetNamespace = "")&lt;br /&gt; @RequestWrapper(localName = "getExchangeRate", targetNamespace = "http://async.ws.adamsresearch.com/", className = "com.adamsresearch.ws.async.generated.GetExchangeRate")&lt;br /&gt; @ResponseWrapper(localName = "getExchangeRateResponse", targetNamespace = "http://async.ws.adamsresearch.com/", className = "com.adamsresearch.ws.async.generated.GetExchangeRateResponse")&lt;br /&gt; public double getExchangeRate(&lt;br /&gt;     @WebParam(name = "arg0", targetNamespace = "")&lt;br /&gt;     String arg0,&lt;br /&gt;     @WebParam(name = "arg1", targetNamespace = "")&lt;br /&gt;     String arg1);&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;When we implemented this interface in our endpoint, it was a simple matter to process the input parameters and return the &lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;double&lt;/span&gt;&lt;span style="font-  family:georgia;"&gt; value.  If you open the artifact that we just generated, you'll see there are two additional declarations:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; @WebMethod(operationName = "getExchangeRate")&lt;br /&gt; @RequestWrapper(localName = "getExchangeRate", targetNamespace = "http://async.ws.adamsresearch.com/", className = "com.adamsresearch.ws.async.generated.GetExchangeRate")&lt;br /&gt; @ResponseWrapper(localName = "getExchangeRateResponse", targetNamespace = "http://async.ws.adamsresearch.com/", className = "com.adamsresearch.ws.async.generated.GetExchangeRateResponse")&lt;br /&gt; public Response&lt;getexchangerateresponse&gt; getExchangeRateAsync(&lt;br /&gt;     @WebParam(name = "arg0", targetNamespace = "")&lt;br /&gt;     String arg0,&lt;br /&gt;     @WebParam(name = "arg1", targetNamespace = "")&lt;br /&gt;     String arg1);&lt;br /&gt;&lt;br /&gt; @WebMethod(operationName = "getExchangeRate")&lt;br /&gt; @RequestWrapper(localName = "getExchangeRate", targetNamespace = "http://async.ws.adamsresearch.com/", className = "com.adamsresearch.ws.async.generated.GetExchangeRate")&lt;br /&gt; @ResponseWrapper(localName = "getExchangeRateResponse", targetNamespace = "http://async.ws.adamsresearch.com/", className = "com.adamsresearch.ws.async.generated.GetExchangeRateResponse")&lt;br /&gt; public Future&lt;!--?--&gt; getExchangeRateAsync(&lt;br /&gt;     @WebParam(name = "arg0", targetNamespace = "")&lt;br /&gt;     String arg0,&lt;br /&gt;     @WebParam(name = "arg1", targetNamespace = "")&lt;br /&gt;     String arg1,&lt;br /&gt;     @WebParam(name = "asyncHandler", targetNamespace = "")&lt;br /&gt;     AsyncHandler&lt;getexchangerateresponse&gt; asyncHandler);&lt;br /&gt;&lt;/getexchangerateresponse&gt;&lt;/getexchangerateresponse&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;What happened here is that we got two additional options to retrieve the data -- one which returns a pollable object, and one which allows you to specify an asynchronous handler (note that &lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;Response&lt;/span&gt;&lt;span style="font-family:georgia;"&gt; is a subinterface of &lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;Future&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family:georgia;" &gt;Implement the client-side logic&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;At this point, you're probably wondering why we will be invoking an asynchronous operation when we haven't yet implemented it on the server.  Bear with me for a moment, while we write our client.&lt;br /&gt;&lt;br /&gt;Here's my version of a client which exercises the three different available method signatures.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;package com.adamsresearch.ws.async;&lt;br /&gt;&lt;br /&gt;import java.net.MalformedURLException;&lt;br /&gt;import java.net.URL;&lt;br /&gt;import javax.xml.namespace.QName;&lt;br /&gt;import javax.xml.ws.AsyncHandler;&lt;br /&gt;import javax.xml.ws.Response;&lt;br /&gt;import com.adamsresearch.ws.async.generated.ExchangeRate;&lt;br /&gt;import com.adamsresearch.ws.async.generated.ExchangeRateService;&lt;br /&gt;import com.adamsresearch.ws.async.generated.GetExchangeRateResponse;&lt;br /&gt;&lt;br /&gt;public class ExchangeRateClient&lt;br /&gt;{&lt;br /&gt;protected ExchangeRateClient theClient = null;&lt;br /&gt;protected String wsdlUrl = null;&lt;br /&gt;protected double rate = 0.0d;&lt;br /&gt;ExchangeRate excRate = null;&lt;br /&gt;&lt;br /&gt;public static void main(String args[]) throws MalformedURLException, InterruptedException&lt;br /&gt;{&lt;br /&gt; if (args.length != 1)&lt;br /&gt; {&lt;br /&gt;   System.out.println("Usage java -cp &amp;lt;jarFile&amp;gt; com.adamsresearch.ws.async.ExchangeRateClient serviceWsdlUrl");&lt;br /&gt;   System.exit(-1);&lt;br /&gt; }&lt;br /&gt; ExchangeRateClient client = new ExchangeRateClient(args[0]);&lt;br /&gt; Thread.sleep(5000L);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public ExchangeRateClient(String urlStr) throws MalformedURLException&lt;br /&gt;{&lt;br /&gt; theClient = this;&lt;br /&gt; wsdlUrl = urlStr;&lt;br /&gt; URL url = new URL(wsdlUrl);&lt;br /&gt; QName qname = new QName("http://async.ws.adamsresearch.com/", "ExchangeRateService");&lt;br /&gt; ExchangeRateService exchangeRateService = new ExchangeRateService(url, qname);&lt;br /&gt; excRate = exchangeRateService.getExchangeRatePort();&lt;br /&gt;&lt;br /&gt; // synchronous:&lt;br /&gt; System.out.println("Airstrip One / Ganymede exchange rate, retrieved synchronously, is: " + excRate.getExchangeRate("AS1", "GMD"));&lt;br /&gt;&lt;br /&gt; // asynchronous with polling:&lt;br /&gt; try&lt;br /&gt; {&lt;br /&gt;   Response&lt;getexchangerateresponse&gt; = excRate.getExchangeRateAsync("AS1", "GMD");&lt;br /&gt;   Thread.sleep (2000L);&lt;br /&gt;   GetExchangeRateResponse output = response.get();&lt;br /&gt;   System.out.println("--&amp;gt; retrieved via polling: " + output.getReturn());&lt;br /&gt; }&lt;br /&gt; catch (Exception exc)&lt;br /&gt; {&lt;br /&gt;   System.out.println(exc.getClass().getName() + " polling for response: " + exc.getMessage());&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // asynchronous with callback:&lt;br /&gt; excRate.getExchangeRateAsync("AS1", "GMD", new AsyncHandler&lt;getexchangerateresponse&gt;()&lt;br /&gt; {&lt;br /&gt;   public void handleResponse(Response&lt;getexchangerateresponse&gt; response)&lt;br /&gt;   {&lt;br /&gt;     System.out.println("In AsyncHandler");&lt;br /&gt;     try&lt;br /&gt;     {&lt;br /&gt;       theClient.setCurrencyExchangeRate(response.get().getReturn());&lt;br /&gt;     }&lt;br /&gt;     catch (Exception exc)&lt;br /&gt;     {&lt;br /&gt;         System.out.println(exc.getClass().getName() + " using callback for response:" + exc.getMessage());&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; });&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;protected void setCurrencyExchangeRate(double newRate)&lt;br /&gt;{&lt;br /&gt;   rate = newRate;&lt;br /&gt;   System.out.println("--&amp;gt; via callback, updated exchange rate to " + rate);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/getexchangerateresponse&gt;&lt;/getexchangerateresponse&gt;&lt;/getexchangerateresponse&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;span style="font-family:courier new;"&gt;Thread.sleep()&lt;/span&gt; in &lt;span style="font-  family:courier new;"&gt;main&lt;/span&gt; is just to make sure we're still around when the web service responds.  Finally, invoking the client:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;c:\dev\AsyncWSDev\AsyncClient&amp;gt;java -cp target\ExchangeRateWebService.jar&lt;br /&gt;com.adamsresearch.ws.async.ExchangeRateClient http://localhost:8282/exchangeRateService?wsdl&lt;br /&gt;Airstrip One / Ganymede exchange rate, retrieved synchronously, is: 2.78&lt;br /&gt;--&amp;gt; retrieved via polling: 2.78&lt;br /&gt;In AsyncHandler&lt;br /&gt;--&amp;gt; via callback, updated exchange rate to 2.78&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;So there we have it -- a Java SE client which hits a Java SE web service three ways:  synchronously, asynchronously with polling, and asynchronously with a callback handler.&lt;br /&gt;&lt;br /&gt;There's a lot to discuss about these results, some of which, frankly, I did not expect (for example, why did we not have to explicitly implement asynchronous service-side logic?).  That is the topic of &lt;a href="http://wayne-adams.blogspot.com/2012/01/asynchronous-java-se-web-services-2.html"&gt;another post&lt;/a&gt;, which I hope you'll find interesting, too.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-459203390137524766?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/459203390137524766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2012/01/asynchronous-java-se-web-services-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/459203390137524766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/459203390137524766'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2012/01/asynchronous-java-se-web-services-1.html' title='Asynchronous Java SE Web Services:  1.  Implementation'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-3147686888920389448</id><published>2012-01-04T20:13:00.001-08:00</published><updated>2012-01-05T00:03:46.830-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java SE web service'/><category scheme='http://www.blogger.com/atom/ns#' term='Endpoint'/><category scheme='http://www.blogger.com/atom/ns#' term='JAX-WS'/><category scheme='http://www.blogger.com/atom/ns#' term='asynchronous'/><title type='text'>Asynchronous Java SE Web Services:  2.  Discussion</title><content type='html'>&lt;span style="font-family:georgia;"&gt;In an &lt;a href="http://wayne-adams.blogspot.com/2012/01/asynchronous-java-se-web-services-1.html"&gt;earlier post&lt;/a&gt;, we stepped through the building of an asynchronous web service, deployed in Java SE.  I saved my comments for this post to keep things a little cleaner.  But there are some loose ends to discuss, especially when you hear my motivation for building an asynchronous web service in the first place.&lt;br /&gt;&lt;br /&gt;Normally, you want to invoke a service asynchronously because you expect potentially long server response times.  This, I would think, is the most likely reason for wanting asynchronous invocation. For example, in a user-facing application, you don't want to block on a call, especially if your front end has other things it could be doing.&lt;br /&gt;&lt;br /&gt;Lately, I've been spending a lot of time on "server push" applications, using frameworks like DWR (Direct Web Remoting) and CometD; these frameworks provide a clean façade for logic which either maintains long-lived HTTP connections or polls for data, for example.  I'd rather not have to rely on a servlet-based framework to do this, however; if possible, I'd prefer to simply leverage the Java SE.  So my ulterior motive was to see if I  could use it to implement server push.  Unfortunately, server push and asynchronous response are not equivalent, of course, although there's some obvious overlap.  The overlap lies in that first (and, for async, only) response.&lt;br /&gt;&lt;br /&gt;What I found most interesting about this exercise is that &lt;span&gt;the asynchronous logic (at least, the logic visible to us, the developers)&lt;/span&gt;&lt;span style="font-style: italic;"&gt; was manifested only on the client side&lt;/span&gt;.  In other words, the asynchronous versions of the operation were entirely a&lt;span style="font-style: italic;"&gt; client-side artifact&lt;/span&gt; -- we did nothing on the web-service side to implement asynchronicity!  I did not expect that result.  We just implemented a synchronous Java method on the service side, and&lt;span style="font-style: italic;"&gt; &lt;/span&gt;the Java SE runtime took care of the asynchronous-invocation details for us, &lt;span style="font-style: italic;"&gt;simply by virtue of our using the asynchronous operations of the client-side API&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I really expected, when I started this exercise, that I would generate asynchronous service-side stubs and actually implement the asynchronous logic myself.  In that case, it would have been natural to assume that I could play some neat trick and continue sending data "down the pipe", rather than providing just one response and seeing the connection get closed afterwards.  I'm not sure how I thought I was going to do this (groundless optimism?), but I planned on figuring that out once I got the basics working.&lt;br /&gt;&lt;br /&gt;What we ended up with is exactly what JAX-WS advertised, and that is actually quite handy; all you have to do is to make the asynchronous call and you can go on with whatever else you need to do; the runtime takes the response, when it returns, and updates your pollable object (or calls your callback).&lt;br /&gt;&lt;br /&gt;One thing that is appealing about this result is that you really don't need to build your web service by starting with a WSDL file, since the asynchronicity is purely a client-side artifact.  In other words, if you prefer to start with a Java bean and use &lt;span style="font-family:courier new;"&gt;wsgen&lt;/span&gt; to generate the web service, that is fine -- you don't need to do anything else on the service side to support asynchronous invocation.  It's only when you create the &lt;span style="font-style: italic;"&gt;client&lt;/span&gt; that you need to worry about asynchronous invocation, but by then you already have a deployed web service, so you can generate the client-side, asynchronous API by running &lt;span style="font-family:courier new;"&gt;wsimport&lt;/span&gt; against the deployed web service's published WSDL file.  Overall, a rather convenient result!&lt;br /&gt;&lt;br /&gt;So, to recap:&lt;br /&gt;&lt;/span&gt;&lt;ol&gt;&lt;li&gt;JAX-WS in the Java SE provides relatively straightforward support for asynchronous web-service development.  The service can be developed starting Java-first or WSDL-first, as the asynchronicity doesn't come into play until the client-side artifacts are generated.&lt;/li&gt;&lt;li&gt;JAX-WS does not (as far as I know at this point) support the concept of server push, by which I mean a long-lived output stream over which data can be pushed to the client.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-3147686888920389448?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/3147686888920389448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2012/01/asynchronous-java-se-web-services-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3147686888920389448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3147686888920389448'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2012/01/asynchronous-java-se-web-services-2.html' title='Asynchronous Java SE Web Services:  2.  Discussion'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-7965351912144543645</id><published>2011-12-17T11:11:00.000-08:00</published><updated>2011-12-17T17:05:58.680-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDI'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Debug Interface'/><title type='text'>Examining variables in JDI</title><content type='html'>As I have mentioned in earlier posts, I am using the Java Debug Interface (JDI) to create a Java process-monitoring tool.  I'm retracing my steps from an earlier such effort a few years ago, and as I wade through the details, I'm posting details in the hope they'll be helpful to someone else out there.  I sometimes wonder who would really be interested in this material, but I have been noticing that my old posts on JDI, &lt;span style="font-family:courier new;"&gt;DTrace&lt;/span&gt;, etc. continue to get hits every week, even the old ones, so I know you're out there.  I hope you find this article helpful, too.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Current Status:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At this stage in the development of my application, I have set up breakpoint requests and am stepping through events as they arrive.  You'd probably do this in a loop similar to the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  EventQueue evtQueue = virtualMachine.eventQueue();&lt;br /&gt;  EventSet evtSet = null;&lt;br /&gt;  while (!stopRequested)&lt;br /&gt;  {&lt;br /&gt;      try&lt;br /&gt;      {&lt;br /&gt;          evtSet = evtQueue.remove();&lt;br /&gt;          EventIterator evtIter = evtSet.eventIterator();&lt;br /&gt;          while (evtIter.hasNext())&lt;br /&gt;          {&lt;br /&gt;          ...&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;      catch (Exception exc)&lt;br /&gt;      {&lt;br /&gt;          ...&lt;br /&gt;      }&lt;br /&gt;      finally&lt;br /&gt;      {&lt;br /&gt;          evtSet.resume();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;In my application, I handle debugger events in a thread, so I need a way for the thread to know if it should stop (that's the purpose of the boolean &lt;span style="font-family:courier new;"&gt;stopRequested&lt;/span&gt;).  Note that an &lt;span style="font-family:courier new;"&gt;EventSet&lt;/span&gt; actually contains an &lt;span style="font-family:courier new;"&gt;EventIterator&lt;/span&gt; which can contain several events.  Also note that it is quite important to ensure that &lt;span style="font-family:courier new;"&gt;resume()&lt;/span&gt; is always called on the &lt;span style="font-family:courier new;"&gt;EventSet&lt;/span&gt;, regardless of any exceptions that are thrown.  Otherwise, you could end up with some permanently hung threads and have to restart your target application.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Inspecting Variables:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At a breakpoint, you'll probably want to extract some of the current state of your target application.  There are two places to find variables in the JDI API -- instance/class variables, and the stack.  Static and instance variables can always be listed by inspecting the class's &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; -- they're always there, as long as the class is loaded, even if the application isn't running (you may still have to be at a breakpoint to look at their values, of course, but the point is you can also see what a class's static and instance variables are simply by looking at its definition).&lt;br /&gt;&lt;br /&gt;On the other hand, the stack variables aren't defined unless you are, well, on the stack where they're defined (e.g. local variables in a method).  In JDI, you find these two types of variables in different parts of the API, in locations which will make sense to you as we continue our discussion.  You see the same division in a debugger.  For example in Eclipse, when you are at a breakpoint and look at the "Variables" window, you will see class/instance variables in a tree structure under "&lt;span style="font-family:courier new;"&gt;this&lt;/span&gt;", and all local (stack) variables listed peer-level to "&lt;span style="font-family: courier new;"&gt;this&lt;/span&gt;" under their local names.&lt;br /&gt;&lt;br /&gt;The following sections assume that you have extracted an &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt; from an &lt;span style="font-family:courier new;"&gt;EventIterator&lt;/span&gt;, verified that it is a &lt;span style="font-family:courier new;"&gt;BreakpointEvent&lt;/span&gt;, extracted the &lt;span style="font-family:courier new;"&gt;EventRequest&lt;/span&gt; from the &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;, and verified that it is a &lt;span style="font-family:courier new;"&gt;BreakpointRequest&lt;/span&gt; (these are all JDI classes).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;Inspecting Static and Instance Variables:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Given a &lt;span style="font-family:courier new;"&gt;BreakpointEvent&lt;/span&gt; and a variable name (defined in your  breakpoint request specification), how would you search for the variable  in the static and instance variables list?  Every &lt;span style="font-family:courier new;"&gt;BreakpointEvent&lt;/span&gt; has a &lt;span style="font-family:courier new;"&gt;Location&lt;/span&gt; (obtained via the &lt;span style="font-family:courier new;"&gt;location()&lt;/span&gt; method).  In addition to having the usual information you would expect a &lt;span style="font-family:courier new;"&gt;Location&lt;/span&gt; object to have (the name of the source, the line number, method name, etc.), a &lt;span style="font-family:courier new;"&gt;Location&lt;/span&gt; has a reference to the class's &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt;.  The &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; has a method called &lt;span style="font-family:courier new;"&gt;allFields()&lt;/span&gt; which, as the API documentation says, "&lt;span style="font-style: italic;"&gt;Returns a list containing each &lt;span style="font-family: courier new;"&gt;Field&lt;/span&gt; &lt;/span&gt;&lt;span style="font-style: italic;"&gt;declared in this type,  and its superclasses, implemented interfaces, and/or superinterfaces.  All declared and inherited  fields are included, regardless of whether they are hidden or   multiply inherited.&lt;/span&gt;  "  Exactly what you want, right?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;allFields()&lt;/span&gt; returns a &lt;span style="font-family:courier new;"&gt;List&lt;field&gt;&lt;/field&gt;&lt;/span&gt;.  The JDI &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt; type has a name field (method: &lt;span style="font-family:courier new;"&gt;name()&lt;/span&gt;) which can be used, while iterating over the &lt;span style="font-family:courier new;"&gt;List&lt;/span&gt;, to find the target variable.  Once you have retrieved the correct &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;, you get its &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt; by appealing to the &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; again, as in:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     Value val = theReferenceType.getValue(theField);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The only other detail at this point is actually extracting the value of the &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt;.  This is a slightly messy topic, which we'll discuss after we look at the other location of variables -- the stack.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;Inspecting Stack Variables:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Stack variables, and specifically their values at your breakpoint, are associated with the JDI &lt;span style="font-family:courier new;"&gt;StackFrame&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;Frame&lt;/span&gt; classes.  They are referred to as &lt;span style="font-family:courier new;"&gt;LocalVariable&lt;/span&gt;s in JDI, you get reach them through the &lt;span style="font-family:courier new;"&gt;BreakpointEvent&lt;/span&gt;, by accessing its &lt;span style="font-family:courier new;"&gt;ThreadReference&lt;/span&gt;, then the &lt;span style="font-family:courier new;"&gt;StackFrame&lt;/span&gt; at the top level (that is, element #0) of the stack.  You can then query the visible variables on the &lt;span style="font-family:courier new;"&gt;StackFrame&lt;/span&gt; by name to find the target variable.  In other words, you could do something like this:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; StackFrame stackFrame = breakpointEvt.thread().frame(0);&lt;br /&gt; LocalVariable localVar = stackFrame.visibleVariableByName(varName);&lt;br /&gt; Value val = stackFrame.getValue(localVar);&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Note that you must get the &lt;span style="font-family:courier new;"&gt;LocalVariable&lt;/span&gt; from the &lt;span style="font-family:courier new;"&gt;StackFrame&lt;/span&gt;, but having retrieved it, you must again access the &lt;span style="font-family:courier new;"&gt;StackFrame&lt;/span&gt; to get the &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt; of the &lt;span style="font-family:courier new;"&gt;LocalVariable&lt;/span&gt;.  Note also that we are now at the same stage we were with class/instance variables -- we have a &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt;, but we need to find out what its "value" is.  As I said, this is a little messy and is the subject of the next section.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Extracting Values:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In JDI, a &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt; isn't just something you can meaningfully display with &lt;span style="font-family:courier new;"&gt;toString()&lt;/span&gt; (unless you find hash codes especially meaningful).  The JDI API documentation contains a very useful table under &lt;span style="font-family:courier new;"&gt;com.sun.jdi.Value&lt;/span&gt; which describes the family of subinterfaces of &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt;.  Basically, all the interfaces which represent a usable value contain a &lt;span style="font-family:courier new;"&gt;value()&lt;/span&gt; method, but this method is only defined in the sub-interfaces (since not all of them define one).  This means that if you want to inspect a &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt; that at heart is a boolean, or a &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt;, you can call &lt;span style="font-family:courier new;"&gt;value()&lt;/span&gt; on it, but you must first determine if it is an instance of the type you need, then cast it to that type and call &lt;span style="font-family:courier new;"&gt;value()&lt;/span&gt; on the cast instance.  I don't know if there's any more practical way to do this that doesn't involve writing extremely clever (in other words, unmaintainable) code, so here's how I do it:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  if (value instanceof BooleanValue)&lt;br /&gt;  {&lt;br /&gt;    return ((BooleanValue)value).value();&lt;br /&gt;  }&lt;br /&gt;  else if (value instanceof ByteValue)&lt;br /&gt;  {&lt;br /&gt;    return ((ByteValue)value).value();&lt;br /&gt;  }&lt;br /&gt;  ...&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and so on.&lt;br /&gt;&lt;br /&gt;There are two main subinterfaces of &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt; -- &lt;span style="font-family:courier new;"&gt;PrimitiveValue&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;ObjectReference&lt;/span&gt;, along with a little more hierarchy which will be important to you.  For example, if you are using code such as the example above to extract values, you will want to check for &lt;span style="font-family:courier new;"&gt;StringReference&lt;/span&gt; &lt;span style="font-style: italic;"&gt;before&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;ObjectReference&lt;/span&gt;.  Why?  &lt;span style="font-family:courier new;"&gt;StringReference&lt;/span&gt; has a &lt;span style="font-family:courier new;"&gt;value()&lt;/span&gt; method, as you would expect and hope, but &lt;span style="font-family:courier new;"&gt;StringReference&lt;/span&gt; is a subinterface of &lt;span style="font-family:courier new;"&gt;ObjectReference&lt;/span&gt;, which does &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; have a &lt;span style="font-family:courier new;"&gt;value()&lt;/span&gt; method.  If you check for &lt;span style="font-family:courier new;"&gt;ObjectReference&lt;/span&gt; first, and you're looking at a &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt;, you will miss out on the available cast to &lt;span style="font-family:courier new;"&gt;StringReference&lt;/span&gt; and miss out on a chance to inspect the value (yes, I accidentally did this; I did it this time, and I remembered when I did it that I did the same thing a few years ago).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Drill-down:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you, too, are writing what I would call a "real-time" JDI-based tool, you'll probably want to provide some drill-down at a breakpoint.  For example, you might want to look at a specific field of a variable on the stack, rather than just the &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt; of the variable.  The way I handle this is to allow a "dot" notation, where "&lt;span style="font-family:courier new;"&gt;a.b.c&lt;/span&gt;" allows my users to specify that they want to look at field &lt;span style="font-family:courier new;"&gt;c&lt;/span&gt; of field &lt;span style="font-family:courier new;"&gt;b&lt;/span&gt; of variable/field &lt;span style="font-family:courier new;"&gt;a&lt;/span&gt;.  Things get a little interesting here, too, as the following example illustrates.&lt;br /&gt;&lt;br /&gt;Suppose you are monitoring the traffic of an application and you just want to know the length of &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt;s being processed (e.g. returned from a service) at a breakpoint.  You don't really want to display the &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt; itself; this could be enormous (and remember, your target application is halted while this breakpoint is being processed, so I/O on a large &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt; could cripple the application).  All you want to know is the length of the &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt;.  But you don't want to write code to actually invoke general methods on your stack/instance variables.  And in this particular case, there is a field available to you from JDI on the &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt; class -- &lt;span style="font-family:courier new;"&gt;count&lt;/span&gt;.  So your users should be able to specify, for example, &lt;span style="font-family:courier new;"&gt;incomingMessage.count&lt;/span&gt;, and get back an integer with the length of the &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The only problem is, not everyone knows that there is a field in &lt;span style="font-family:courier new;"&gt;java.lang.String&lt;/span&gt; called &lt;span style="font-family:courier new;"&gt;count&lt;/span&gt; -- they're more accustomed to calling the method &lt;span style="font-family:courier new;"&gt;length()&lt;/span&gt;.  In an interactive debugger, this issue isn't a problem, as you don't specify what you want in advance -- you just inspect the state when the breakpoint occurs, and the debugger will show all the fields for you.  In a debugger of the type I'm developing, users would need to know what is available.  For a stack variable, this is a problem because you can't inspect it until the application is running.  For class/instance variables, once you have the &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; of the class, you can at least inspect those variables and drill down at will.&lt;br /&gt;&lt;br /&gt;The way I'm handling this issue (for stack variables) is to provide a diagnostic version of a breakpoint request, where the user can request a dump of the variables on the stack, to a specified depth.  Note such a feature should be used with some care; an application with a very large number of stack variables, all traversed to (say) 10 levels deep, can end up being suspended for seconds, minutes, or tens of minutes just dumping the state of the stack (yes, I've done that before too, but will not repeat that this time!).  Suffice to say that if you want to inspect an application for nested variables, you should do so on a non-production system.&lt;br /&gt;&lt;br /&gt;How do you drill down into fields?  Unsurprisingly, there's a different procedure for class/instance variables than for stack variables.  Unfortunately, some things in JDI are not immediately obvious (in fact, every time I write code to do this, I have to "re-discover" how to do it), which is why I illustrate below.&lt;br /&gt;&lt;br /&gt;For class/instance variables, you got the fields by getting the &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; and looking at its &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;s.  Having retrieved a reference to the &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;, you can simply repeat the process -- there is no method on the &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt; itself to drill down, but you can get the &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; of each &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt; and then get the &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;s of each &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt; from each &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;'s &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt;.  Here's an example:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;   List childFields = bpEvt.location().declaringType().allFields();&lt;br /&gt;   for (Field childField: childFields)&lt;br /&gt;   {&lt;br /&gt;     List grandChildFields = childField.declaringType().allFields();&lt;br /&gt;     for (Field grandChildField: grandChildFields)&lt;br /&gt;     {&lt;br /&gt;       System.out.println(grandChildField.name() + " is a grandchild field");&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The situation for stack variables is as follows.  If you are trying to drill down into a variable, by definition it is an &lt;span style="font-family:courier new;"&gt;ObjectReference&lt;/span&gt;, right?  In other words, there's no drilling down into a primitive.  If the &lt;span style="font-family:courier new;"&gt;Value&lt;/span&gt; on the &lt;span style="font-family:courier new;"&gt;StackFrame&lt;/span&gt; is an instance of an &lt;span style="font-family:courier new;"&gt;ObjectReference&lt;/span&gt;, then you can get the &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; of the &lt;span style="font-family:arial;"&gt;Value&lt;/span&gt; and retrieve its &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;s just as we did above when we retrieved the &lt;span style="font-family:courier new;"&gt;ReferenceType&lt;/span&gt; of the class/instance &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;.  Note that since &lt;span style="font-family:courier new;"&gt;StringReference&lt;/span&gt; is a subinterface of &lt;span style="font-family:courier new;"&gt;ObjectReference&lt;/span&gt;, we could do something like the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    else if (value instanceof StringReference)&lt;br /&gt;    {&lt;br /&gt;      // look at the fields:&lt;br /&gt;      List childFields = ((StringReference) value).referenceType().allFields();&lt;br /&gt;      for (Field childField: childFields)&lt;br /&gt;      {&lt;br /&gt;        System.out.println("&amp;gt;&amp;gt; child field: '" + childField.name() + "'");&lt;br /&gt;      }&lt;br /&gt;      return ((StringReference)value).value();&lt;br /&gt;    }&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If we run this code, we would see something like the following output for a &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt; child field:  'value'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt; child field:  'offset'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt; child field:  'count'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt; child field:  'hash'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt; child field:  'serialVersionUID'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt; child field:  'serialPersistentFields'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt; child field:  'CASE_INSENSITIVE_ORDER'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Note our &lt;span style="font-family: courier new;"&gt;count&lt;/span&gt; &lt;span style="font-family: courier new;"&gt;Field&lt;/span&gt;, which happens to be an &lt;span style="font-family: courier new;"&gt;IntegerValue&lt;/span&gt;).  Of course, you can continue drilling down, using the same procedure, on each of these &lt;span style="font-family:courier new;"&gt;Field&lt;/span&gt;s.&lt;br /&gt;&lt;br /&gt;That's all I have for now -- look for more in the coming weeks as the project comes along.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-7965351912144543645?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/7965351912144543645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/12/examining-variables-in-jdi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7965351912144543645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7965351912144543645'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/12/examining-variables-in-jdi.html' title='Examining variables in JDI'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-6968574952026008717</id><published>2011-12-07T20:24:00.000-08:00</published><updated>2011-12-07T23:53:33.752-08:00</updated><title type='text'>From OO to FP: Haskell I/O, Part 2</title><content type='html'>In my &lt;a href="http://wayne-adams.blogspot.com/2011/11/from-oo-to-fp-haskell-io-part-1.html"&gt;Part-1&lt;/a&gt; post on this topic, we actually did all the I/O I'm going to do here.  We lazily read in the entire sample data file, a file containing data describing events generated by a process monitor.  My next goal was to re-hydrate my &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;s from the &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt;s serialized to the file.  These &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt;s were generated by calling the function show on my &lt;span style="font-family:courier new;"&gt;List&lt;/span&gt; of &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;s.&lt;br /&gt;&lt;br /&gt;Time to back up a little.  We got &lt;span style="font-family:courier new;"&gt;show&lt;/span&gt; for free, but we had to ask for it.  Leaving aside the &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt; data type for a moment and looking at the simpler &lt;span style="font-family:courier new;"&gt;Property&lt;/span&gt; data type, remember how we defined it:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     data Property = Property {&lt;br /&gt;     key :: Key,&lt;br /&gt;     value:: Value }&lt;br /&gt;     deriving (Show)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;At that time we discussed "&lt;span style="font-family:courier new;"&gt;deriving (Show)&lt;/span&gt;" by simply noting it allowed &lt;span style="font-family:courier new;"&gt;ghci&lt;/span&gt; to know how to output &lt;span style="font-family:courier new;"&gt;Property&lt;/span&gt; values.  Of course, there's more to it than that.  The "more" is Haskell typeclasses.  A Haskell typeclass defines a set of functions that can be defined to operate on a data type.  The &lt;span style="font-family:courier new;"&gt;show&lt;/span&gt; function is a member of the &lt;span style="font-family:courier new;"&gt;Show&lt;/span&gt; typeclass and has the following type:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     *EventProcessor&amp;gt; :type show&lt;br /&gt;   show :: Show a =&amp;gt; a -&amp;gt; String&lt;/tt&gt;&lt;/pre&gt;For a moment, let's see what had happened if we had not specified that &lt;span style="font-family:courier new;"&gt;Property&lt;/span&gt; derives &lt;span style="font-family:courier new;"&gt;Show&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     -- file:  c:/HaskellDev/eventProcessor/simpleProperty.hs&lt;br /&gt;  type Key = String&lt;br /&gt;  type Value = String&lt;br /&gt;  data Property = Property {&lt;br /&gt;    key :: Key,&lt;br /&gt;    value:: Value }&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;If we load this file, then create a &lt;span style="font-family:courier new;"&gt;Property&lt;/span&gt;, then try to &lt;span style="font-family:courier new;"&gt;show&lt;/span&gt; it, we see the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     Prelude&amp;gt; :load simpleProperty.hs&lt;br /&gt;   [1 of 1] Compiling Main             ( simpleProperty.hs, interpreted )&lt;br /&gt;   Ok, modules loaded: Main.&lt;br /&gt;   *Main&amp;gt; let prop1 = Property "key1" "value1"&lt;br /&gt;   *Main&amp;gt; show prop1&lt;br /&gt;   &lt;interactive&gt;:1:1:&lt;br /&gt;   No instance for (Show Property)&lt;br /&gt;     arising from a use of `show'&lt;br /&gt;   Possible fix: add an instance declaration for (Show Property)&lt;br /&gt;   In the expression: show prop1&lt;br /&gt;   In an equation for `it': it = show prop1&lt;br /&gt;&lt;/interactive&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;That's considerably more helpful than a typical compiler error message.  The key is the hint to add an instance declaration.  In order for the functions of a typeclass to be applicable to your data type, you need to declare an instance of that typeclass that handles your data type.  In our case, we can get &lt;span style="font-family:courier new;"&gt;Show&lt;/span&gt; simply by stating that we derive it.  So we go back to our old definition:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     -- file:  c:/HaskellDev/eventProcessor/simpleProperty.hs&lt;br /&gt;   type Key = String&lt;br /&gt;   type Value = String&lt;br /&gt;   data Property = Property {&lt;br /&gt;     key :: Key,&lt;br /&gt;     value:: Value }&lt;br /&gt;     deriving (Show)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Repeating our earlier test, now we get the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     *Main&amp;gt; :load simpleProperty.hs&lt;br /&gt;   [1 of 1] Compiling Main             ( simpleProperty.hs, interpreted )&lt;br /&gt;   Ok, modules loaded: Main.&lt;br /&gt;   *Main&amp;gt; let prop1 = Property "key1" "value1"&lt;br /&gt;   *Main&amp;gt; show prop1&lt;br /&gt;   "Property {key = \"key1\", value = \"value1\"}"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;That's definitely an improvement.  But, back to the subject -- what I want is to be able to read a &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt; and turn it in to a &lt;span style="font-family:courier new;"&gt;Property&lt;/span&gt;.  First, let's try to read a &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt; into an &lt;span style="font-family:courier new;"&gt;Integer&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     *Main&amp;gt; read "5"&lt;br /&gt;   &lt;interactive&gt;:1:1:&lt;br /&gt;   Ambiguous type variable `a0' in the constraint:&lt;br /&gt;   Read a0) arising from a use of `read'&lt;br /&gt;   Probable fix: add a type signature that fixes these type variable(s)&lt;br /&gt;   In the expression: read "5"&lt;br /&gt;   In an equation for `it': it = read "5"&lt;br /&gt;&lt;/interactive&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Again, a helpful hint from &lt;span style="font-family:courier new;"&gt;ghci&lt;/span&gt;.  It basically doesn't know what we are trying to create and suggests adding a type signature.  Here's how you would do it:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     *Main&amp;gt; let anInt = (read "5")::Integer&lt;br /&gt;   *Main&amp;gt; :type anInt&lt;br /&gt;   anInt :: Integer&lt;br /&gt;   *Main&amp;gt; show anInt&lt;br /&gt;   "5"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Haskell now knows we're trying to read an &lt;span style="font-family:courier new;"&gt;Integer&lt;/span&gt;, so it recognizes that &lt;span style="font-family:courier new;"&gt;anInt&lt;/span&gt; is an &lt;span style="font-family:courier new;"&gt;Integer&lt;/span&gt; and knows how to &lt;span style="font-family:courier new;"&gt;show&lt;/span&gt; it.  All of this should tell you that &lt;span style="font-family:courier new;"&gt;Integer&lt;/span&gt; has defined instances for both &lt;span style="font-family:courier new;"&gt;Show&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;Read&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Can we get &lt;span style="font-family:courier new;"&gt;Read&lt;/span&gt; "for free" simply by stating that our data type derives it?  It can't hurt to try:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     -- file:  c:/HaskellDev/eventProcessor/simpleProperty.hs&lt;br /&gt;   type Key = String&lt;br /&gt;   type Value = String&lt;br /&gt;   data Property = Property {&lt;br /&gt;     key :: Key,&lt;br /&gt;     value:: Value }&lt;br /&gt;     deriving (Read, Show)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Next, I'll create a &lt;span style="font-family:courier new;"&gt;Property&lt;/span&gt; and output it with &lt;span style="font-family:courier new;"&gt;show&lt;/span&gt;, then see if that format (which, incidentally, is how I created my sample &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt; file -- using show on a &lt;span style="font-family:courier new;"&gt;List&lt;/span&gt; of &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;s) is "&lt;span style="font-family:courier new;"&gt;read&lt;/span&gt;"-able:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;   *Main&amp;gt; let prop1 = Property "key1" "value1"&lt;br /&gt;   *Main&amp;gt; show prop1&lt;br /&gt;   "Property {key = \"key1\", value = \"value1\"}"&lt;br /&gt;   *Main&amp;gt; let prop2 = (read "Property {key = \"key1\", value = \"value1\"}")::Property&lt;br /&gt;   *Main&amp;gt; show prop2&lt;br /&gt;   "Property {key = \"key1\", value = \"value1\"}"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;This is great news -- I didn't have to write a parser, and I'm perfectly happy to use, as my format, the same format that Haskell uses to &lt;span style="font-family:courier new;"&gt;show&lt;/span&gt; a Haskell data structure.&lt;br /&gt;&lt;br /&gt;What I would really like to do is to be able to read a full &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;, as defined in my earlier posts, including a &lt;span style="font-family:courier new;"&gt;List&lt;/span&gt; of &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;s.  Here's an example &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     "Event {timestamp = 1320512200548, className = \"java.lang.String\", lineNumber = 1293, message = \"NPE in substring()\", properties = [Property {key = \"userId\", value = \"smith\"},Property {key = \"sessionId\", value = \"ABCD1234\"}]}"&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Let's try the same trick with &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt; that we used with &lt;span style="font-family:courier new;"&gt;Property&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     -- file:  c:/HaskellDev/eventProcessor/notSoSimpleProperty.hs&lt;br /&gt;&lt;br /&gt;   type Timestamp = Integer&lt;br /&gt;   type ClassName = String&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;     &lt;/tt&gt;&lt;tt&gt;type LineNumber = Integer&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;     &lt;/tt&gt;&lt;tt&gt;type Message = String&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;     &lt;/tt&gt;&lt;tt&gt;type Key = String&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;     &lt;/tt&gt;&lt;tt&gt;type Value = String&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;     &lt;/tt&gt;&lt;tt&gt;type Properties = [Property]&lt;br /&gt;&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;     &lt;/tt&gt;&lt;tt&gt;data Property = Property {&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;key :: Key,&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;value:: Value }&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;deriving (Read, Show)&lt;br /&gt;&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;     &lt;/tt&gt;&lt;tt&gt;data Event = Event {&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;timestamp :: Timestamp,&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;className :: ClassName,&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;lineNumber :: LineNumber,&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;message :: Message,&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;properties :: Properties }&lt;br /&gt;&lt;/tt&gt;&lt;tt&gt;       &lt;/tt&gt;&lt;tt&gt;deriving (Read, Show)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Was it enough simply to declare that &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt; derives &lt;span style="font-family:courier new;"&gt;Show&lt;/span&gt;?  Let's see:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     *EventProcessor&amp;gt; :load notSoSimpleProperty.hs&lt;br /&gt;   [1 of 1] Compiling Main             ( notSoSimpleProperty.hs, interpreted )&lt;br /&gt;   Ok, modules loaded: Main.&lt;br /&gt;   *Main&amp;gt; let event1 = (read "Event {timestamp = 1320512200548, className = \"java.lang.String\", lineNumber = 1293, message = \"NPE in substring()\", properties = [Property {key = \"userId\", value = \"smith\"},Property {key = \"sessionId\", value = \"ABCD1234\"}]}")::Event&lt;br /&gt;   *Main&amp;gt; show event1&lt;br /&gt;   "Event {timestamp = 1320512200548, className = \"java.lang.String\", lineNumber = 1293, message = \"NPE in substring()\", properties = [Property {key = \"userId\", value = \"smith\"},Property {key = \"sessionId\", value = \"ABCD1234\"}]}"&lt;br /&gt;   *Main&amp;gt; show (properties event1)&lt;br /&gt;   "[Property {key = \"userId\", value = \"smith\"},Property {key = \"sessionId\", value = \"ABCD1234\"}]"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;This is great.  We can take a &lt;span style="font-family:courier new;"&gt;String&lt;/span&gt; representation of an &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;, as output by &lt;span style="font-family:courier new;"&gt;show&lt;/span&gt;, and use it directly with &lt;span style="font-family:courier new;"&gt;read&lt;/span&gt; to instantiate an &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt; variable.&lt;br /&gt;&lt;br /&gt;This discussion in no way described how to provide an instance of a typeclass; maybe in another post.  Right now I still want to create &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;s from my sample &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt; file.&lt;br /&gt;&lt;br /&gt;My first cut at this is the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;   import System.IO&lt;br /&gt;   import EventProcessor&lt;br /&gt;&lt;br /&gt;   main :: IO ()&lt;br /&gt;   main = do&lt;br /&gt;    inh &amp;lt;- openFile "sampleEvents" ReadMode&lt;br /&gt;    inContents &amp;lt;- hGetContents inh&lt;br /&gt;    let eventList = processData (lines inContents)&lt;br /&gt;    hClose inh&lt;br /&gt;&lt;br /&gt;   processData :: [String] -&amp;gt; [Event]&lt;br /&gt;   processData = map createEvent&lt;br /&gt;&lt;br /&gt;   createEvent :: String -&amp;gt; Event&lt;br /&gt;   createEvent event = (read event)::Event&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;While this appears to be correct, it doesn't do anything that proves I've been able to parse my example-file lines into a &lt;span style="font-family:courier new;"&gt;List&lt;/span&gt; of &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;s.  Unfortunately, at this point I'm a little stuck, as I haven't yet figured out how to correctly extract elements from my &lt;span style="font-family:courier new;"&gt;Event&lt;/span&gt;s (I can do so interactively in &lt;span style="font-family:courier new;"&gt;ghci&lt;/span&gt;, but I am plagued by compiler errors if I try to do so in the &lt;span style="font-family:courier new;"&gt;do&lt;/span&gt; block).&lt;br /&gt;&lt;br /&gt;I'm going to leave this for a while and go back to some online resources/tutorials, then revisit.  The problem for me is that I still don't understand the I/O monad, as it's called.  It's becoming clear to me that the concept of a monad -- apparently so integral to Haskell -- isn't easily grasped, as evidenced by the overwhelming number of "Here's my take on monads" tutorials on-line (one author, I see, jokes that everyone who learns about monads appears to post a tutorial on the subject shortly thereafter).  So I'm off to the Haskell Wiki to learn about monads, then learn some more about Haskell I/O, and then pick up where I left off.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-6968574952026008717?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6968574952026008717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6968574952026008717'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/12/from-oo-to-fp-haskell-io-part-2.html' title='From OO to FP: Haskell I/O, Part 2'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-8110997209647871151</id><published>2011-11-22T11:15:00.000-08:00</published><updated>2011-12-07T22:40:49.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='I/O'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='FP'/><title type='text'>From OO to FP:  Haskell I/O, Part 1</title><content type='html'>I'm about halfway through &lt;span style="font-style: italic;"&gt;Real World Haskell&lt;/span&gt;,  and I've spent a week trying to decide when to write this post.  As the  authors point out, Haskell I/O is easy to work with.  However,  understanding the significance of what is going on in Haskell I/O  requires a little more than simply outputting "Hello, World".  The  reason:  once you include I/O, you start mixing pure and impure code,  and a good understanding of what's going on will additionally include  some discussion of monads.  While my understanding of these topics is  starting to gel, what I'm about to say should be taken (like everything  else in this series) more as a snapshot of my transition from  object-oriented, imperative-style development to functional programming,  rather than an authoritative resource.&lt;br /&gt;  &lt;br /&gt;   I'm going to continue with the example I've been using to-date, which  involves working with data that represents events coming from a  process-monitoring system.  Instead of including the events themselves  in my source code, this time I'm going to read them from a file.  Here's  a rehash of what the data structures look like. as output by &lt;span style="font-family: courier new;"&gt;ghci&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     Event {timestamp =  1320512200548, className = \"java.lang.String\", lineNumber = 1293,  message = \"NPE in substring()\", properties = [Property {key =  \"userId\", value = \"smith\"},Property {key = \"sessionId\", value =  \"ABCD1234\"}]}&lt;/tt&gt;&lt;/pre&gt;  &lt;br /&gt;   My first goal is simply to read a file of these items, one per line, and  echo them to the console.  I'm using GHC Haskell and will be using the &lt;span style="font-family: courier new;"&gt;ghci&lt;span style="font-family: georgia;"&gt; &lt;/span&gt;&lt;/span&gt;interpreter  as well.  I'm going to start with my original Haskell file (which I  won't reproduce here); suffice to say I would like to turn it into a  module and export my data type and type synonym definitions, so I can  use them from my new file processor.&lt;br /&gt;  &lt;br /&gt;   I'm starting slowly because I have to backtrack a little to fit Haskell's requirements.  My original file was called &lt;span style="font-family: courier new;"&gt;eventProcessor.hs&lt;/span&gt;,  and I see now that a Haskell module name must start with a capital  letter, and that the name of the module must match the base name of the  source file.  My first change, then, is to rename &lt;span style="font-family: courier new;"&gt;eventProcessor.hs&lt;/span&gt; to &lt;span style="font-family: courier new;"&gt;EventProcessor.hs&lt;/span&gt; (this will be enjoyable for those of you working on a Windows system).  Then, inside my file, I add the following &lt;span style="font-family: courier new;"&gt;module&lt;/span&gt; declaration at the top of my file (note: this also comes before any &lt;span style="font-family: courier new;"&gt;import&lt;/span&gt; statements):&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;module EventProcessor&lt;br /&gt;  (&lt;br /&gt;    Timestamp,&lt;br /&gt;    ClassName,&lt;br /&gt;    LineNumber,&lt;br /&gt;    Message,&lt;br /&gt;    Key,&lt;br /&gt;    Value,&lt;br /&gt;    Properties,&lt;br /&gt;    Property,&lt;br /&gt;    Event,&lt;br /&gt;    isUserWithId,&lt;br /&gt;    eventGeneratedByUser,&lt;br /&gt;    getEventsGeneratedByUser&lt;br /&gt;  ) where&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;   I've decided to export basically everything I defined in this file.   Don't forget, of course, that the above indentation of the parentheses  is significant, rather than cosmetic.  My original file also contained a  number of variable definitions.  I'll take those out once I'm convinced  I can actually retrieve them from a file!&lt;br /&gt;  &lt;br /&gt;   Leaving the EventProcessor module for a moment, let's read the contents  of my events file and output them to the screen.  This example won't do  much, but it will provide some notation we need to examine.  Here is the  source code:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;     import System.IO&lt;br /&gt;&lt;br /&gt;     main :: IO ()&lt;br /&gt;     main = do&lt;br /&gt;       inh &amp;lt;- openFile "sampleEvents" ReadMode&lt;br /&gt;       inContents &amp;lt;- hGetContents inh&lt;br /&gt;       putStrLn inContents&lt;br /&gt;       hClose inh&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;   This is the first Haskell program I have run from a console.  Note the &lt;span style="font-family: courier new;"&gt;System.IO&lt;/span&gt; import, and the familiar &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt; function.  Not as familiar -- the type of &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt;.  It is an &lt;span style="font-family: courier new;"&gt;&lt;span style="font-family: georgia;"&gt;"&lt;/span&gt;IO ()&lt;/span&gt;&lt;span style="font-family: georgia;"&gt;".&lt;/span&gt;  The &lt;span style="font-family: courier new;"&gt;IO&lt;/span&gt; in the type not only lets you know I/O is involved, but lets you know you are dealing with a function (&lt;span style="font-family: courier new;"&gt;main&lt;/span&gt;) that may have side effects (is not pure).  The "&lt;span style="font-family: courier new;"&gt;()&lt;/span&gt;" part just means that main does not return a value ("&lt;span style="font-family: courier new;"&gt;()&lt;/span&gt;" is an empty tuple, called "&lt;span style="font-family: courier new;"&gt;unit&lt;/span&gt;").  So, &lt;span style="font-family: courier new;"&gt;&lt;span style="font-family: georgia;"&gt;"&lt;/span&gt;main :: IO ()&lt;span style="font-family: georgia;"&gt;"&lt;/span&gt;&lt;/span&gt; is a function which has side effects and does not return a value.  Additionally, of course, &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt; is the function which is called when you execute the compiled version of the source code for this file.&lt;br /&gt;  &lt;br /&gt;   The function gets an input handle on my events file, uses a special  function to get the entire contents of the file (remember that Haskell's  lazy evaluation allows such a function to be practical), and puts the  output to the console, finally closing the handle.  Before we inspect  the logic any further, here is how we compile and run the program, and  what we see for output:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;     c:\HaskellDev\eventProcessor&amp;gt;ghc --make processEventsFile.hs&lt;br /&gt;     [1 of 1] Compiling Main             ( processEventsFile.hs, processEventsFile.o )&lt;br /&gt;     Linking processEventsFile.exe ...&lt;br /&gt;    &lt;br /&gt;     c:\HaskellDev\eventProcessor&amp;gt;processEventsFile.exe&lt;br /&gt;     Event {timestamp =  1320512200548, className = \"java.lang.String\", lineNumber = 1293,  message = \"NPE in substring()\", properties= [Property {key =  \"userId\", value = \"smith\"},Property {key = \"sessionId\", value =  \"ABCD1234\"}]}&lt;br /&gt;     ...&lt;br /&gt;     Event {timestamp =  1320512265147, className = \"javax.swing.JPanel\", lineNumber = 388,  message = \"initialized\", properties = [Property {key = \"userId\",  value = \"smith\"},Property {key = \"sessionId\", value =  \"ABCD1234\"}]}]"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;  &lt;br /&gt;   The next interesting thing you see in the sample code is the &lt;span style="font-family: courier new;"&gt;do&lt;/span&gt;.  Before we discuss &lt;span style="font-family: courier new;"&gt;do&lt;/span&gt;, let's discuss &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt; again, with its type of &lt;span style="font-family: courier new;"&gt;IO ()&lt;/span&gt;.  In Haskell, anything with a type starting with &lt;span style="font-family: courier new;"&gt;IO&lt;/span&gt;  is called an I/O action.  I/O actions are lazily evaluated, too, and  are executed when their parent I/O actions are executed.  In this  program, &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt; is an I/O action, so &lt;span style="font-family: courier new;"&gt;putStrLn&lt;/span&gt;, also an I/O action, will be executed when &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt; is executed.  In other words, their side effects do not occur when they are evaluated, but when they are actually performed.  A &lt;span style="font-family: courier new;"&gt;do&lt;/span&gt; block is used to chain (join) actions together; the &lt;span style="font-family: courier new;"&gt;do&lt;/span&gt; is necessary only if you have more than one action.  The value of a &lt;span style="font-family: courier new;"&gt;do&lt;/span&gt; block is the last action in the block to be performed.&lt;br /&gt;  &lt;br /&gt;   Note also the &lt;span style="font-family: courier new;"&gt;&amp;lt;-&lt;/span&gt; notation.  Assignment from an I/O action looks a little different than assignment from a pure function.  The &lt;span style="font-family: courier new;"&gt;&amp;lt;-&lt;/span&gt; operator takes the result from performing an I/O action and stores it in a variable.  As an example, let's look at &lt;span style="font-family: courier new;"&gt;openFile&lt;/span&gt;'s type in &lt;span style="font-family: lucida grande;"&gt;ghci&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;     *EventProcessor&amp;gt; :type System.IO.openFile&lt;br /&gt;     System.IO.openFile&lt;br /&gt;       :: FilePath&lt;br /&gt;          -&amp;gt; GHC.IO.IOMode.IOMode&lt;br /&gt;          -&amp;gt; IO GHC.IO.Handle.Types.Handle&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;  &lt;br /&gt;   So &lt;span style="font-family: courier new;"&gt;openFile&lt;/span&gt; is an I/O action of type &lt;span style="font-family: courier new;"&gt;&lt;span style="font-family: georgia;"&gt;"&lt;/span&gt;IO GHC.IO.Handle.Types.Handle&lt;span style="font-family: georgia;"&gt;."  &lt;/span&gt;&lt;/span&gt;In  our sample program, the &lt;span style="font-family: courier new;"&gt;openFile&lt;/span&gt; I/O action is performed when &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt; is  performed, and at that point the result of &lt;span style="font-family: courier new;"&gt;openFile&lt;/span&gt; is assigned to the &lt;span style="font-family: courier new;"&gt;inh&lt;/span&gt; handle using the &lt;span style="font-family: courier new;"&gt;&amp;lt;-&lt;/span&gt; operator.&lt;br /&gt;  &lt;br /&gt;  If the operator &lt;span style="font-family: courier new;"&gt;&amp;lt;-&lt;/span&gt; takes the result of an I/O action out of &lt;span style="font-family: courier new;"&gt;System.IO&lt;/span&gt;, then you might naturally ask what takes values in the opposite direction.  The &lt;span style="font-family: courier new;"&gt;return&lt;/span&gt; keyword provides this functionality.  Don't attempt to correlate the Haskell &lt;span style="font-family: courier new;"&gt;return&lt;/span&gt; with the &lt;span style="font-family: courier new;"&gt;return&lt;/span&gt;  keyword in any imperative programming language you have used.  As an  example, suppose we have a function which returns an I/O action:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;     import System.IO&lt;br /&gt;   &lt;br /&gt;     main :: IO ()&lt;br /&gt;     main = do&lt;br /&gt;       inh &amp;lt;- openFile "sampleEvents" ReadMode&lt;br /&gt;       inContents &amp;lt;- getContentsHereInstead inh&lt;br /&gt;       putStrLn inContents&lt;br /&gt;       hClose inh&lt;br /&gt;   &lt;br /&gt;     getContentsHereInstead :: Handle -&amp;gt; IO String&lt;br /&gt;     getContentsHereInstead handle = do&lt;br /&gt;       inContents &amp;lt;- hGetContents handle&lt;br /&gt;       return inContents&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt; &lt;br /&gt;  I have modified my earlier program and now delegate the actual "getting"  of the contents to a function.  Notice that the type of this function  is a "&lt;span style="font-family: courier new;"&gt;IO String&lt;/span&gt;" -- it has side effects as does main, only this time it returns an I/O action which, when performed, returns a &lt;span style="font-family: courier new;"&gt;String&lt;/span&gt; containing the file contents. &lt;br /&gt;&lt;br /&gt;Interestingly, note the assignment statements.  In &lt;span style="font-family: courier new;"&gt;getContentsHereInstead&lt;/span&gt;, I use &lt;span style="font-family: courier new;"&gt;return&lt;/span&gt; to wrap &lt;span style="font-family: courier new;"&gt;inContents&lt;/span&gt; in an &lt;span style="font-family: courier new;"&gt;IO String&lt;/span&gt;, as that is the return value type of the function.  Because &lt;span style="font-family: courier new;"&gt;hGetContents handle&lt;/span&gt; defines an I/O action, I could just as easily have defined the function as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     getContentsHereInstead :: Handle -&amp;gt; IO String&lt;br /&gt;     getContentsHereInstead handle = do&lt;br /&gt;       hGetContents handle&lt;/tt&gt;&lt;/pre&gt; &lt;br /&gt;and saved myself the trouble of (1) extracting the I/O action result  from the IO system, and (2) re-wrapping it in IO for the purposes of  returning the correct type.  An interesting situation exists in &lt;span style="font-family: courier new;"&gt;main&lt;/span&gt;, where I use the &lt;span style="font-family: courier new;"&gt;&amp;lt;-&lt;/span&gt; operator to assign the results of &lt;span style="font-family: courier new;"&gt;getContentsHereInstead&lt;/span&gt; to a pure value, then pass the pure value to &lt;span style="font-family: courier new;"&gt;putStrLn&lt;/span&gt;.  Note, however, that I really do need the pure value to pass to &lt;span style="font-family: courier new;"&gt;putStrLn&lt;/span&gt;.  From &lt;span style="font-family: courier new;"&gt;ghci&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     Prelude&amp;gt; :type putStrLn&lt;br /&gt;     putStrLn :: String -&amp;gt; IO ()&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;  &lt;span style="font-family: courier new;"&gt;putStrLn&lt;/span&gt; returns &lt;span style="font-family: courier new;"&gt;IO ()&lt;/span&gt;, but it actually does expect a pure &lt;span style="font-family: courier new;"&gt;String&lt;/span&gt; as input.  So, it would be incorrect to try to "&lt;span style="font-family: courier new;"&gt;putStrLn&lt;/span&gt;" the actual output of &lt;span style="font-family: courier new;"&gt;getContentsHereInstead&lt;/span&gt;; if I try something like&lt;pre&gt;&lt;tt&gt;     putStrLn (getContentsHereInstead inh)&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  I will get the following complaint from &lt;span style="font-family: courier new;"&gt;ghci&lt;/span&gt;:&lt;pre&gt;&lt;tt&gt;     processEventsFile2.hs:7:13:     &lt;br /&gt;         Couldn't match expected type `[Char]' with actual type `IO String'&lt;br /&gt;         Expected type: String&lt;br /&gt;           Actual type: IO String&lt;br /&gt;         In the return type of a call of `getContentsHereInstead'&lt;br /&gt;         In the first argument of `putStrLn', namely&lt;br /&gt;           `(getContentsHereInstead inh)'&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  The problem is that &lt;span style="font-family: courier new;"&gt;putStrLn&lt;/span&gt; expected a pure &lt;span style="font-family: courier new;"&gt;String&lt;/span&gt; and instead got an &lt;span style="font-family: courier new;"&gt;IO String&lt;/span&gt;.  So we see that &lt;span style="font-family: courier new;"&gt;&amp;lt;-&lt;/span&gt; maps the result of an I/O action to a pure value, and &lt;span style="font-family: courier new;"&gt;return&lt;/span&gt; wraps the pure value in &lt;span style="font-family: courier new;"&gt;System.IO&lt;/span&gt;, and that we need to ensure we're passing around values of the expected data types.&lt;br /&gt; &lt;br /&gt;  I still haven't unmarshalled my lines in my data file to &lt;span style="font-family: courier new;"&gt;Event&lt;/span&gt;  objects, which was the motivation of this post.  To accomplish this  goal, I first want to get the contents of the file, as before, and this  time, pass a pure value to a non-I/O function which will re-hydrate the Event objects.  To keep the post to a  manageable length, I'm going to call it a day, and call this Part 1.  In Part 2, coming later this week, I'll finish up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-8110997209647871151?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/8110997209647871151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/8110997209647871151'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/11/from-oo-to-fp-haskell-io-part-1.html' title='From OO to FP:  Haskell I/O, Part 1'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-8597314714453445820</id><published>2011-11-14T20:44:00.000-08:00</published><updated>2011-11-14T21:51:22.965-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDI'/><category scheme='http://www.blogger.com/atom/ns#' term='ClassPrepareEvent'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Debug Interface'/><title type='text'>Monitoring classloading in JDI</title><content type='html'>For the last few weeks, I have been building a Java process monitoring tool based on the Java Debug Interface.  Although I've done much of this work before, it has been a few years, and so now I'm retracing my steps.  As I remember the details and pitfalls, I've been posting my notes in the hope that you'll find them useful.&lt;br /&gt;&lt;br /&gt;Today I'm going to talk about &lt;span style="font-family: courier new;"&gt;ClassPrepareEvent&lt;/span&gt;s, after a little background.  As you probably already know, you can attach a debugger to an already-running Java process, or launch the target process itself from your debugger (using various command-line switches).  In my project, I'm always going to be attaching to a running process, as the point is to collect process data on an as-needed basis.  The reason JDI's &lt;span style="font-family: courier new;"&gt;ClassPrepareEvent&lt;span style="font-family: georgia;"&gt; &lt;/span&gt;&lt;/span&gt;is interesting is that, when you launch a debug target process, or even when you attach to an already-running process, it's likely that some of your desired breakpoints lie in classes which have not yet been loaded.&lt;br /&gt;&lt;br /&gt;In my usual scenario, I call the &lt;span style="font-family: courier new;"&gt;com.sun.jdi.VirtualMachine&lt;/span&gt;'s &lt;span style="font-family: courier new;"&gt;allClasses()&lt;/span&gt; method to get a list of all loaded &lt;span style="font-family: courier new;"&gt;ReferenceType&lt;/span&gt;s.  One way to think of a &lt;span style="font-family: courier new;"&gt;ReferenceType&lt;span style="font-family: georgia;"&gt; &lt;/span&gt;&lt;/span&gt;is as a chunk of a Java class definition.  If your Java class has inner classes, then they will be broken out by JDI into separate &lt;span style="font-family: georgia;"&gt;&lt;span style="font-family: courier new;"&gt;ReferenceType&lt;/span&gt;s.  &lt;/span&gt;Each &lt;span style="font-family: courier new;"&gt;ReferenceType&lt;span style="font-family: georgia;"&gt; &lt;/span&gt;&lt;/span&gt;contains a collection of line locations; these correspond to lines of code on which breakpoints can be set and are identified by (among other things) the source-code line number.  If a line of source code cannot be the target of a breakpoint, then there will not be a line location for it in the &lt;span style="font-family: courier new;"&gt;ReferenceType&lt;/span&gt;.  In my debugger-based applications, I step through the line locations of all the &lt;span style="font-family: courier new;"&gt;ReferenceTypes&lt;/span&gt;, matching up line locations with breakpoint specifications, and then register my breakpoint requests.&lt;br /&gt;&lt;br /&gt;As you can guess, I have a potential problem:  what should I do if a class I need has not yet been loaded at the time I'm constructing my breakpoint requests?  The answer is:  JDI's &lt;span style="font-family: courier new;"&gt;ClassPrepareEvent&lt;/span&gt;.  The entry point for using this part of the API is the &lt;span style="font-family: courier new;"&gt;EventRequestManager&lt;/span&gt;'s &lt;span style="font-family: courier new;"&gt;createClassPrepareRequest()&lt;/span&gt; method.  Having made our request, the same event-listener loop we use to wait for breakpoint events can also be used to wait for class prepare events (see the &lt;a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#71421"&gt;JVM specification&lt;/a&gt; for a definition of class preparation).&lt;br /&gt;&lt;br /&gt;One thing I remember from my previous development on this API is that there is a timing risk here.  You probably want to create the class prepare request before you iterate over the list of currently-loaded classes.  The reason is that you don't want to fall into this trap:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Iterate over a set of the currently-loaded classes, processing and making breakpoint requests.&lt;/li&gt;&lt;li&gt;Suddenly, a class you need is loaded!&lt;/li&gt;&lt;li&gt;You register your class-prepare event and start getting events as classes are loaded, but you miss the class that loaded in between step #1 and step #3.&lt;/li&gt;&lt;/ol&gt;Here's another possible trap:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Register for class-prepare events so you don't get caught by the above issue.&lt;/li&gt;&lt;li&gt;Iterate over the currently-loaded classes, requesting breakpoints as necessary.&lt;/li&gt;&lt;li&gt;Process newly-loaded classes, requesting breakpoints as necessary.&lt;/li&gt;&lt;/ol&gt;The problem with this second approach is that you may process the same breakpoint twice.  Why?  By the time you iterate over the currently-loaded classes, some of the classes in that list are very likely going to be classes which have shown up in your class-prepare listener.  Neither of these problems can be fixed by slapping a &lt;span style="font-family: courier new;"&gt;synchronized&lt;span style="font-family: georgia;"&gt; &lt;/span&gt;&lt;/span&gt;keyword &lt;span style="font-family: courier new;"&gt;&lt;/span&gt;somewhere.&lt;br /&gt;&lt;br /&gt;Whether you launch your target application from your debugger or attach to it after the fact, you will have to deal with some variation of this issue.  The way I deal with it is to add some state to the class I use to define each breakpoint specification.  As each corresponding loaded class is found and the breakpoint request is made, I set a flag on the specification so that I know the request was registered.  Further, I follow the second approach outlined above (better to have duplicates than to miss one).  If I see a class-prepare event for a class I've already processed from the VM's &lt;span style="font-family: courier new;"&gt;ReferenceType&lt;span style="font-family: georgia;"&gt; &lt;/span&gt;&lt;/span&gt;list, then I simply skip over it.  I do the same for the reverse situation, in which my list of &lt;span style="font-family: courier new;"&gt;ReferenceType&lt;/span&gt;s contains &lt;span style="font-family: courier new;"&gt;ReferenceTypes&lt;/span&gt; which I have just processed in my &lt;span style="font-family: courier new;"&gt;ClassPrepareEvent&lt;/span&gt; listener.&lt;br /&gt;&lt;br /&gt;Finally, one issue I have not looked at before (either for this development effort, or in my previous development in this area) -- what happens when a class is unloaded, especially a class on which you have registered breakpoint requests.   For example, will a registered breakpoint request prevent a class from being unloaded?  Do you care about a stranded breakpoint request if the class isn't even loaded?  (Answer:  yes, I suppose, if it gets reloaded and you no longer have a valid breakpoint request for it).  JDI does have a &lt;span style="font-family: courier new;"&gt;ClassUnloadEvent&lt;/span&gt;, for which you can also register a listener.  As I said, I have not dealt with this (possible) issue, having never seen a target class get unloaded before, but it's good to know "there's an API for that". &lt;br /&gt;&lt;h3&gt;&lt;br /&gt;&lt;/h3&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-8597314714453445820?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/8597314714453445820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/11/monitoring-classloading-in-jdi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/8597314714453445820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/8597314714453445820'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/11/monitoring-classloading-in-jdi.html' title='Monitoring classloading in JDI'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-7746922255197132661</id><published>2011-11-12T09:37:00.000-08:00</published><updated>2011-11-12T16:00:21.096-08:00</updated><title type='text'>More on Haskell/FP function organization; lazy evaluation</title><content type='html'>After my &lt;a href="http://wayne-adams.blogspot.com/2011/11/haskell-from-oo-developers-perspective.html"&gt;last post&lt;/a&gt; scrolled off the bottom of the page, I realized I missed a couple of opportunities:  one related to some additional code optimization, and one related to the topic of &lt;span style="font-style: italic;"&gt;lazy (&lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span style="font-style: italic;"&gt;nonstrict) evaluation&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;First, let me review what I was doing.  I was processing a data structure I was using to represent events generated from a process monitor.  The structure includes a timestamp, a class name and source line number, a text message, and a set of properties.  Displaying one of these in &lt;tt&gt;ghci&lt;/tt&gt; yields the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;Event {timestamp = 1320513130333, className = "com.adamsresearch.jarview.JarView", lineNumber = 388, message = "fileNotFound", properties = [Property {key = "userId", value = "adams"},Property {key = "sessionId", value = "EFGH5678"}]}&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;My goal was to write -- in authentic FP style -- some code to extract, from a List of these events, events whose &lt;tt&gt;userId&lt;/tt&gt; property value matched a particular user ID.  Here is the code (minus type definitions, etc.) I ended up using:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;eventGeneratedByUser :: String -&amp;gt; Event -&amp;gt; Bool&lt;br /&gt;eventGeneratedByUser id event =&lt;br /&gt; if (containsUserPropertyWithValue (properties event) id)&lt;br /&gt;   then True&lt;br /&gt;   else False&lt;br /&gt; where&lt;br /&gt;   containsUserPropertyWithValue (x:xs) id =&lt;br /&gt;     if (isUserWithId x id)&lt;br /&gt;       then True&lt;br /&gt;       else containsUserPropertyWithValue xs id&lt;br /&gt;     where&lt;br /&gt;       isUserWithId prop id =&lt;br /&gt;         if (key prop == "userId" &amp;amp;&amp;amp; value prop == id)&lt;br /&gt;           then True&lt;br /&gt;           else False&lt;br /&gt;   containsUserPropertyWithValue [] _ = False&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Finally, in &lt;tt&gt;ghci&lt;/tt&gt;, I retrieved the list of events I wanted with the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; let filterPred = eventGeneratedByUser "adams"&lt;br /&gt;    *Main&amp;gt; let eventsForAdams = filter filterPred eventList&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;One theme object-oriented developers hear about repeatedly in FP is to stop thinking in loops, and start thinking in terms of recursion.  An additional theme is (as best as I can state it) to avoid recursion when you can use a mapping-style function, that is, a function which structurally is defined to operate on all the elements of a list.  When you set up a recursive function to process a list, a large part of what you are building is boilerplate.  Boilerplate is the developer's curse: some live with it (care to pound out the boilerplate for Java's &lt;tt&gt;GridBagLayout&lt;/tt&gt; and &lt;tt&gt;GridBagConstraints&lt;/tt&gt;, anyone?), while others replace it with "frameworks" that the rest of us usually find even less appealing than writing the boilerplate code ourselves.&lt;br /&gt;&lt;br /&gt;As you can tell from the above source code, I used recursion to create the boolean function which determines if an event is associated with a user.  However, when I actually filtered the list, instead of using a recursive function I used Haskell's &lt;tt&gt;filter&lt;/tt&gt;, passing it my partial function.  For that last step, I feel I finally was writing in the spirit of Haskell and FP in general, but now let's take a look at that source code again and see if there's room for improvement.&lt;br /&gt;&lt;br /&gt;Note first my innermost nested function, &lt;tt&gt;isUserWithId&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;isUserWithId prop id =&lt;br /&gt; if (key prop == "userId" &amp;amp;&amp;amp; value prop == id)&lt;br /&gt;   then True&lt;br /&gt;   else False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Note from my old post that I used Haskell record syntax to define the &lt;tt&gt;Property&lt;/tt&gt; data type and that Haskell has used type inference to recognize that I am passing a &lt;tt&gt;Property&lt;/tt&gt; structure to the &lt;tt&gt;isUserWithId&lt;/tt&gt; function.  All this function does is look at a key-value pair and return &lt;tt&gt;True&lt;/tt&gt; if the key is &lt;tt&gt;userId&lt;/tt&gt; and the value matches the parameter I pass in.  I think this function is fine "as is".&lt;br /&gt;&lt;br /&gt;The enclosing function, found in the &lt;tt&gt;where&lt;/tt&gt; clause of the function &lt;tt&gt;eventGeneratedByUser&lt;/tt&gt;, is a recursive function.  Let's repeat the whole function:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;eventGeneratedByUser :: String -&amp;gt; Event -&amp;gt; Bool&lt;br /&gt;eventGeneratedByUser id event =&lt;br /&gt; if (containsUserPropertyWithValue (properties event) id)&lt;br /&gt;   then True&lt;br /&gt;   else False&lt;br /&gt; where&lt;br /&gt;   containsUserPropertyWithValue (x:xs) id =&lt;br /&gt;     if (isUserWithId x id)&lt;br /&gt;       then True&lt;br /&gt;       else containsUserPropertyWithValue xs id&lt;br /&gt;     where&lt;br /&gt;       isUserWithId prop id =&lt;br /&gt;         if (key prop == "userId" &amp;amp;&amp;amp; value prop == id)&lt;br /&gt;           then True&lt;br /&gt;           else False&lt;br /&gt;   containsUserPropertyWithValue [] _ = False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;What I am doing with this function is essentially iterating over the &lt;tt&gt;Property&lt;/tt&gt; elements of an &lt;tt&gt;Event&lt;/tt&gt;, returning &lt;tt&gt;True&lt;/tt&gt; as soon as I find a &lt;tt&gt;Property&lt;/tt&gt; that matches the desired condition.&lt;br /&gt;&lt;br /&gt;Can this be converted from a recursive function to something a little more compact?  As it turns out, yes, easily.  Haskell contains a function called &lt;tt&gt;any&lt;/tt&gt; which acts on a List and returns &lt;tt&gt;True&lt;/tt&gt; if any element of the List is &lt;tt&gt;True&lt;/tt&gt;.  To use this function in my example, I would rearrange my code to calculate the &lt;tt&gt;isUserWithId&lt;/tt&gt; value for each &lt;tt&gt;Property&lt;/tt&gt; in the data structure, wrap those boolean values in a List, and apply the Haskell function &lt;tt&gt;any&lt;/tt&gt; to the List.  If you are wondering if I will be wasting cycles calculating values I may not need, bear with me for a few minutes.&lt;br /&gt;&lt;br /&gt;The first question is how to generate a List of boolean values, the results of applying &lt;tt&gt;isUserWithId&lt;/tt&gt; to a List of properties.  To start, let me promote &lt;tt&gt;isUserWithId&lt;/tt&gt; to a standalone function, but before we do that, let's do the same thing we did in my last post -- plan ahead to be able to use it as a partial function.  By this I mean we'll want to apply this function to a list of &lt;tt&gt;Property&lt;/tt&gt; values, where the "user ID" will be built-in, so to speak, to the function definition.  I'll redefine the function to take the user ID first, so I can  create a partial function later which I can apply directly to a &lt;tt&gt;Property&lt;/tt&gt; (note this involves re-ordering the arguments in the &lt;tt&gt;isUserWithId&lt;/tt&gt; equation, also):&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;isUserWithId :: String -&amp;gt; Property -&amp;gt; Bool&lt;br /&gt;isUserWithId id prop =&lt;br /&gt; if (key prop == "userId" &amp;amp;&amp;amp; value prop == id)&lt;br /&gt;   then True&lt;br /&gt;   else False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;We can verify the function, both in its "full form", where we pass in both the user ID and the &lt;tt&gt;Property&lt;/tt&gt; and in its partial form, where we first create a partial function with the user ID specified, and then pass in only a &lt;tt&gt;Property&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; prop4&lt;br /&gt;    Property {key = "userId", value = "smith"}&lt;br /&gt;    *Main&amp;gt; isUserWithId "smith" prop4&lt;br /&gt;    True&lt;br /&gt;    *Main&amp;gt; let containsSmith = isUserWithId "smith"&lt;br /&gt;    *Main&amp;gt; containsSmith prop4&lt;br /&gt;    True&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Next, I'll take the existing three, short &lt;tt&gt;Property&lt;/tt&gt; Lists from my example and concatenate them into a larger list:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; let bigPropList = concat [propList1,propList2,propList3]&lt;br /&gt;    *Main&amp;gt; bigPropList&lt;br /&gt;    [Property {key = "userId", value = "smith"},Property {key = "sessionId", value = "ABCD1234"},Property {key = "userId", value = "adams"},Property {key = "sessionId", value = "EFGH5678"},Property {key = "userId", value = "jobim"},Property {key = "sessionId", value = "WXYZ9876"}]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Now let's use &lt;tt&gt;any&lt;/tt&gt; to return &lt;tt&gt;True&lt;/tt&gt; if any item in the list matches our partial function, which is testing to see if a &lt;tt&gt;Property&lt;/tt&gt; has user ID "smith":&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; any containsSmith bigPropList&lt;br /&gt;    True&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;and that is literally all we had to do to get our result.  Note the interesting invocation of &lt;tt&gt;any&lt;/tt&gt;:  our partial function takes a &lt;tt&gt;Property&lt;/tt&gt;, not a List of &lt;tt&gt;Property&lt;/tt&gt; values.  The &lt;tt&gt;any&lt;/tt&gt; function steps through the elements of the list and returns &lt;tt&gt;True&lt;/tt&gt; as soon as the invocation of &lt;tt&gt;containsSmith&lt;/tt&gt; against a single &lt;tt&gt;Property&lt;/tt&gt; returns &lt;tt&gt;True&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;To integrate this code into our new version of &lt;tt&gt;eventGeneratedByUser&lt;/tt&gt;, we could do the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;eventGeneratedByUser :: String -&amp;gt; Event -&amp;gt; Bool&lt;br /&gt;eventGeneratedByUser id event =&lt;br /&gt; any (isUserWithId id) (properties event)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;and then test this in &lt;tt&gt;ghci&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; head eventList&lt;br /&gt;    Event {timestamp = 1320512200548, className = "java.lang.String", lineNumber = 1293, message = "NPE in substring()", properties = [Property {key = "userId", value = "smith"},Property {key = "sessionId", value = "ABCD1234"}]}&lt;br /&gt;    *Main&amp;gt; eventGeneratedByUser "smith" (head eventList)&lt;br /&gt;    True&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Note the code is considerably more compact, and (unlike in some languages where "terse" = "dense") actually more readable.  In fact, things are so clean we can go a step farther than we did before and provide a function to return a subset of the List, something we just did interactively in &lt;tt&gt;ghci&lt;/tt&gt; the last time:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;getEventsGeneratedByUser :: String -&amp;gt; [Event] -&amp;gt; [Event]&lt;br /&gt;getEventsGeneratedByUser id events =&lt;br /&gt; filter (eventGeneratedByUser id) events&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;and, testing in &lt;tt&gt;ghci&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; getEventsGeneratedByUser "jobim" eventList&lt;br /&gt;    [Event {timestamp = 1320512200699, className = "javax.swing.JPanel", lineNumber = 388, message = "initialized", properties = [Property {key = "userId", value = "jobim"},Property {key = "sessionId", value = "WXYZ9876"}]},Event {timestamp = 1320512203699, className = "javax.swing.JList", lineNumber = 1255, message = "model replaced", properties = [Property {key = "userId", value = "jobim"},Property {key = "sessionId", value = "WXYZ9876"}]},Event {timestamp = 1320512259333, className = "javax.lang.Integer", lineNumber = 133, message = "number format exception", properties = [Property {key = "userId", value = "jobim"},Property {key = "sessionId", value = "WXYZ9876"}]}]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Note how compact and readable our resulting code is.  We have one function which determines if a &lt;tt&gt;Property&lt;/tt&gt; contains a user ID of a specified value -- 5 lines of code, including the type declaration.  We have two additional functions, one of which returns &lt;tt&gt;True&lt;/tt&gt; if an &lt;tt&gt;Event&lt;/tt&gt; is generated by a specified user, and one which returns a subset of a List of &lt;tt&gt;Event&lt;/tt&gt;s which satisfy this condition -- each 3 lines of code, including the type declaration.  And as I mentioned earlier, in this case, compact actual means readable.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;b&gt;Lazy Evaluation&lt;/b&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;In the above code, you might have been wondering "What is the performance impact of looping through a List of, say, 5000 properties and returning &lt;tt&gt;True&lt;/tt&gt; if only one of them meets the test?  Especially if the first property meets the test?".  Haskell evaluates expressions only when they are needed.  Technically in Haskell this is called &lt;em&gt;nonstrict evaluation&lt;/em&gt;, and it allows you to do some things that would truly look odd in Java.  For example, in Haskell you can define a list as a range of elements using &lt;tt&gt;..&lt;/tt&gt;; the following defines a list of integer values from 1 through 9:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; [1..9]&lt;br /&gt;    [1,2,3,4,5,6,7,8,9]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;While this may look normal, what do you think of this?&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    Prelude&amp;gt; [1..]&lt;br /&gt;    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20&lt;br /&gt;,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40&lt;br /&gt;,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60&lt;br /&gt;,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80&lt;br /&gt;,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100&lt;br /&gt;,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120&lt;br /&gt;,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135&lt;br /&gt;    ...&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;where I have added the line breaks to make it easier to read.  Big surprise: this is an infinite list starting with the integer 1, and &lt;tt&gt;ghci&lt;/tt&gt; will happily continue printing this output to the screen forever, or until Something Really Bad Happens, whichever comes first.  I had to hit Control-C to stop the output.  But, you can assign this infinite list to a variable:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    Prelude&amp;gt; let infiniteList = [1..]&lt;br /&gt;    Prelude&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;with no problems.  The reason is that &lt;tt&gt;infiniteList&lt;/tt&gt; has not yet been evaluated (populated).  If you were to try to &lt;tt&gt;show&lt;/tt&gt; this in &lt;tt&gt;ghci&lt;/tt&gt;, you'd be back to the infinite output again.  Nonstrict evaluation allows us to do some interesting things.  For example, you can take the first 11 items of an infinite list:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    Prelude&amp;gt; take 11 infiniteList&lt;br /&gt;    [1,2,3,4,5,6,7,8,9,10,11]&lt;br /&gt;    Prelude&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;This feature allows us to write code that (for example) returns &lt;tt&gt;True&lt;/tt&gt; if "any" element in a List satisfies some predicate.  Haskell isn't going to sift through the entire List, evaluating every expression, and then step through the List and apply the predicate.  So it doesn't matter how many properties my events have; I'll return a &lt;tt&gt;True&lt;/tt&gt; as soon as I get a match.  Note that there are cases where all the elements will indeed be evaluated; for example, if you are summing the elements of a List (of course, you didn't expect Haskell to give you the sum of the elements of an infinite List, right?).&lt;br /&gt;&lt;br /&gt;Nonstrict evaluation is already one of my favorite features of Haskell, right up there with standard library functions that operate on all the elements of a List.  Next post, I expect to discuss I/O in Haskell, continuing along with the process-event-monitoring example I've been using to date.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-7746922255197132661?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7746922255197132661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7746922255197132661'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/11/more-on-haskellfp-function-organization.html' title='More on Haskell/FP function organization; lazy evaluation'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-3362747334390600906</id><published>2011-11-05T08:54:00.000-07:00</published><updated>2011-11-06T13:16:03.561-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='FP'/><title type='text'>Haskell From an OO Developer's Perspective, Part 3</title><content type='html'>Today I'm going to process a set of structured data using Haskell,  tainted by years of Smalltalk, C++, Java and C# experience.  I've been  following the book &lt;em&gt;Real World Haskell&lt;/em&gt;, which I chose for a couple of reasons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;From the little I know of functional programming, Haskell appears to be a relatively "pure" FP language, and&lt;/li&gt;&lt;li&gt;The book is very comprehensive, covering FP topics of interest in depth.&lt;/li&gt;&lt;/ul&gt;While  there are shorter introductions to FP, or good books on hybrid OO/FP  languages, my preference is to make a clean break with OO and quickly  become proficient in FP.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;em&gt;The structured data&lt;/em&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I'm  going to process a set of events generated by a Java program (they  could be generated by any program, but this choice allows me to leverage  one of my other ongoing projects).  Each event consists of:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A timestamp, the epoch time measured in the usual Java milliseconds&lt;/li&gt;&lt;li&gt;A fully-qualified Java class name&lt;/li&gt;&lt;li&gt;The line number in the class at which the event is generated&lt;/li&gt;&lt;li&gt;A short descriptive message&lt;/li&gt;&lt;li&gt;A list of key-value pairs&lt;/li&gt;&lt;/ul&gt;The  key-value pairs are analogous to the properties of a JMS message.  In  my application, I'll assume that some keys are present in &lt;em&gt;every&lt;/em&gt; message, for the purposes of filtering messages during processing.&lt;br /&gt;&lt;br /&gt;If  you, too, are coming to Haskell or FP in general from an OO background,  you don't need to see how this data structure would be implemented as  an OO object, so I will focus instead of implementing it in Haskell.  Here  is my first cut:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    -- file:  c:/HaskellDev/eventProcessor/eventProcessor.hs&lt;br /&gt;&lt;br /&gt;    type Timestamp = Integer&lt;br /&gt;    type ClassName = String&lt;br /&gt;    type LineNumber = Integer&lt;br /&gt;    type Message = String&lt;br /&gt;    type Key = String&lt;br /&gt;    type Value = String&lt;br /&gt;    type Property = (Key, Value)&lt;br /&gt;    type Properties = [Property]&lt;br /&gt;&lt;br /&gt;    data Event= Event Timestamp ClassName LineNumber Message Properties&lt;br /&gt;      deriving (Show)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;I have defined &lt;tt&gt;Properties&lt;/tt&gt; to be a list of &lt;tt&gt;Property&lt;/tt&gt; structures, where a &lt;tt&gt;Property&lt;/tt&gt; is a 2-tuple consisting of a &lt;tt&gt;String&lt;/tt&gt; &lt;tt&gt;Key&lt;/tt&gt; and a &lt;tt&gt;String&lt;/tt&gt; &lt;tt&gt;Value&lt;/tt&gt;.   Hopefully this structure will be interesting enough to provide a  non-trivial example of an event processor in Haskell.  Note that I  included &lt;tt&gt;deriving (Show)&lt;/tt&gt; in the type definition so that &lt;tt&gt;ghci&lt;/tt&gt; will know how to output a value of my new type.&lt;br /&gt;&lt;br /&gt;Now that we've defined the data type, let's create an &lt;tt&gt;Event&lt;/tt&gt; value:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; let prop1 = ("sessionId", "ABCD1234")&lt;br /&gt;    *Main&amp;gt; :type prop1&lt;br /&gt;    prop1 :: ([Char], [Char])&lt;br /&gt;    *Main&amp;gt; let props = [prop1]&lt;br /&gt;    *Main&amp;gt; let evt1 = Event 1320512200548 "java.lang.String" 1293 "NPE in substring()" props&lt;br /&gt;    *Main&amp;gt; evt1&lt;br /&gt;    Event 1320512200548 "java.lang.String" 1293 "NPE in substring()" [("sessionId","ABCD1234")]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Next, we'll look at what we might want to do with this kind of data, and how we could process it in Haskell.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;b&gt;Generating the data&lt;/b&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Suppose  for a moment that we have a large application running, with many  concurrent user sessions, producing hundreds or thousands of these  values (our &lt;tt&gt;Event&lt;/tt&gt;s above) per minute.  Occasionally a session  will "come off the rails", in which case it would be really useful to be  able to extract all messages specific to that user's session to see  what is going on.  We may want to do this in real time, or we may just  process the data "after the fact", restricting ourselves to a time  window during which the issues arose&lt;br /&gt;&lt;br /&gt;In this example, I'm going  to concentrate on the post-processing case.  One reason is that I don't  want to get into event-driven Haskell programming just yet, and a second  reason is that I can arrange to skip (for now) the "non-FP-pure" code  used to get the &lt;tt&gt;Event&lt;/tt&gt;s (file I/O, for example) and focus only on the "pure-FP" code.  So I'll assume that we have a ready-made Haskell List of &lt;tt&gt;Event&lt;/tt&gt; values to process in our example.  I'll set the data up in my &lt;tt&gt;eventProcessor.hs&lt;/tt&gt;  file, entering as many values as I can before being overcome by  boredom.  I will put two properties in each property list:  a session ID  and a user ID (on the assumption that sessions come and go for the same  user, and a user may even have multiple sessions open simultaneously).   In my example data set there will be three user sessions going at any  one time.  Note that the &lt;tt&gt;let&lt;/tt&gt; in variable assignment is a &lt;tt&gt;ghci&lt;/tt&gt; artifact, so it isn't necessary if you make your assignments in the Haskell source file, below my &lt;tt&gt;Event&lt;/tt&gt; data type definition:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    prop1 = ("sessionId", "ABCD1234")&lt;br /&gt;    prop2 = ("sessionId", "EFGH5678")&lt;br /&gt;    prop3 = ("sessionId", "WXYZ9876")&lt;br /&gt;    prop4 = ("userId", "smith")&lt;br /&gt;    prop5 = ("userId", "adams")&lt;br /&gt;    prop6 = ("userId", "jobim")&lt;br /&gt;&lt;br /&gt;    propList1 = [prop4, prop1]&lt;br /&gt;    propList2 = [prop5, prop2]&lt;br /&gt;    propList3 = [prop6, prop3]&lt;br /&gt;&lt;br /&gt;    eventList = [&lt;br /&gt;      Event 1320512200548 "java.lang.String" 1293 "NPE in substring()" propList1,&lt;br /&gt;      Event 1320512200699 "javax.swing.JPanel" 388 "initialized" propList3,&lt;br /&gt;      Event 1320512203699 "javax.swing.JList" 1255 "model replaced" propList3,&lt;br /&gt;      Event 1320513130333 "com.adamsresearch.jarview.JarView" 388 "fileNotFound" propList2,&lt;br /&gt;      Event 1320513255342 "com.adamsresearch.jarview.FileFilter" 79 "initialized" propList1,&lt;br /&gt;      Event 1320513257324 "com.adamsresearch.jarview.ArchiveSearch" 193 "search started13255342" propList2,&lt;br /&gt;      Event 1320512259333 "javax.lang.Integer" 133 "number format exception" propList3,&lt;br /&gt;      Event 1320512260122 "com.adamsresearch.jarview.JarView" 725 "search started" propList2,&lt;br /&gt;      Event 1320512263122 "com.adamsresearch.jarview.JarView" 779 "search completed" propList2,&lt;br /&gt;      Event 1320512265147 "javax.swing.JPanel" 388 "initialized" propList1&lt;br /&gt;      ]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Note  a common beginner mistake, which I made initially -- I know that  indentation is important in Haskell, but I still made the old-style indentation mistake of putting the final, closing square bracket in  column 1.  This results in an error because the closing bracket is  itself part of the List assignment statement.  Hence the indentation,  above, on the last line of the &lt;tt&gt;eventList&lt;/tt&gt; assignment.  The indentation means we're still in the assignment statement.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;b&gt;Processing the data&lt;/b&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Given  this List of sample data, in imperative-style programming you would  probably resort to a loop statement to process the individual &lt;tt&gt;Event&lt;/tt&gt;s.  Haskell does not have a loop construct; instead, learn to think about loop-style processing of a List as&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Recursively operating on each element of the List, or&lt;/li&gt;&lt;li&gt;Using Haskell library functions which operate on all elements of a List.&lt;/li&gt;&lt;/ul&gt;Although  we'll settle on the second case, most FP books discuss the first case  first, as it seems a more natural transition from imperative  programming, so we will follow that approach here, too.&lt;br /&gt;&lt;br /&gt;To  introduce the idea of processing a List of data with a recursive  function, let's first aim low:  let's write a function that just returns  a new List of the same data.  This will be a simple function and looks  as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    -- file:  c:/HaskellDev/eventProcessor/clone.hs&lt;br /&gt;&lt;br /&gt;    clone :: [a] -&amp;gt; [a]&lt;br /&gt;&lt;br /&gt;    clone (x:xs) = x : clone xs&lt;br /&gt;    clone [] = []&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;tt&gt;clone&lt;/tt&gt; takes as an argument a List, and returns a List.  The first equation of &lt;tt&gt;clone&lt;/tt&gt; performs a pattern match on the incoming List using the List constructor (&lt;tt&gt;:&lt;/tt&gt;).  If this pattern matches, the head of the List (&lt;tt&gt;x&lt;/tt&gt;) is extracted from the list, and &lt;tt&gt;clone&lt;/tt&gt; is called on the tail of the List.   The head of the list and the return of &lt;tt&gt;clone&lt;/tt&gt;  will be used, as the constructor indicates, to form a new List.  So  we're just cloning the input List here.  As recursion continues,  eventually the tail will be an empty List, at which point the second  equation will match and the function will return an empty List (appended  to the List it has been building on each recursive call).&lt;br /&gt;&lt;br /&gt;To see this function in action, we load it into &lt;tt&gt;ghci&lt;/tt&gt;, then inspect the value of the List returned when we pass a List to &lt;tt&gt; clone&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; :load clone.hs&lt;br /&gt;    [1 of 1] Compiling Main             ( clone.hs, interpreted )&lt;br /&gt;    Ok, modules loaded: Main.&lt;br /&gt;    *Main&amp;gt; let clone1 = clone [1,2,3,4,5]&lt;br /&gt;    *Main&amp;gt; clone1&lt;br /&gt;    [1,2,3,4,5]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Now, on to something non-trivial:  I want to extract, from our sample data, all &lt;tt&gt;Event&lt;/tt&gt; values with a specific user ID. In &lt;tt&gt;clone&lt;/tt&gt;,  we took each value indiscriminately because we wanted all of them; in  this case, we'll need to pattern match on the attributes of the &lt;tt&gt;Event&lt;/tt&gt;.  Not only that, but we'll have to find the user ID in the List of properties nested within the &lt;tt&gt;Event&lt;/tt&gt;.  These requirements will allow me to show an example with a little more substance than a "Hello, World" example.&lt;br /&gt;&lt;br /&gt;Recall the format of our &lt;tt&gt;Event&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;Event 1320512200548 "java.lang.String" 1293 "NPE in substring()" [("userId","smith"),("sessionId","ABCD1234")]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Let's say we are interested in extracting every &lt;tt&gt;Event&lt;/tt&gt; with a specified user ID, and let's call the function &lt;tt&gt;getMessagesForUser&lt;/tt&gt;.  For each &lt;tt&gt;Event&lt;/tt&gt;,  once we determine that the user ID matches, we append the itemit to a List  which will be the function's return value.&lt;br /&gt;&lt;br /&gt;The way I approached  this is to recognize that I first need a function that will iterate over  a list of key-value pairs, searching for a key of &lt;tt&gt;userId&lt;/tt&gt; and a value (actually, the second element of a 2-tuple) matching the passed-in user ID.  I'll call this function &lt;tt&gt;matchesUserId&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Before I get started, though, I'm going to revisit my original algebraic data type &lt;tt&gt;Event&lt;/tt&gt; and make it a little more user-friendly.  The reason:  I want to easily access the fields of an &lt;tt&gt;Event&lt;/tt&gt;  without having to write boilerplate accessor functions.  By boilerplate  I mean something like the following, to access the timestamp of an &lt;tt&gt;Event&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    timestamp (Event ts _ _ _ _) = ts&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;where  you would have to supply one of these for each field you want to  access.  Instead, we can use Haskell record syntax to supply default  accessors while defining the data type, which I modify here.  While I'm  at it, I'll perform a similar change to &lt;tt&gt;Property&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    data Property = Property {&lt;br /&gt;      key :: Key,&lt;br /&gt;      value:: Value }&lt;br /&gt;      deriving (Show)&lt;br /&gt;&lt;br /&gt;    data Event= Event {&lt;br /&gt;      timestamp :: Timestamp,&lt;br /&gt;      className :: ClassName,&lt;br /&gt;      lineNumber :: LineNumber,&lt;br /&gt;      message :: Message,&lt;br /&gt;      properties :: Properties }&lt;br /&gt;      deriving (Show)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Having done this, I'll need to change my initialization of my Property values, as they are now no longer simple 2-tuples:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    prop1 = Property "sessionId" "ABCD1234"&lt;br /&gt;    prop2 = Property "sessionId" "EFGH5678"&lt;br /&gt;    prop3 = Property "sessionId" "WXYZ9876"&lt;br /&gt;    prop4 = Property "userId" "smith"&lt;br /&gt;    prop5 = Property "userId" "adams"&lt;br /&gt;    prop6 = Property "userId" "jobim"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Remember that my &lt;tt&gt;eventProcessor.hs&lt;/tt&gt; file creates a List of sample &lt;tt&gt;Event&lt;/tt&gt; objects.  Now I can use the &lt;tt&gt;head&lt;/tt&gt; function to retrieve the first &lt;tt&gt;Event&lt;/tt&gt; in the list, and then use the new &lt;tt&gt;timestamp&lt;/tt&gt; accessor function to retrieve the timestamp, as in the following.  Note also that &lt;tt&gt;timestamp&lt;/tt&gt;'s type signature ("takes an &lt;tt&gt;Event&lt;/tt&gt;; returns a &lt;tt&gt;Timestamp&lt;/tt&gt;") can be displayed in &lt;tt&gt;ghci&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; let evt1 = head eventList&lt;br /&gt;    *Main&amp;gt; evt1&lt;br /&gt;    Event {timestamp = 1320512200548, className = "java.lang.String", lineNumber = 1293, message = "NPE in substring()", properties = [("userId","smith"),("sessionId","ABCD1234")]}&lt;br /&gt;    *Main&amp;gt; :type timestamp&lt;br /&gt;    timestamp :: Event -&amp;gt; Timestamp&lt;br /&gt;    *Main&amp;gt; timestamp evt1&lt;br /&gt;    1320512200548&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Now we can go back to our function &lt;tt&gt;matchesUserId&lt;/tt&gt;. I decided that before I create this function, I need an additional small function that looks at a single &lt;tt&gt;Property&lt;/tt&gt; and returns &lt;tt&gt;True&lt;/tt&gt; if the key is &lt;tt&gt;userId&lt;/tt&gt; and the value is the passed-in user ID.  I called this function &lt;tt&gt;isUserId&lt;/tt&gt; and placed it in the &lt;tt&gt;eventProcessor.hs&lt;/tt&gt; file, directly below the &lt;tt&gt;Event&lt;/tt&gt; data type definition:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    isUserWithId :: Property -&amp;gt; String -&amp;gt; Bool&lt;br /&gt;    isUserWithId prop id =&lt;br /&gt;      if (key prop == "userId" &amp;amp;&amp;amp; value prop == id)&lt;br /&gt;        then True&lt;br /&gt;        else False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Note  the indentation.  I have defined the type signature in a way that we'll  need to discuss later, when we talk about partial functions and  currying.  Suffice to say the function takes a &lt;tt&gt;Property&lt;/tt&gt; and a &lt;tt&gt;String&lt;/tt&gt; and returns a &lt;tt&gt;Bool&lt;/tt&gt;.  We can test this function against some of the properties I create in this file:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; prop1&lt;br /&gt;    Property {key = "sessionId", value = "ABCD1234"}&lt;br /&gt;    *Main&amp;gt; isUserWithId prop1 "smith"&lt;br /&gt;    False&lt;br /&gt;    *Main&amp;gt; prop4&lt;br /&gt;    Property {key = "userId", value = "smith"}&lt;br /&gt;    *Main&amp;gt; isUserWithId prop4 "smith"&lt;br /&gt;    True&lt;br /&gt;    *Main&amp;gt; prop6&lt;br /&gt;    Property {key = "userId", value = "jobim"}&lt;br /&gt;    *Main&amp;gt; isUserWithId prop6 "smith"&lt;br /&gt;    False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;With that function completed, we can work on &lt;tt&gt;containsUserPropertyWithValue&lt;/tt&gt;, which looks for the user ID in a List of properties.  Here's what I came up with:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    containsUserPropertyWithValue :: [Property] -&amp;gt; String -&amp;gt; Bool&lt;br /&gt;    containsUserPropertyWithValue (x:xs) id =&lt;br /&gt;      if (isUserWithId x id)&lt;br /&gt;        then True&lt;br /&gt;        else containsUserPropertyWithValue xs id&lt;br /&gt;    containsUserPropertyWithValue [] _ = False &lt;/tt&gt;&lt;/pre&gt;and we can test this against a couple of the &lt;tt&gt;Property&lt;/tt&gt; Lists that we created in our sample data:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; containsUserPropertyWithValue propList3 "jobim"&lt;br /&gt;    True&lt;br /&gt;    *Main&amp;gt; containsUserPropertyWithValue propList3 "smith"&lt;br /&gt;    False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Before we move on, note that Haskell has a &lt;tt&gt;where&lt;/tt&gt; clause, in which I can add my &lt;tt&gt;isUserWithId&lt;/tt&gt; function directly to this function.  It makes sense in this case; I am unlikely to need this function anywhere else besides the &lt;tt&gt;containsUserPropertyWithValue&lt;/tt&gt; function.  Let's try this:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    containsUserPropertyWithValue :: [Property] -&amp;gt; String -&amp;gt; Bool&lt;br /&gt;    containsUserPropertyWithValue (x:xs) id =&lt;br /&gt;      if (isUserWithId x id)&lt;br /&gt;        then True&lt;br /&gt;        else containsUserPropertyWithValue xs id&lt;br /&gt;      where&lt;br /&gt;        isUserWithId prop id =&lt;br /&gt;          if (key prop == "userId" &amp;amp;&amp;amp; value prop == id)&lt;br /&gt;            then True&lt;br /&gt;            else False&lt;br /&gt;    containsUserPropertyWithValue [] _ = False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;and I can verify that everything works as before, except that I now no longer have an &lt;tt&gt;isUserWithId&lt;/tt&gt; function in scope:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; isUserWithId prop4 "smith"&lt;br /&gt;&lt;br /&gt;    &lt;interactive&gt;:1:1: Not in scope: `isUserWithId'&lt;br /&gt;&lt;/interactive&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;This function was defined within another function only and so is no longer available to me as a standalone function.&lt;br /&gt;&lt;br /&gt;The final step is to use this function while iterating over the entire list of &lt;tt&gt;Event&lt;/tt&gt;s.  As I described earlier, we won't be iterating in the usual sense.  First I'll experiment with using a recursive function.  On each call, the function will add an &lt;tt&gt;Event&lt;/tt&gt; to the list if it matches the specified user ID.  Here's what my first cut looks like:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    listEventsForUser :: [Event] -&amp;gt; String -&amp;gt; [Event]&lt;br /&gt;    listEventsForUser (x:xs) id =&lt;br /&gt;      if (containsUserPropertyWithValue (properties x) id)&lt;br /&gt;        then x : listEventsForUser xs id&lt;br /&gt;        else listEventsForUser xs id&lt;br /&gt;    listEventsForUser [] _ = []&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If I run this against the sample set of events I generate in this file, I get exactly what I expected:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    Prelude&amp;gt; :load eventProcessor.hs&lt;br /&gt;    [1 of 1] Compiling Main             ( eventProcessor.hs, interpreted )&lt;br /&gt;    Ok, modules loaded: Main.&lt;br /&gt;    *Main&amp;gt; let evtList1 = listEventsForUser eventList "adams"&lt;br /&gt;    *Main&amp;gt; evtList1&lt;br /&gt;    [Event {timestamp = 1320513130333, className = "com.adamsresearch.jarview.JarView", lineNumber = 388, message = "fileNotFound",&lt;br /&gt;properties = [Property {key = "userId", value = &lt;b&gt;"adams"&lt;/b&gt;},Property {key = "sessionId", value = "EFGH5678"}]},&lt;br /&gt;    Event {timestamp = 1320513257324, className = "com.adamsresearch.jarview.ArchiveSearch", lineNumber = 193, message = "search started13255342",&lt;br /&gt;properties = [Property {key = "userId", value = &lt;b&gt;"adams"&lt;/b&gt;},Property {key = "sessionId", value = "EFGH5678"}]},&lt;br /&gt;    Event {timestamp = 1320512260122, className = "com.adamsresearch.jarview.JarView", lineNumber = 725, message = "search started",&lt;br /&gt;properties = [Property {key = "userId", value = &lt;b&gt;"adams"&lt;/b&gt;},Property {key = "sessionId", value = "EFGH5678"}]},&lt;br /&gt;    Event {timestamp = 1320512263122, className = "com.adamsresearch.jarview.JarView", lineNumber = 779, message = "search completed",&lt;br /&gt;properties = [Property {key = "userId", value = &lt;b&gt;"adams"&lt;/b&gt;},Property {key = "sessionId", value = "EFGH5678"}]}]&lt;br /&gt;    *Main&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;(with a little bit of output formatting to make it easier to see that the correct &lt;tt&gt;Event&lt;/tt&gt;s have been selected).&lt;br /&gt;&lt;br /&gt;This post has become chapter-length (although note how compact the actual working code is!), but I have one more topic to discuss.  FP languages like Haskell recognize the above pattern occurs so often that there is built-in support in the language to perform operations on every element in a List, leading to extremely compact but very readable code.  For example, there is the Haskell &lt;tt&gt;map&lt;/tt&gt; function, which takes a function as an argument and applies that function to each element in a list.  Some such functions return Lists, while others reduces Lists to a scalar value.  What would be helpful in our case is the &lt;tt&gt;filter&lt;/tt&gt; function, which applies a function to each List element and returns a List of items for which the filter is true.&lt;br /&gt;&lt;br /&gt;Here is how I would have used &lt;tt&gt;filter&lt;/tt&gt; in this example.  First, I would like to define a function that would apply to an entire event.  To make things a little more compact, I will include (in nested &lt;tt&gt;where&lt;/tt&gt; clauses) my previously-defined functions, as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    eventGeneratedByUser :: String -&amp;gt; Event -&amp;gt; Bool&lt;br /&gt;    eventGeneratedByUser id event =&lt;br /&gt;      if (containsUserPropertyWithValue (properties event) id)&lt;br /&gt;        then True&lt;br /&gt;        else False&lt;br /&gt;      where&lt;br /&gt;        containsUserPropertyWithValue (x:xs) id =&lt;br /&gt;          if (isUserWithId x id)&lt;br /&gt;            then True&lt;br /&gt;            else containsUserPropertyWithValue xs id&lt;br /&gt;          where&lt;br /&gt;            isUserWithId prop id =&lt;br /&gt;              if (key prop == "userId" &amp;amp;&amp;amp; value prop == id)&lt;br /&gt;                then True&lt;br /&gt;                else False&lt;br /&gt;        containsUserPropertyWithValue [] _ = False&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;This is a good time for a "teaser" on partial functions.  Note how I defined my function signature  -- I put the &lt;tt&gt;String&lt;/tt&gt; user ID first, then the &lt;tt&gt;Event&lt;/tt&gt;.  The reason for this organization is that I want to use Haskell's &lt;tt&gt;filter&lt;/tt&gt;, which takes a predicate.  In most examples, the predicate is something simple like the Haskell &lt;tt&gt;odd&lt;/tt&gt; function, which needs no arguments.  If you say &lt;tt&gt;filter odd [1,2,3,4,5,6]&lt;/tt&gt;, you get back &lt;tt&gt;[1,3,5]&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;What do you do if you need to pass an argument to a function (in this case, the user ID) to create the predicate?  The answer lies in that odd signature, in this case&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    eventGeneratedByUser :: String -&amp;gt; Event -&amp;gt; Bool&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;I pass in a user ID and an &lt;tt&gt;Event&lt;/tt&gt;. In that order, specifically. You've probably noticed by now that the signature (whether I define it, or request it from &lt;tt&gt;ghci&lt;/tt&gt;) is &lt;em&gt;not&lt;/em&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    eventGeneratedByUser :: String  Event -&amp;gt; Bool&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;as you would expect from a function taking two arguments.  The function appears (from the actual signature) to be a series of single-argument function invocations.  The reason:  all functions in Haskell actually take only one argument!  Someone might correct my description, but I look on it this way:  this signature defines a function that takes a String, and that newly defined function is itself a function that takes an &lt;tt&gt;Event&lt;/tt&gt;.  In my case, this helps a lot, because in Haskell you can take a multi-argument function and create a &lt;em&gt;partial function&lt;/em&gt; for which you have defined &lt;em&gt;some but not all&lt;/em&gt; of the arguments.  Hence the choice for my ordering of my arguments.  That ordering allows me to create a predicate which is a partial function where "user ID" has already been defined:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; let filterPred = eventGeneratedByUser "adams"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Since I have not fully specified the arguments to this function, what I get back is a function which requires only an &lt;tt&gt;Event&lt;/tt&gt; to return &lt;tt&gt;True&lt;/tt&gt; or &lt;tt&gt;False&lt;/tt&gt;.  Now I have the predicate I need for &lt;tt&gt;filter&lt;/tt&gt;, and here is how I use it:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    *Main&amp;gt; let eventsForAdams = filter filterPred eventList&lt;br /&gt;    *Main&amp;gt; eventsForAdams&lt;br /&gt;    [Event {timestamp = 1320513130333, className = "com.adamsresearch.jarview.JarView", lineNumber = 388, message = "fileNotFound", properties = [Property {key = "userId", value = "adams"},Property {key = "sessionId", value = "EFGH5678"}]},&lt;br /&gt;    Event {timestamp = 1320513257324, className = "com.adamsresearch.jarview.ArchiveSearch", lineNumber = 193, message = "search started13255342", properties = [Property {key = "userId", value = "adams"},Property {key = "sessionId", value = "EFGH5678"}]},&lt;br /&gt;    Event {timestamp = 1320512260122, className = "com.adamsresearch.jarview.JarView", lineNumber = 725, message = "search started", properties = [Property {key = "userId", value = "adams"},Property {key = "sessionId", value = "EFGH5678"}]},&lt;br /&gt;    Event {timestamp = 1320512263122, className = "com.adamsresearch.jarview.JarView", lineNumber = 779, message = "search completed", properties = [Property {key = "userId", value = "adams"},Property {key = "sessionId", value = "EFGH5678"}]}]&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;If I could not define a partial function in Haskell, I could not have used the Haskell &lt;tt&gt;filter&lt;/tt&gt; function for this exercise, as it takes a single argument -- the predicate.  This predicate (by now a single-argument function looking for an &lt;tt&gt;Event&lt;/tt&gt;) is applied to each element of the &lt;tt&gt;Event&lt;/tt&gt; List, and I get exactly what I wanted.&lt;br /&gt;&lt;br /&gt;I really enjoyed creating this post.  For those of you who are at the same level of FP understanding as I am, I hope you found this post both interesting and helpful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-3362747334390600906?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3362747334390600906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3362747334390600906'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/11/haskell-from-oo-developers-perspective.html' title='Haskell From an OO Developer&apos;s Perspective, Part 3'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-7564544273142815627</id><published>2011-11-03T21:27:00.000-07:00</published><updated>2011-11-03T23:42:41.765-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDI'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Debug Interface'/><title type='text'>Breakpoint processing in JDI</title><content type='html'>I've been working on a JDI (Java Debug Interface) project lately and have been posting helpful tips as I go along.  It has been a few years since I've worked with this API, but although I know there have been a few enhancements, the API is quite consistent with what I remember.  In this post I'm going to discuss how to use the API to inspect variable values at a breakpoint.&lt;br /&gt;&lt;br /&gt;As in a &lt;a href="http://wayne-adams.blogspot.com/2011/10/generating-minable-event-stream-with.html"&gt;previous post&lt;/a&gt;, I'll be restricting myself to breakpoint requests (as opposed to method-entry, method-exit, exception requests, etc.), mainly because I know they can be processed rather quickly in near-real-time. Some other types of exceptions significantly slow down the target application, even if you process them as quickly as practical and immediately resume all threads.  In a typical, interactive debugger, a human is in the loop, inspecting variables and making decisions, and a speed difference between JDI event types would not be noticeable.  But in the application I'm developing, I want to pause execution just long enough to collect data and then continue execution immediately.  So I'm going to use only breakpoint requests for my project.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;em&gt;Finding Values at a Breakpoint&lt;/em&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Given an instance &lt;tt&gt;vm&lt;/tt&gt; of a &lt;tt&gt;VirtualMachine&lt;/tt&gt;, you might configure your event-consuming code as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;EventQueue evtQueue = vm.eventQueue();&lt;br /&gt;while(true)&lt;br /&gt;{&lt;br /&gt; EventSet evtSet = evtQueue.remove();&lt;br /&gt; EventIterator evtIter = evtSet.eventIterator();&lt;br /&gt; while (evtIter.hasNext())&lt;br /&gt; {&lt;br /&gt;   try&lt;br /&gt;   {&lt;br /&gt;     Event evt = evtIter.next();&lt;br /&gt;     EventRequest evtReq = evt.request();&lt;br /&gt;     if (evtReq instanceof BreakpointRequest)&lt;br /&gt;     {&lt;br /&gt;       BreakpointRequest bpReq = (BreakpointRequest)evtReq;&lt;br /&gt;       BreakpointEvent bpEvt = (BreakpointEvent)evt;&lt;br /&gt;       ThreadReference threadRef = bpEvt.thread();&lt;br /&gt;       StackFrame stackFrame = threadRef.frame(0);&lt;br /&gt;       ...&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;At this point, you can find variables in two places:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The stack (hence the retrieval of the &lt;tt&gt;StackFrame)&lt;/tt&gt;; for example, local variables in a method;&lt;/li&gt;&lt;li&gt;The current &lt;tt&gt;ObjectReference&lt;/tt&gt;, for static and instance variables.&lt;/li&gt;&lt;/ul&gt;If, at a breakpoint, you are searching for the value of a local variable, let's call it &lt;tt&gt;varName&lt;/tt&gt;, you could find it with the following snippet of code:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;  List&lt;localvariable&gt; visVars = stackFrame.visibleVariables();&lt;br /&gt;for (LocalVariable visibleVar: visVars)&lt;br /&gt;{&lt;br /&gt;  if (visibleVar.name().equals(varName))&lt;br /&gt;  {&lt;br /&gt;    Value val = stackFrame.getValue(visibleVar);&lt;br /&gt;    ...&lt;br /&gt;&lt;/localvariable&gt;&lt;/tt&gt;&lt;/pre&gt;As I've mentioned before, the JDI API isn't big on classes with constructors; most of what you see is interface definitions, with &lt;tt&gt;impl&lt;/tt&gt;s supplied behind the scenes.  So, you would not instantiate a &lt;tt&gt;Field&lt;/tt&gt; in JDI and search for it; instead, you drill down into the API and compare some aspect of the object you want with the data you have at hand.  For example, you list all the &lt;tt&gt;LocalVariable&lt;/tt&gt;s on the stack and then compare their &lt;tt&gt;.name()&lt;/tt&gt;s with the name of your target variable.&lt;br /&gt;&lt;br /&gt;If you don't find your variable on the stack, then you can check the object's fields (I prefer to check the stack first).  To get object field values, you would first get the &lt;tt&gt;ObjectReference&lt;/tt&gt; and then query it:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;ObjectReference objRef = stackFrame.thisObject();&lt;br /&gt;Value targetVal = objRef.getValue(field...&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Halt.  An &lt;tt&gt;ObjectReference&lt;/tt&gt; will get a value for you, but it requires a &lt;tt&gt;Field&lt;/tt&gt; object, for which there is no constructor.  This is just the issue I was discussing above.  Just where do you get a &lt;tt&gt;Field&lt;/tt&gt; object? You query the available &lt;tt&gt;Field&lt;/tt&gt;s of the object's &lt;tt&gt;ReferenceType&lt;/tt&gt; first, then pass those &lt;tt&gt;Field&lt;/tt&gt; references to the object to get their values for this instance:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;ObjectReference objRef = stackFrame.thisObject();&lt;br /&gt;ReferenceType refType = objRef.referenceType();&lt;br /&gt;List&amp;lt;Field&amp;gt; objFields = refType.allFields();&lt;br /&gt;for (int i=0; i&amp;lt;objFields.size(); i++)&lt;br /&gt;{&lt;br /&gt;  Field nextField = objFields.get(i);&lt;br /&gt;  if (nextField.name().equals(varName))&lt;br /&gt;  {&lt;br /&gt;    Value targetVal = objRef.getValue(nextField);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;So there are your values at the breakpoint, obtained either from the stack or the instance fields of the &lt;tt&gt;ObjectReference&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;em&gt;Working with JDI Values&lt;/em&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;tt&gt;Value&lt;/tt&gt; that you get from JDI requires a little effort to be of practical use.  For example, if the &lt;tt&gt;Value&lt;/tt&gt; is an instance of a &lt;tt&gt;StringReference&lt;/tt&gt;, you'll need to cast it to a &lt;tt&gt;StringReference&lt;/tt&gt;, then call &lt;tt&gt;.value()&lt;/tt&gt; to get a &lt;tt&gt;java.lang.String&lt;/tt&gt; value.  If it's an instance of an &lt;tt&gt;IntegerValue&lt;/tt&gt;, then you'll have to cast the &lt;tt&gt;Value&lt;/tt&gt; to an &lt;tt&gt;IntegerValue&lt;/tt&gt; and call &lt;tt&gt;.value()&lt;/tt&gt;, which in this case will return an &lt;tt&gt;int&lt;/tt&gt;!  I find this process to be a little tedious (note: &lt;tt&gt;.toString()&lt;/tt&gt; &lt;em&gt;doesn't&lt;/em&gt; return the value!).  In my case, I'm going to be generating either log output or key-value pairs for each breakpoint event, so my approach is just to write a convenience method that hides the details and provides the value in &lt;tt&gt;String&lt;/tt&gt; form.&lt;br /&gt;&lt;br /&gt;An interesting case is when the &lt;tt&gt;Value&lt;/tt&gt; is itself an &lt;tt&gt;ObjectReference&lt;/tt&gt;.  Just as you can expand variables down to their fields in a typical debugger, you can also choose to drill down into objects at a breakpoint and retrieve &lt;em&gt;their&lt;/em&gt; fields, to an arbitrary level of depth.  The same process can be used for other JDI types, such as &lt;tt&gt;StringReference&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;These fields might not be quite as familiar as the methods you are more accustomed to using.  For example, if you are logging the size of &lt;tt&gt;String&lt;/tt&gt;s that are being generated in your target program, you can't call &lt;tt&gt;.length()&lt;/tt&gt; on the &lt;tt&gt;StringReference&lt;/tt&gt;, but you can get its instance fields and retrieve &lt;tt&gt;count&lt;/tt&gt;, which is the name of the field holding the &lt;tt&gt;String&lt;/tt&gt;'s length.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;em&gt;Practical Considerations&lt;/em&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;While it is possible to drill down to an arbitrary depth in the stack or in the instance's fields, keep in mind that you have halted your application while this is occurring.  It's best to keep processing during this period to a minimum.  While you could spawn a thread to finish processing the breakpoint (for example, creating and sending a JMS message), you will need to retrieve all the variables from the stack and instance while the target application is halted.  So that drill-down should be quick.&lt;br /&gt;&lt;br /&gt;That caveat aside, you can then specify variables in some custom format, such as dot-notation, and then drill down into the fields/variables recursively until you find the value you want.  For example, you could have a variable specified as &lt;tt&gt;fileName.count&lt;/tt&gt;, in which case you would locate the &lt;tt&gt;fileName&lt;/tt&gt; &lt;tt&gt;StringReference&lt;/tt&gt;, then get the instance fields of &lt;tt&gt;fileName&lt;/tt&gt; and find &lt;tt&gt;count&lt;/tt&gt;, which is the length of the file name.&lt;br /&gt;&lt;br /&gt;For fields like &lt;tt&gt;String&lt;/tt&gt;'s &lt;tt&gt;count&lt;/tt&gt;, which might not be an obvious choice to someone configuring a breakpoint specification, some type of browser would be useful.  Browsing the stack isn't an option until you've already set breakpoints and reached a breakpoint, as the stack frame isn't in scope until the breakpoint is reached.  But for static and instance fields, you only need a &lt;tt&gt;ReferenceType&lt;/tt&gt; to list the available &lt;tt&gt;Fields&lt;/tt&gt;, to some configurable depth, before you even start debugging the application.  Since these &lt;tt&gt;Fields&lt;/tt&gt; are available in JDI as soon as the class is loaded, you don't have to halt program execution just to get the static and instance field names for the class.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-7564544273142815627?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/7564544273142815627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/11/breakpoint-processing-in-jdi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7564544273142815627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7564544273142815627'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/11/breakpoint-processing-in-jdi.html' title='Breakpoint processing in JDI'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-9017613106149457291</id><published>2011-10-29T09:17:00.001-07:00</published><updated>2011-10-29T11:32:30.526-07:00</updated><title type='text'>Haskell From an OO Developer's Perspective, Part 2</title><content type='html'>Today I'm looking at Haskell type definition and the use of pattern-matching in functions.  Pattern-matching is much more an integral feature of FP, as opposed to OO.  But first...&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;b&gt;Haskell type definition&lt;/b&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;According to the &lt;a href="http://www.haskell.org/haskellwiki/Algebraic_data_type"&gt;HaskellWiki&lt;/a&gt;, an algebraic data type is a type which specifies the shape of the elements.  One way to approach this topic, if you tend to think in OO, is 1) think C &lt;tt&gt;struct&lt;/tt&gt;s, and 2) try to forget behavior, for a moment.  Even in OO, we've all been there -- sometimes you really want something like a &lt;tt&gt;struct&lt;/tt&gt; just to organize some data, and the only behavior (in an OO sense, meaning "methods") that you really want is a set of accessors/mutators (getters/setters).  So you either swallow a little hard and make the attributes public, or you blast out boilerplate getters/setters. Meanwhile, some people write frameworks of code that automagically expose your attributes, and so on.&lt;br /&gt;&lt;br /&gt;Right now we just want to define a data structure.  We'll be manipulating the structure with functions later, so we don't care about what it "does".  It's just there.  Here's an example of a data-type declaration in Haskell; I'm using it to describe some breakpoints I've serialized from a Java program:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;-- file:  c:/HaskellDev/typesDemo.hs&lt;br /&gt;&lt;br /&gt;type Label = String&lt;br /&gt;type FileName = String&lt;br /&gt;type LineNumber = Int&lt;br /&gt;type MethodName = String&lt;br /&gt;type ExceptionName = String&lt;br /&gt;type Description = String&lt;br /&gt;&lt;br /&gt;data Breakpoint = LineNumberBreakpoint Label FileName LineNumber Description |&lt;br /&gt;MethodBreakpoint Label FileName MethodName Description |&lt;br /&gt;ExceptionBreakpoint Label ExceptionName Description&lt;br /&gt;deriving (Show)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;This isn't the simplest-possible example, but it's representative of a useful structure and allows me to introduce a few things at once.  First, focus on the &lt;tt&gt;data&lt;/tt&gt; keyword; &lt;tt&gt;data&lt;/tt&gt;  is the beginning of the definition of an algebraic data type and is followed by the name of the type (which must start with a capital letter).  This type name is followed by an equals sign and the type-constructor definition.   &lt;tt&gt;"deriving (Show)"&lt;/tt&gt; isn't critical to understanding the type; it provides information &lt;tt&gt;ghci&lt;/tt&gt; needs to output the values we'll create based on this type definition.&lt;br /&gt;&lt;br /&gt;The type constructor definition is composed of one or more value constructors.  These value constructors must also be labeled by a name beginning with a capital letter and are separated by the pipe "|" symbol.  Value constructors and type constructors reside in different "namespaces", so to speak, so if you have a really simple data type, you can use the same label for both the type definition name and the value constructor name and not worry about collisions between the two names.  For example:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;type User = User String String String Int&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Back to our example, let's first get out of the way the list of &lt;tt&gt;type&lt;/tt&gt;s at the beginning of the source file.  These &lt;tt&gt;type&lt;/tt&gt;s are called type synonyms in Haskell and are nothing elaborate; they are available to improve the readability of your code.  So, if I want to describe a breakpoint definition as consisting of a label, the name of the file, the line number in the code, and a short description, in Haskell I could say&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;data Breakpoint = Breakpoint String String Int String&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;or I could improve the readability/understandability of the definition with some type synonyms:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;type Label = String&lt;br /&gt;type FileName = String&lt;br /&gt;type LineNumber = Int&lt;br /&gt;type Description = String&lt;br /&gt;&lt;br /&gt;data Breakpoint = Breakpoint Label FileName LineNumber Description&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;and that's what I've done in our example.  In addition, I've defined three different breakpoint types:  one based on line number, one based on method call (e.g. method-entry, method-exit) (yes, we're using Haskell to analyze breakpoints in a Java class!), and one based on thrown exceptions.&lt;br /&gt;&lt;br /&gt;Going back to our example, the next question would be "what do you do with this type definition?"  At this point I want to launch the Glasgow interpreter/debugger, &lt;tt&gt;ghci&lt;/tt&gt;.  Once this is up and running, I can load my file.  Note that &lt;tt&gt;ghci&lt;/tt&gt; loads by default from the directory in which it was launched; you can set the directory from which it loads with &lt;tt&gt;:cd &lt;em&gt;dirName&lt;/em&gt;&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;*Main&amp;gt; :cd c:/HaskellDev&lt;br /&gt;*Main&amp;gt; :load typesDemo.hs&lt;br /&gt;[1 of 1] Compiling Main             ( typesDemo.hs, interpreted )&lt;br /&gt;Ok, modules loaded: Main.&lt;br /&gt;*Main&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;I now have three value constructors for my Breakpoint data type, and I can  create instances of each.  I do this by referencing the name of the value constructor and providing the arguments that it expects, as specified in the type definition.  Additionally, in &lt;tt&gt;ghci&lt;/tt&gt;, to assign a variable a value, we need to use the &lt;tt&gt;let&lt;/tt&gt; keyword.  First, imagine that we want to create an exception breakpoint, but all we remember is the name of its value constructor.  In &lt;tt&gt;ghci&lt;/tt&gt;, you can get the type info for this value constructor:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;*Main&amp;gt; :type ExceptionBreakpoint&lt;br /&gt;ExceptionBreakpoint&lt;br /&gt;:: Label -&amp;gt; ExceptionName -&amp;gt; Description -&amp;gt; Breakpoint&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;An explanation of the chain of &lt;tt&gt;-&amp;gt;&lt;/tt&gt; symbols will have to wait until a later day, as it is a little foreign to the OO mind.  But for now we can use the output to  remind ourselves what we need to supply to the value constructor.  Let's create an &lt;tt&gt;ExceptionBreakpoint&lt;/tt&gt;, output its value, then use &lt;tt&gt;ghci&lt;/tt&gt;'s &lt;tt&gt;:type&lt;/tt&gt; to output its type:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;*Main&amp;gt; let bp3 = ExceptionBreakpoint "NPE" "java.lang.NullPointerException" "Break on all NullPointerExceptions"&lt;br /&gt;*Main&amp;gt; bp3&lt;br /&gt;ExceptionBreakpoint "NPE" "java.lang.NullPointerException" "Break on all NullPointerExceptions"&lt;br /&gt;*Main&amp;gt; :type bp3&lt;br /&gt;bp3 :: Breakpoint&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Note that &lt;tt&gt;:type&lt;/tt&gt; returns the actual type of the breakpoint, not the name of the value constructor which was used to build it.  There are times when we want to know which value constructor was used -- an excellent segue to the 2nd topic of this post.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;b&gt;Pattern-matching in functions&lt;/b&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Suppose I want to write a function that extracts the description of a breakpoint definition and further, reminds me what type of breakpoint it is.  In Haskell, you accomplish this with pattern matching.  In the following fragment:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;describeBreakpoint (ExceptionBreakpoint _ _ desc) = desc&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;I have defined a function -- &lt;tt&gt;describeBreakpoint&lt;/tt&gt; -- which matches only on an &lt;tt&gt;ExceptionBreakpoint&lt;/tt&gt;.  I've written it to match on a tuple which consists of&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the name of the value constructor&lt;/li&gt;&lt;li&gt;two wildcards ("_", placeholders) for the values I'm not currently interested in (the &lt;tt&gt;Label&lt;/tt&gt; and the &lt;tt&gt;ExceptionName&lt;/tt&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;a parameter for the description, &lt;tt&gt;desc&lt;/tt&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;After the equals sign is the value returned from the function, which is just the description.  Applying this function to the breakpoint we created earlier, I get:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     *Main&amp;gt; describeBreakpoint bp3&lt;br /&gt;    "Break on all NullPointerExceptions"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;This process is called deconstruction, as we've essentially reversed the process we used to create &lt;tt&gt;bp3&lt;/tt&gt;, by using a pattern which looks like the pattern used to construct the breakpoint value.&lt;br /&gt;&lt;br /&gt;Haskell allows us to define a function as a series of predicate/value pairs.  For example, we can update our function to extract the description of any &lt;tt&gt;Breakpoint&lt;/tt&gt; as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;   describeBreakpoint (LineNumberBreakpoint _ _ _ desc) = desc&lt;br /&gt;  describeBreakpoint (MethodBreakpoint _ _ _ desc) = desc&lt;br /&gt;  describeBreakpoint (ExceptionBreakpoint _ _ desc) = desc&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;If we did not do this, we would get an error if we tried to use the function to describe a &lt;tt&gt;LineNumberBreakpoint&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;    *Main&amp;gt; let bp4 = LineNumberBreakpoint "parseParam" "Parser.java" 79 "Break at beginning of parse"&lt;br /&gt;   *Main&amp;gt; describeBreakpoint bp4&lt;br /&gt;   "*** Exception: typesDemo.hs:15:1-56: Non-exhaustive patterns in function describeBreakpoint&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Note that in general FP functions prefer that your matching patterns be exhaustive and will complain if they exhaust the list without a match.  In this case the message should be self-explanatory.  After updating our function as described earlier (and, reloading in &lt;tt&gt;ghci&lt;/tt&gt;, which will require that you re-define the breakpoints), we get the expected answers:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;*Main&amp;gt; :load typesDemo.hs&lt;br /&gt;[1 of 1] Compiling Main             ( typesDemo.hs, interpreted )&lt;br /&gt;Ok, modules loaded: Main.&lt;br /&gt;*Main&amp;gt; let bp3 = ExceptionBreakpoint "NPE" "java.lang.NullPointerException" "Break on all NullPointerExceptions"&lt;br /&gt;*Main&amp;gt; let bp4 = LineNumberBreakpoint "parseParam" "Parser.java" 79 "Break at beginning of parse"&lt;br /&gt;*Main&amp;gt; let bp5 = MethodBreakpoint "initBean" "Parser.java" "init()" "Break at parser init() method"&lt;br /&gt;*Main&amp;gt; describeBreakpoint bp3&lt;br /&gt;"Break on all NullPointerExceptions"&lt;br /&gt;*Main&amp;gt; describeBreakpoint bp4&lt;br /&gt;"Break at beginning of parse"&lt;br /&gt;*Main&amp;gt; describeBreakpoint bp5&lt;br /&gt;"Break at parser init() method"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Note that the matches above treat the value as a simple tuple, where the first element is the name of the value constructor and subsequent elements are simply the values passed to the value constructor.  Pattern matching can be performed on any tuple, in general.  For example, suppose we write a function that returns the 2nd element of a 4-tuple:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     secondElement (a, b, c, d) = b&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;and then try this:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;*Main&amp;gt; secondElement ("Washington", "Lincoln", "Fillmore", "Roosevelt")&lt;br /&gt;"Lincoln"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;That's great.  Now look at this:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;*Main&amp;gt; secondElement ("Washington", "Lincoln", "Fillmore")&lt;br /&gt;&lt;br /&gt;&lt;interactive&gt;:1:15:&lt;br /&gt;   Couldn't match expected type `(t0, t10, t20, t30)'&lt;br /&gt;               with actual type `(t1, t2, t3)'&lt;br /&gt;   In the first argument of `secondElement', namely&lt;br /&gt;     `("Washington", "Lincoln", "Fillmore")'&lt;br /&gt;   In the expression:&lt;br /&gt;     secondElement ("Washington", "Lincoln", "Fillmore")&lt;br /&gt;   In an equation for `it':&lt;br /&gt;       it = secondElement ("Washington", "Lincoln", "Fillmore")&lt;br /&gt;&lt;/interactive&gt;&lt;/tt&gt;&lt;/pre&gt;While there &lt;em&gt;is&lt;/em&gt; a second element in this list, it is a 3-tuple and there is no pattern in the function &lt;tt&gt;secondElement&lt;/tt&gt; which matches a 3-tuple.  We could add another match in the function definition to handle a 3-tuple (and so on), but there are better ways to do this, which we may investigate in later posts.&lt;br /&gt;&lt;br /&gt;As with all other topics I'll be investigating in these early posts, this one is far from exhaustive, and it isn't intended to be.  Again, this discussion reflects what stands out to me, as an OO developer, looking at all of this for the first time.  Next post:  more on thinking in FP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-9017613106149457291?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/9017613106149457291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/9017613106149457291'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/haskell-from-oo-developers-perspective_29.html' title='Haskell From an OO Developer&apos;s Perspective, Part 2'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-4352827293115157346</id><published>2011-10-24T22:35:00.000-07:00</published><updated>2011-10-25T22:36:08.307-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='FP'/><title type='text'>Haskell From an OO Developer's Perspective, Part 1</title><content type='html'>I'm learning Haskell by following O'Sullivan, Goerzen and Stewart's &lt;em&gt;Real World Haskell&lt;/em&gt;.  I've been writing object-oriented code for well over half my career as a developer, and there are things about functional programming that really stand out to me specifically because of my OO background.  My goal is to capture that experience as I learn, because I haven't been able to find much material that speaks to the unique experience of transitioning from OO to FP.  So here goes.&lt;br /&gt;&lt;br /&gt;As you can guess, functions are highly regarded in functional programming.  There is an emphasis on "purity", something you don't hear much about in OO.  Simply put, a pure function does its work without side effects.  Repeatedly invoking a pure function with the same arguments will always yield the same result.&lt;br /&gt;&lt;br /&gt;When you hear this topic discussed in FP, it frequently includes references to mutable state. For example, if invoking your function changes the state of a variable, your function is not pure.  In fact, if your function even references a global variable, it is not pure.  Why?  Because you can't guarantee that invoking your function repeatedly, with the same arguments, will yield the same results, because it relies on state over which it has no control.&lt;br /&gt;&lt;br /&gt;In functional programming, the goal is to keep code as pure as possible and to isolate impure code.  One advantage of pure code is in testing, as you don't have to worry about the effect of other threads on the results produced by your code.  In addition to code that employs mutable state, other examples of impure code are: any I/O, pinging a web service for that live data feed, and so on.  As I go through my self-training, I will be very interested in how useful an FP application will be in my field.  I write mostly middle-tier Java code with a lot of interfaces to web services, and I have to admit at this stage I'm a little skeptical.  Will I write a big chunk of FP code that's 99% "impure" and feel that I just performed the equivalent of porting a Fortran program to C++?  I hope not.  But it's way too early to pass judgment, and I expect a far happier outcome.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Anatomy of a Haskell function&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Functions in Haskell look a lot different than Java functions.  I've spent a few months trying to become proficient in Erlang, and so the structure of an FP function is starting to become familiar to me.  Here's an example Haskell function:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;agentName code =&lt;br /&gt;if code == 86&lt;br /&gt;then "adams"&lt;br /&gt;else if code == 99&lt;br /&gt;then "feldon"&lt;br /&gt;else "unknown"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Given an agent's code number, it returns the agent's (real) name.  In general, a function consists of:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The name of the function&lt;/li&gt;&lt;li&gt;The argument names, separated by whitespace&lt;/li&gt;&lt;li&gt;The equals "=" sign&lt;/li&gt;&lt;li&gt;The expression that your function evaluates and returns&lt;/li&gt;&lt;/ul&gt;Note that the example does not have a return statement.  In this example, the "if" statement &lt;em&gt;itself&lt;/em&gt; is the value returned by the function.  For this reason, you cannot leave an unaccounted-for branch of the if statement.  In other words, if you try to load the following function definition into the interactive Glasgow Haskell compiler:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;agentName code =&lt;br /&gt;if code == 86&lt;br /&gt;then "adams"&lt;br /&gt;else if code == 99&lt;br /&gt;then "feldon"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;you will see the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     agentName.hs:7:1: parse error (possibly incorrect indentation)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;the reason being that there are some inputs for which the function will not be able to return a value at all.  If you've ever declared a non-&lt;tt&gt;void&lt;/tt&gt; Java function and forgot to return a value from a branch of an &lt;tt&gt;if&lt;/tt&gt; statement, then this error message seems reasonable, if not quite as informative.&lt;br /&gt;&lt;br /&gt;If we go back to the original version of the function, we can test its behavior:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;Prelude&amp;gt; :load agentName.hs&lt;br /&gt;[1 of 1] Compiling Main             ( agentName.hs, interpreted )&lt;br /&gt;Ok, modules loaded: Main.&lt;br /&gt;*Main&amp;gt; agentName 86&lt;br /&gt;"adams"&lt;br /&gt;*Main&amp;gt; agentName 99&lt;br /&gt;"feldon"&lt;br /&gt;*Main&amp;gt; agentName 007&lt;br /&gt;"unknown"&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Note, in the examples, the indentation, which is required when a statement (in this case, the function definition) extends across a line boundary.  The size of the indentation and the characters used (space, tab) are not important, as long as the indentation is there.&lt;br /&gt;&lt;br /&gt;There is obviously a lot more to Haskell functions, of course.  The above points are what stand out to me as a mostly-OO developer.&lt;br /&gt;&lt;br /&gt;I've been using the Glasgow Haskell Compiler and, in the examples above, the interactive interpreter (and debugger) &lt;tt&gt;ghci&lt;/tt&gt;.  Although I'm generally following &lt;em&gt;Real World Haskell&lt;/em&gt;, I don't really expect to review the entire book in slow-motion on a blog (who would read that?).  So I may not write a post about defining types unless it seems unusually foreign to OO.  My ultimate goal is to become proficient enough to provide useful and practical advice, oriented toward an OO developer wanting to learn to write production-quality FP code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-4352827293115157346?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4352827293115157346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4352827293115157346'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/haskell-from-oo-developers-perspective.html' title='Haskell From an OO Developer&apos;s Perspective, Part 1'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-2400572092504719197</id><published>2011-10-23T18:57:00.000-07:00</published><updated>2011-10-23T19:48:32.698-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='FP'/><title type='text'>OO to FP: Transition</title><content type='html'>For the last year or so, I've been trying to come up to speed on functional programming, studying bits and pieces here and there.  One interesting source was Bruce Tate's &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;, which included a number of FP languages.  I reviewed the book on this blog -- in seven days -- a few months ago, if that tells you how much time I've devoted to this topic in general!  I've decided to get a little more serious now.&lt;br /&gt;&lt;br /&gt;Since I've been doing primarily object-oriented development for many years, I have a perspective that is different than someone just learning to program.  I think that a person with an OO background might need a slightly different introduction to FP than someone coming in with a clean slate -- it certainly seems that way to me, as I don't feel a lot of the "intro" material emphasizes the differences that an OO person would find important.  The point of my posts on this topic is to capture my own experience learning FP before I forget what my "angle" was (and then myself become useless to an OO person about to go through the same process).&lt;br /&gt;&lt;br /&gt;This experience reminds me of my last development paradigm shift, when a number of my co-workers and I decided to learn object-oriented analysis, design and programming (in those pre-agile days, huge emphasis was placed on the difference between those three phases!).  I worked in a research lab, and we wrote mostly in C and Fortran.  Some of use wanted to become really grounded in OOA/D/P before we started writing code (I was in this camp) and some of us just wanted to start hammering out code.  I could not understand these people in the latter camp.  &lt;em&gt;How could you develop object-oriented code without learning what object-oriented analysis is?  And you're not even going to learn about OOD?  You're skipping the analysis and design phases?  You're just going to be writing Fortran code in C++!&lt;/em&gt;  Ahh!  I was young and thought I would live forever.  Actually, I thought about death a lot (actually, I didn't).&lt;br /&gt;&lt;br /&gt;We used Smalltalk and C++.  Although I was really happy with my Smalltalk tic-tac-toe program (on a Mac), I knew from the beginning that this platform was not going to rule the OO world.  C++ had a lot going for it (and still does): it was a bridge technology from C to object orientation, and the results speak for themselves.  Of course Java has been hot for many years, too, but frankly I suspect that the success C++ had in bridging procedural developers to OO may have been the big enabler for Java.&lt;br /&gt;&lt;br /&gt;One thing about FP:  I'm not sure I see an equivalent bridge technology; not an out-of-the-park winner, at least.  I appreciate the FP-inspired languages that run on the JVM; the JVM seems like a potential bridge technology.  For example, I could probably convince my co-workers to accept some Scala code on our Java platform.  But I don't feel very enthused working with Scala.  If you read my posts on &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;, you know I like Erlang a lot.  I've spent a lot of time learning Erlang, but I'm just now giving up on it for a number of reasons, the main one being that I just don't see it becoming a Java or a C++.  I don't feel particularly competent in my ability to predict which FP language is likely to prevail, though.  I won't be surprised by what happens, but I also know it won't be something I could have predicted, as things seem a little less clear-cut than the competition between OO languages years ago.&lt;br /&gt;&lt;br /&gt;So, here is what I have decided to do:  I'm going to learn Haskell, using the O'Reilly book &lt;em&gt;Real World Haskell&lt;/em&gt;.  My goal is to get a good education in functional programming and not to worry at this time about who's going to "win", and I feel Haskell is a great language to choose to learn FP.  As I learn, I'll collect my thoughts and mention what jumps out at me, as an OO person, and hopefully some other OO people will find the commentary useful.&lt;br /&gt;&lt;br /&gt;I don't hold strong opinions on any of these topics.  Mostly I just want to learn FP and hopefully help other OO developers do the same.  I would also like to be especially proficient in one FP language, so I've made my choice.  If you are interested in Haskell, or are a Java developer interested in FP, I hope I provide something useful to you.  My first post is coming in a couple of days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-2400572092504719197?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/2400572092504719197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/2400572092504719197'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/oo-to-fp-transition.html' title='OO to FP: Transition'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-4448778063162355415</id><published>2011-10-15T08:48:00.000-07:00</published><updated>2011-10-15T10:42:54.217-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UnsatisfiedLinkError'/><category scheme='http://www.blogger.com/atom/ns#' term='JDI'/><category scheme='http://www.blogger.com/atom/ns#' term='no attach in java.library.path'/><category scheme='http://www.blogger.com/atom/ns#' term='debug'/><category scheme='http://www.blogger.com/atom/ns#' term='VisualVM'/><category scheme='http://www.blogger.com/atom/ns#' term='no providers installed'/><category scheme='http://www.blogger.com/atom/ns#' term='shared memory'/><title type='text'>JDI:  three ways to attach to a Java process</title><content type='html'>If you've looked at my recent posts, you know I'm working on a plugin for &lt;a href="http://visualvm.java.net/api-quickstart.html"&gt;VisualVM&lt;/a&gt;, a very useful tool supplied with the JDK.  In one example, I showed how to attach to a waiting Java application using a socket-based &lt;tt&gt;AttachingConnector&lt;/tt&gt;.  At that time I said that there were two primary ways of attaching to a process with JDI -- via shared memory, and with a socket.&lt;br /&gt;&lt;br /&gt;It turns out there is a "third way".  Following is an example of why this way is useful, and why it was provided.&lt;br /&gt;&lt;br /&gt;When I last wrote JDI programs (in Java 5), I would notice that my target application would start up and print (to &lt;tt&gt;stdout&lt;/tt&gt;) the port on which it was listening, as in the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;Listening for transport dt_socket at address: 55779&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;In Java 5, if you detached your debugger from this process, you would get another line to &lt;tt&gt;stdout&lt;/tt&gt; in the target's console, like this:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;Listening for transport dt_socket at address: 55779&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;and this would go on for as long as you chose to attach and detach, etc.&lt;br /&gt;&lt;br /&gt;At some point (and I don't know when this started happening), the port on which the target is listening started changing on each detach of an external debugger.  If in Java 6 (I'm using u20), you repeatedly attach and detach from the target process, you'll see the following out in the target's console:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;Listening for transport dt_socket at address: 55837&lt;br /&gt;ERROR: transport error 202: recv error: Connection reset by peer&lt;br /&gt;Listening for transport dt_socket at address: 55844&lt;br /&gt;ERROR: transport error 202: recv error: Connection reset by peer&lt;br /&gt;Listening for transport dt_socket at address: 55846&lt;br /&gt;ERROR: transport error 202: recv error: Connection reset by peer&lt;br /&gt;Listening for transport dt_socket at address: 55911&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;If you're writing an application that attaches using the debug port, each time you attach you need to find out what port the target is using.  This information is not available from the process itself; in other words, you have to play the usual unpleasant game of capturing console output to know what the port is.  Even if you specify a port at target start, you still need to get your hands on the value.&lt;br /&gt;&lt;br /&gt;You can still find the original request for a feature to attach to a process by its process ID if you search around the old Java bug reports.  The long and short of it:  a new &lt;tt&gt;AttachingConnector&lt;/tt&gt; was created, one which attaches by PID.  As you know, sometimes it isn't much fun finding a process's PID either.  In my case, however, I am writing a plugin for VisualVM, and one thing you get for free when you do that is &lt;a href="http://visualvm.java.net/nonav/apidocs/13/index.html"&gt;Visual VM's API&lt;/a&gt;, which as you might expect includes calls to get the PID.  My goal, then, is to use this new connector in my VisualVM plugin, and I thought it might be appreciated if I shared the details.&lt;br /&gt;&lt;br /&gt;I've adapted my test program from &lt;a href="http://wayne-adams.blogspot.com/2011/10/generating-minable-event-stream-with.html"&gt;an earlier post&lt;/a&gt; so that it now outputs the details of each &lt;tt&gt;AttachingConnector&lt;/tt&gt;; the changed code fragment is shown here:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;List&amp;lt;AttachingConnector&amp;gt; attachingConnectors = vmMgr.attachingConnectors();&lt;br /&gt;for (AttachingConnector ac: attachingConnectors)&lt;br /&gt;{&lt;br /&gt;  Map&lt;string, argument=""&gt; paramsMap = ac.defaultArguments();&lt;br /&gt;  Iterator&lt;string&gt; keyIter = paramsMap.keySet().iterator();&lt;br /&gt;  System.out.println("AttachingConnector:  '" + ac.getClass().getName() + "'");&lt;br /&gt;  System.out.println("  name: '" + ac.name() + "'");&lt;br /&gt;  System.out.println("  description: '" + ac.description() + "'");&lt;br /&gt;  System.out.println("  transport name: '" + ac.transport().name() + "'");&lt;br /&gt;  System.out.println("  default arguments:");&lt;br /&gt;  while (keyIter.hasNext())&lt;br /&gt;  {&lt;br /&gt;    String nextKey = keyIter.next();&lt;br /&gt;    System.out.println("    key: '" + nextKey + "'; value: '" + paramsMap.get(nextKey) + "'");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;The output from this code is shown below:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;AttachingConnector:  'com.sun.tools.jdi.SocketAttachingConnector'&lt;br /&gt; name: 'com.sun.jdi.SocketAttach'&lt;br /&gt; description: 'Attaches by socket to other VMs'&lt;br /&gt; transport name: 'dt_socket'&lt;br /&gt; default arguments:&lt;br /&gt;   key: 'timeout'; value: 'timeout='&lt;br /&gt;   key: 'hostname'; value: 'hostname=AdamsResearch'&lt;br /&gt;   key: 'port'; value: 'port='&lt;br /&gt;AttachingConnector:  'com.sun.tools.jdi.SharedMemoryAttachingConnector'&lt;br /&gt; name: 'com.sun.jdi.SharedMemoryAttach'&lt;br /&gt; description: 'Attaches by shared memory to other VMs'&lt;br /&gt; transport name: 'dt_shmem'&lt;br /&gt; default arguments:&lt;br /&gt;   key: 'timeout'; value: 'timeout='&lt;br /&gt;   key: 'name'; value: 'name='&lt;br /&gt;AttachingConnector:  'com.sun.tools.jdi.ProcessAttachingConnector'&lt;br /&gt; name: 'com.sun.jdi.ProcessAttach'&lt;br /&gt; description: 'Attaches to debuggee by process-id (pid)'&lt;br /&gt; transport name: 'local'&lt;br /&gt; default arguments:&lt;br /&gt;   key: 'pid'; value: 'pid='&lt;br /&gt;   key: 'timeout'; value: 'timeout='&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;A couple of things I hadn't noticed before is that the socket-based connector comes with the &lt;tt&gt;hostname&lt;/tt&gt; argument pre-set to my machine's hostname, and that all three connectors have a &lt;tt&gt;timeout&lt;/tt&gt; default argument.  The first observation brings up an interesting point:  if you use the local, PID-based connector, remember that you'll only be attaching to processes on your debugger's host.&lt;br /&gt;&lt;br /&gt;I changed my test program to use the local connector and it works as before!  Well, no, actually, it does not.  Here's what I now get:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;java.lang.UnsatisfiedLinkError: no attach in java.library.path&lt;br /&gt;Exception in thread "main" java.io.IOException: no providers installed&lt;br /&gt;at com.sun.tools.jdi.ProcessAttachingConnector.attach(ProcessAttachingConnector.java:86)&lt;br /&gt;at com.adamsresearch.jdiDemo.JDIDemo.main(JDIDemo.java:70)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Does this mean the local connector isn't exactly ready for use?  No, but I have been burned by the &lt;a href="http://blogs.oracle.com/sundararajan/entry/using_mustang_s_attach_api"&gt;same issue&lt;/a&gt; that has plagued a number of others (scroll down in that page -- the issue was found by a reader of that post and was solved, partially, by another reader of that post).  I'm working on a Windows platform, and when you do that you have to be a little careful ;-&amp;gt; . In this case, the problem is caused by 1) using the &lt;tt&gt;java&lt;/tt&gt; interpreter as found on the system path, and 2) not making sure that path points directly to your JDK or JRE directory.  The executable will look in a path relative to itself for the needed libraries, and when Windows copies the &lt;tt&gt;java&lt;/tt&gt; executable to &lt;tt&gt;C:\Windows\system32&lt;/tt&gt; (or similar) -- and if you use that executable -- that relative path is broken.  I believe this is the true issue, unlike described in the comments on the above post, where the distinction is made between using the JRE &lt;tt&gt;java&lt;/tt&gt; and the JDK &lt;tt&gt;java&lt;/tt&gt;.  I don't think that's the issue.  For example, below are the results of my attach test in 3 different scenarios:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Using &lt;tt&gt;java&lt;/tt&gt; from my path, the first hit of which comes from &lt;tt&gt;C:\Windows\system32&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;java -cp c:\jdk1.6.0_20\lib\tools.jar;. com.adamsresearch.jdiDemo.JDIDemo 10816 863 fileName&lt;br /&gt;...&lt;br /&gt;java.lang.UnsatisfiedLinkError: no attach in java.library.path&lt;br /&gt;Exception in thread "main" java.io.IOException: no providers installed&lt;br /&gt; at com.sun.tools.jdi.ProcessAttachingConnector.attach(ProcessAttachingConnector.java:86)&lt;br /&gt; at com.adamsresearch.jdiDemo.JDIDemo.main(JDIDemo.java:70)&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Using the full path to the JRE &lt;tt&gt;bin java&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;c:\jdk1.6.0_20\jre\bin\java -cp c:\jdk1.6.0_20\lib\tools.jar;. com.adamsresearch.jdiDemo.JDIDemo 10816 863 fileName&lt;br /&gt;...&lt;br /&gt;Attached to process 'Java HotSpot(TM) 64-Bit Server VM'&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Using the full path to the JDK &lt;tt&gt;bin java&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;c:\jdk1.6.0_20\bin\java -cp c:\jdk1.6.0_20\lib\tools.jar;. com.adamsresearch.jdiDemo.JDIDemo 10816 863 fileName&lt;br /&gt;...&lt;br /&gt;Attached to process 'Java HotSpot(TM) 64-Bit Server VM'&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-family:monospace;"&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;As you can see, the above seems to support my theory that it's not the JRE vs the JDK, but rather the context-poor placement of the &lt;tt&gt;java&lt;/tt&gt; executable in the "usual" Windows binaries directory, that caused the problem.  That posting is several years old, so it is possible that at that time, the needed JDI libraries actually were not included in the JRE, but it is clear that today, you will see the same exception if you use the &lt;tt&gt;java&lt;/tt&gt; executable found in Windows' default binaries directory.&lt;br /&gt;&lt;br /&gt;Now, if I run my JDI application against my &lt;tt&gt;JarView&lt;/tt&gt; utility, searching for &lt;tt&gt;AttachingConnector&lt;/tt&gt; in the JDK installation directory, I get the following output:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'AttachingConnector.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'GenericAttachingConnector$1.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'GenericAttachingConnector.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'ProcessAttachingConnector$1.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'ProcessAttachingConnector$2.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'ProcessAttachingConnector.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'SharedMemoryAttachingConnector$1.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'SharedMemoryAttachingConnector.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'SocketAttachingConnector$1.class'&lt;br /&gt;Breakpoint at line 863:&lt;br /&gt;fileName = 'SocketAttachingConnector.class'&lt;/tt&gt;&lt;/pre&gt;and so have done what I set out to do, which is 1) debug-attach by process ID, and 2) thrash through the inevitable hiccups and share the solutions.  Hopefully this will be useful to you, too.&lt;br /&gt;&lt;br /&gt;Note:  actually, there are even more ways to attach to a Java process. &lt;a href="http://download.oracle.com/javase/6/docs/technotes/guides/jpda/conninv.html"&gt;JPDA Connection and Invocation&lt;/a&gt; is the definitive guide, from Oracle.  If you're going to be writing debuggers, you can't go wrong reading this page first.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-4448778063162355415?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/4448778063162355415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/jdi-three-ways-to-attach-to-java.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4448778063162355415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4448778063162355415'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/jdi-three-ways-to-attach-to-java.html' title='JDI:  three ways to attach to a Java process'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-3410714581847950239</id><published>2011-10-08T09:21:00.000-07:00</published><updated>2011-10-15T08:50:17.143-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDI'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='data mining'/><category scheme='http://www.blogger.com/atom/ns#' term='performance monitoring'/><title type='text'>Generating a minable event stream with JDI</title><content type='html'>Say you've got a good-sized chunk of code, in production, that doesn't always act as expected but it does so often enough that everyone's willing to keep using it (including your customers).  You have a lot on your to-do list, and you keep busy enough just handling the serious meltdowns, so much so that you don't really have time to investigate that occasional failed parse-and-load, or that mysterious stack trace that's supposed to be harmless.  Besides:  your application does &lt;span style="font-style:italic;"&gt;so&lt;/span&gt; much; statistically, it can't get everything right all the time, can it?&lt;br /&gt;&lt;br /&gt;For an issue that isn't easily repeatable but is considered to be a significant problem, running in the debugger can be demoralizing.  What if you could produce the equivalent of a "robo-debugger", a process that would run the debugger for you, continuously, and wait with infinite patience for that rare occurrence?  And then have the common sense to collect information off the stack and -- gasp -- even &lt;span style="font-style:italic;"&gt;tell you about it?&lt;/span&gt;  If this does &lt;span style="font-style:italic;"&gt;not&lt;/span&gt; sound revolutionary, then good for you.  Why do humans ever sit in front of a monitor, stepping through a debugger manually anyway?  We've "manualized" an operation that should be automated.&lt;br /&gt;&lt;br /&gt;Of course, logging could do the same thing for you.  My interest in this idea arose when I was supporting an application for which I had the source code, but I was not permitted to modify it.  I was allowed to recompile the application with the debug switch on, however, and I was allowed to attach with a debugger.  After I wrote a JDI-based monitor for this application, I realized it had one additional advantage -- you don't have to add a lot of logging statements for an issue that might only need to be debugged once.  Also note that code like this could be embedded into another application (for example, it could be a &lt;tt&gt;VisualVM&lt;/tt&gt; extension) and be used to generate events on demand, another reason to skip the embedded logging statements.&lt;br /&gt;&lt;br /&gt;Here's the general approach:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Ensure your target application is compiled with the &lt;tt&gt;-g&lt;/tt&gt; switch.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Start the targeted application as usual, but listening on a port for a debugger connection.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Start your robo-debugger and attach to the target JVM.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Read a list of breakpoint specifications, each of which contains the following information:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Class name and source line number.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;List of variables on the stack that you want to inspect.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Optional message in the form of a formatted String with placeholders for said variables retrieved from the stack.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Optional list of key-value pairs, values again being retrieved from the stack.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;At each defined breakpoint, halt execution (briefly!) and generate an event, realized as a log (to file, JDBC, etc) message, JMS message, etc.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mine the event stream from your application to solve all the issues that have been nagging you since you went to production.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;This post will cover everything except the last item, which is the hard part.  I also won't write logging or JMS code, as that's not relevant to the discussion.  My example will generate some output to &lt;tt&gt;stdout&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;To get started, pick a target application.  I'll be using an application I wrote called "JarView" (just a simple Swing application to search through a directory of .jar files to find a missing class file).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Start the target application&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;There are two primary transports in JPDA (Java Platform Debugger Architecture): socket-based, and shared-memory-based.  I'll start my application using socket-based JPDA and (&lt;tt&gt;transport=dt_socket&lt;/tt&gt;), instruct it to wait for a debugger to attach to it (&lt;tt&gt;server=y&lt;/tt&gt;) and do &lt;em&gt;not&lt;/em&gt; suspend while waiting for a connection (&lt;tt&gt;suspend=n&lt;/tt&gt;):&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     c:\JarView&amp;gt;java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n -cp jarview.jar JarView&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;You'll see a launch message like the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     Listening for transport dt_socket at address: 50069&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;b&gt;Attach to the target&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Write a program to&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Use the JDI &lt;tt&gt;Bootstrap&lt;/tt&gt; class to get an instance of a &lt;tt&gt;VirtualMachineManager.&lt;/tt&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Iterate over the &lt;tt&gt;VirtualMachineManager&lt;/tt&gt;'s list of &lt;tt&gt;AttachingConnector&lt;/tt&gt;s until you find a connector supporting transport &lt;tt&gt;dt_socket.&lt;/tt&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Get the &lt;tt&gt;port&lt;/tt&gt; &lt;tt&gt;Connector.Argument&lt;/tt&gt; of the &lt;tt&gt;AttachingConnector&lt;/tt&gt; and set it to the port on which your target application is listening.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Attach to the &lt;tt&gt;AttachingConnector&lt;/tt&gt; and get an instance of a &lt;tt&gt;VirtualMachine&lt;/tt&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;An example piece of code (bare minimum, with no special exception handling) that will perform the above steps follows.  You will need to compile and run with the JDK's &lt;tt&gt;lib/tools.jar&lt;/tt&gt; on the classpath (this is not found in the JRE, by the way).&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;import java.util.List;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import com.sun.jdi.Bootstrap;&lt;br /&gt;import com.sun.jdi.VirtualMachine;&lt;br /&gt;import com.sun.jdi.VirtualMachineManager;&lt;br /&gt;import com.sun.jdi.connect.AttachingConnector;&lt;br /&gt;import com.sun.jdi.connect.Connector;&lt;br /&gt;&lt;br /&gt;public class JDIDemo&lt;br /&gt;{&lt;br /&gt;public static void main(String[] args) throws Exception&lt;br /&gt;{&lt;br /&gt;  VirtualMachineManager vmMgr = Bootstrap.virtualMachineManager();&lt;br /&gt;  AttachingConnector socketConnector = null;&lt;br /&gt;  List&lt;attachingconnector&gt; attachingConnectors = vmMgr.attachingConnectors();&lt;br /&gt;  for (AttachingConnector ac: attachingConnectors)&lt;br /&gt;  {&lt;br /&gt;    if (ac.transport().name().equals("dt_socket"))&lt;br /&gt;    {&lt;br /&gt;      socketConnector = ac;&lt;br /&gt;      break;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  if (socketConnector != null)&lt;br /&gt;  {&lt;br /&gt;    Map&lt;string, argument=""&gt; paramsMap = socketConnector.defaultArguments();&lt;br /&gt;    Connector.IntegerArgument portArg = (Connector.IntegerArgument)paramsMap.get("port");&lt;br /&gt;    portArg.setValue(Integer.parseInt(args[0]));&lt;br /&gt;    VirtualMachine vm = socketConnector.attach(paramsMap);&lt;br /&gt;    System.out.println("Attached to process '" + vm.name() + "'");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/string,&gt;&lt;/attachingconnector&gt;&lt;/tt&gt;&lt;/pre&gt;It is a lot easier to get a &lt;tt&gt;Connector.Argument&lt;/tt&gt; from an existing data structure (as above) than it is to create one from scratch. Also note, there are very few (if any) constructors in this API; just about every reference you get is retrieved ultimately by going through the &lt;tt&gt;Bootstrap&lt;/tt&gt; class and working your way into the API.   In my example, there were 3 &lt;tt&gt;AttachingConnector&lt;/tt&gt;s, representing transports &lt;tt&gt;dt_socket&lt;/tt&gt;, &lt;tt&gt;dt_shmem&lt;/tt&gt;, and &lt;tt&gt;local&lt;/tt&gt;.  When I run the above example, I see the following output:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;    Attached to process 'Java HotSpot(TM) 64-Bit Server VM'&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Note that when this program exits, the target VM changes the port on which it is listening, something you should remember if you run again.  I don't remember this behavior on Java 5, but it has been a while since I've written a JDI application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pause at a breakpoint and generate an event&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To conclude this post in a reasonable length, I will just pick a line of code in my target that I know well and give some example code that will pick a variable off the stack and output it to &lt;tt&gt;stdout&lt;/tt&gt;.  The details of logging or sending a JMS message aren't really relevant to this topic.&lt;br /&gt;&lt;br /&gt;For this example, I want to break at line 863, where I'm about to add the name of a file to my Swing table.  This is a file whose name at least partially matches an input class name.  Below is a segment of the source:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;849:    if (fullName.lastIndexOf("/") &amp;gt; -1)&lt;br /&gt;850:    {&lt;br /&gt;851:      directoryName = fullName.substring(0, fullName.lastIndexOf("/"));&lt;br /&gt;852:      fileName = fullName.substring(directoryName.length()+1, fullName.length());&lt;br /&gt;853:    }&lt;br /&gt;854:    else&lt;br /&gt;855:    {&lt;br /&gt;856:      fileName = fullName;&lt;br /&gt;857:    }&lt;br /&gt;858:    if (fileName.indexOf(searchForTextField.getText()) &amp;gt; -1)&lt;br /&gt;859:    {&lt;br /&gt;860:      Vector nextRow = new Vector();&lt;br /&gt;861:      nextRow.add(archive.getAbsolutePath());&lt;br /&gt;862:      nextRow.add(fileName);&lt;br /&gt;863:      rowData.add(nextRow);&lt;br /&gt;864:    }&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;I'd like to print a short message at line 863 which outputs the value of &lt;tt&gt;fileName&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;How do you specify a breakpoint in JDI?  You have to know what you're asking for.  Normally you would look for a class, maybe a method, and a line number.  My target application is a Swing application with a lot of anonymous inner classes, so rather than figure out which one is the one I want, I'm just going to search on line number.  You probably want to call a constructor to create a breakpoint for a line number, but there is no constructor; you'll have to search through a lot of metadata and "find" the description of this line of code, then request a breakpoint using that description and a factory method in the &lt;tt&gt;EventRequestManager&lt;/tt&gt;.  To make a long story somewhat shorter:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Get a list of all classes (as &lt;tt&gt;ReferenceType&lt;/tt&gt;s).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For each class, get all line locations (&lt;tt&gt;Location&lt;/tt&gt;).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;At line location corresponding to line 863, break out of the search loop.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Get an instance of the &lt;tt&gt;EventRequestManager&lt;/tt&gt; from the &lt;tt&gt;VirtualMachine.&lt;/tt&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a &lt;tt&gt;BreakpointRequest&lt;/tt&gt; in the &lt;tt&gt;EventRequestManager&lt;/tt&gt;, using the &lt;tt&gt;Location&lt;/tt&gt; object for line 863.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Get the &lt;tt&gt;EventQueue&lt;/tt&gt; instance from the &lt;tt&gt;VirtualMachine.&lt;/tt&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a &lt;tt&gt;while(true)&lt;/tt&gt; loop on the &lt;tt&gt;EventQueue&lt;/tt&gt;, calling its &lt;tt&gt;remove()&lt;/tt&gt; method.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For each &lt;tt&gt;EventSet&lt;/tt&gt; removed from the queue, process each &lt;tt&gt;Event.&lt;/tt&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For each &lt;tt&gt;Event&lt;/tt&gt;, check to see if it is a &lt;tt&gt;BreakpointEvent&lt;/tt&gt;, and if the line number matches the breakpoint we're interested in, process the &lt;tt&gt;Event&lt;/tt&gt; further.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For a matching &lt;tt&gt;Event&lt;/tt&gt;, get the top element of the &lt;tt&gt;StackFrame&lt;/tt&gt;, get all visible variables on the &lt;tt&gt;StackFrame&lt;/tt&gt; element, find the one whose name matches the variable you are looking for, and if so, dig through the API for the correct chain of method calls to extract its value.&lt;/li&gt;&lt;/ol&gt;This is probably easier shown with code.  Below is an updated version of the first cut of the example code (note: please refactor out of &lt;tt&gt;main&lt;/tt&gt; for a real application!):&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;import java.util.List;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import com.sun.jdi.AbsentInformationException;&lt;br /&gt;import com.sun.jdi.Bootstrap;&lt;br /&gt;import com.sun.jdi.LocalVariable;&lt;br /&gt;import com.sun.jdi.Location;&lt;br /&gt;import com.sun.jdi.ReferenceType;&lt;br /&gt;import com.sun.jdi.StackFrame;&lt;br /&gt;import com.sun.jdi.StringReference;&lt;br /&gt;import com.sun.jdi.ThreadReference;&lt;br /&gt;import com.sun.jdi.Value;&lt;br /&gt;import com.sun.jdi.VirtualMachine;&lt;br /&gt;import com.sun.jdi.VirtualMachineManager;&lt;br /&gt;import com.sun.jdi.connect.AttachingConnector;&lt;br /&gt;import com.sun.jdi.connect.Connector;&lt;br /&gt;import com.sun.jdi.event.BreakpointEvent;&lt;br /&gt;import com.sun.jdi.event.Event;&lt;br /&gt;import com.sun.jdi.event.EventIterator;&lt;br /&gt;import com.sun.jdi.event.EventQueue;&lt;br /&gt;import com.sun.jdi.event.EventSet;&lt;br /&gt;import com.sun.jdi.request.BreakpointRequest;&lt;br /&gt;import com.sun.jdi.request.EventRequest;&lt;br /&gt;import com.sun.jdi.request.EventRequestManager;&lt;br /&gt;&lt;br /&gt;public class JDIDemo&lt;br /&gt;{&lt;br /&gt;public static void main(String[] args) throws Exception&lt;br /&gt;{&lt;br /&gt;  if (args.length != 3)&lt;br /&gt;  {&lt;br /&gt;    System.out.println("Usage:  java JDIDemo debugPortNumber sourceLineNumber variableName");&lt;br /&gt;    System.exit(-1);&lt;br /&gt;  }&lt;br /&gt;  int debugPort = Integer.parseInt(args[0]);&lt;br /&gt;  int lineNumber = Integer.parseInt(args[1]);&lt;br /&gt;  String varName = args[2];&lt;br /&gt;&lt;br /&gt;  VirtualMachineManager vmMgr = Bootstrap.virtualMachineManager();&lt;br /&gt;  AttachingConnector socketConnector = null;&lt;br /&gt;  List&lt;attachingconnector&gt; attachingConnectors = vmMgr.attachingConnectors();&lt;br /&gt;  for (AttachingConnector ac: attachingConnectors)&lt;br /&gt;  {&lt;br /&gt;    if (ac.transport().name().equals("dt_socket"))&lt;br /&gt;    {&lt;br /&gt;      socketConnector = ac;&lt;br /&gt;      break;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (socketConnector != null)&lt;br /&gt;  {&lt;br /&gt;    Map&lt;string, argument=""&gt; paramsMap = socketConnector.defaultArguments();&lt;br /&gt;    Connector.IntegerArgument portArg = (Connector.IntegerArgument)paramsMap.get("port");&lt;br /&gt;    portArg.setValue(debugPort);&lt;br /&gt;    VirtualMachine vm = socketConnector.attach(paramsMap);&lt;br /&gt;    System.out.println("Attached to process '" + vm.name() + "'");&lt;br /&gt;&lt;br /&gt;    List&lt;referencetype&gt; refTypes = vm.allClasses();&lt;br /&gt;    Location breakpointLocation = null;&lt;br /&gt;    for (ReferenceType refType: refTypes)&lt;br /&gt;    {&lt;br /&gt;      if (breakpointLocation != null)&lt;br /&gt;      {&lt;br /&gt;        break;&lt;br /&gt;      }&lt;br /&gt;      List&lt;location&gt; locs = refType.allLineLocations();&lt;br /&gt;      for (Location loc: locs)&lt;br /&gt;      {&lt;br /&gt;        if (loc.lineNumber() == lineNumber)&lt;br /&gt;        {&lt;br /&gt;          breakpointLocation = loc;&lt;br /&gt;          break;&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (breakpointLocation != null)&lt;br /&gt;    {&lt;br /&gt;      EventRequestManager evtReqMgr = vm.eventRequestManager();&lt;br /&gt;      BreakpointRequest bReq = evtReqMgr.createBreakpointRequest(breakpointLocation);&lt;br /&gt;      bReq.setSuspendPolicy(BreakpointRequest.SUSPEND_ALL);&lt;br /&gt;      bReq.enable();&lt;br /&gt;      EventQueue evtQueue = vm.eventQueue();&lt;br /&gt;      while(true)&lt;br /&gt;      {&lt;br /&gt;        EventSet evtSet = evtQueue.remove();&lt;br /&gt;        EventIterator evtIter = evtSet.eventIterator();&lt;br /&gt;        while (evtIter.hasNext())&lt;br /&gt;        {&lt;br /&gt;          try&lt;br /&gt;          {&lt;br /&gt;            Event evt = evtIter.next();&lt;br /&gt;            EventRequest evtReq = evt.request();&lt;br /&gt;            if (evtReq instanceof BreakpointRequest)&lt;br /&gt;            {&lt;br /&gt;              BreakpointRequest bpReq = (BreakpointRequest)evtReq;&lt;br /&gt;              if (bpReq.location().lineNumber() == lineNumber)&lt;br /&gt;              {&lt;br /&gt;                System.out.println("Breakpoint at line " + lineNumber + ": ");&lt;br /&gt;                BreakpointEvent brEvt = (BreakpointEvent)evt;&lt;br /&gt;                ThreadReference threadRef = brEvt.thread();&lt;br /&gt;                StackFrame stackFrame = threadRef.frame(0);&lt;br /&gt;                List&lt;localvariable&gt; visVars = stackFrame.visibleVariables();&lt;br /&gt;                for (LocalVariable visibleVar: visVars)&lt;br /&gt;                {&lt;br /&gt;                  if (visibleVar.name().equals(varName))&lt;br /&gt;                  {&lt;br /&gt;                    Value val = stackFrame.getValue(visibleVar);&lt;br /&gt;                    if (val instanceof StringReference)&lt;br /&gt;                    {&lt;br /&gt;                      String varNameValue = ((StringReference)val).value();&lt;br /&gt;                      System.out.println(varName + " = '" + varNameValue + "'");&lt;br /&gt;                    }&lt;br /&gt;                  }&lt;br /&gt;                }&lt;br /&gt;              }&lt;br /&gt;            }&lt;br /&gt;          }&lt;br /&gt;          catch (AbsentInformationException aie)&lt;br /&gt;          {&lt;br /&gt;            System.out.println("AbsentInformationException: did you compile your target application with -g option?");&lt;br /&gt;          }&lt;br /&gt;          catch (Exception exc)&lt;br /&gt;          {&lt;br /&gt;            System.out.println(exc.getClass().getName() + ": " + exc.getMessage());&lt;br /&gt;          }&lt;br /&gt;          finally&lt;br /&gt;          {&lt;br /&gt;            evtSet.resume();&lt;br /&gt;          }&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/localvariable&gt;&lt;/location&gt;&lt;/referencetype&gt;&lt;/string,&gt;&lt;/attachingconnector&gt;&lt;/tt&gt;&lt;/pre&gt;When I run this application with a command line like:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;     java -cp c:\jdk1.6.0_20\lib\tools.jar;. JDIDemo 56485 863 fileName&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;I get the following output:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;    Attached to process 'Java HotSpot(TM) 64-Bit Server VM'&lt;br /&gt;   Breakpoint at line 863:&lt;br /&gt;   fileName = 'BreakpointEvent.class'&lt;br /&gt;   Breakpoint at line 863:&lt;br /&gt;   fileName = 'EventSetImpl$BreakpointEventImpl.class'&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;b&gt;Pointers&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;You might have noticed the line above referencing the &lt;tt&gt;AbsentInformationException&lt;/tt&gt;.  You will get this if your target application has not been compiled with the debug (&lt;tt&gt;-g&lt;/tt&gt;) switch.  If you cannot compile the code with the debug switch, you will be able to set a breakpoint, but there won't be any information available on the stack when you get there.&lt;br /&gt;&lt;br /&gt;Some JDI operations are more expensive than others.  The last time I wrote a JDI application, I noticed that "method-entry" and "method-exit" breakpoints were enormously more expensive than simple line breakpoints.  Now that I have a working example, I'll investigate these issues in a later post to see how things are in the current update of Java 6.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-3410714581847950239?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/3410714581847950239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/generating-minable-event-stream-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3410714581847950239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3410714581847950239'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/generating-minable-event-stream-with.html' title='Generating a minable event stream with JDI'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-4578228059501614021</id><published>2011-10-04T19:11:00.000-07:00</published><updated>2011-10-15T08:52:01.522-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Getting Started'/><category scheme='http://www.blogger.com/atom/ns#' term='VisualVM'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans 7'/><category scheme='http://www.blogger.com/atom/ns#' term='Hello World'/><title type='text'>VisualVM Extensions</title><content type='html'>As I mentioned in an &lt;a href="http://wayne-adams.blogspot.com/2011/10/extending-jvisualvm-more-on-getting.html"&gt;earlier post&lt;/a&gt;, I noticed recently that the JDK utility &lt;tt&gt;VisualVM&lt;/tt&gt; is extensible, and it was my goal to create a useful extension.  I didn't intend to create a "getting started" guide, as there is plenty of information already available, but I keep running into the "out of date tutorial" issue.  Having encapsulated some additional information into my earlier post in the setup category, I now find myself having to clear up issues I'm encountering while using NetBeans 7 to actually create an extension.  While some of the differences might be traceable to the new version of NetBeans, I think some of them may be due to expected API changes and similar issues.&lt;br /&gt;&lt;br /&gt;I'm working through the &lt;a href="http://visualvm.java.net/api-quickstart.html#hello"&gt;Creating a "Hello World" Plugin&lt;/a&gt; tutorial.  I'll basically follow that tutorial here, with changes and observations/tips as needed.&lt;br /&gt;&lt;br /&gt;If you followed my earlier post, you already have a new project, as that step was necessary to "seed" the Platform Manager into the clean-install NetBeans 7 Tools menu.  If not, just follow Geertjan's steps in his tutorial.  My next step was to create the Module Installer.  In NetBeans 7, the selection items are slightly different.  You still choose "New", then "Other...", then select "Module Development", but the File Type is now called "Installer / Activator" rather than "Module Installer".  Further, the description says this installer is frequently not needed.  I don't know if that's the case here, so I created one anyway.&lt;br /&gt;&lt;br /&gt;The tutorial says to add the "VisualVM-Core" library as a dependency for the project.  As you create your "Hello World" application according to the tutorial, you'll quickly learn that you also need to add a dependency on "VisualVM-Application", also, so you may as well do so at the same time.&lt;br /&gt;&lt;br /&gt;If you're not fond of "seeing red" in an IDE, you might want to create the Java classes in the reverse order of the tutorial.  Also, source listings in the tutorial don't include imports (the downloadable full sample does, of course).  If you don't feel like retrieving the full sample, here are the imports for the &lt;tt&gt;HelloWorldProvider&lt;/tt&gt; class:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; import com.sun.tools.visualvm.application.Application;&lt;br /&gt; import com.sun.tools.visualvm.core.ui.DataSourceView;&lt;br /&gt; import com.sun.tools.visualvm.core.ui.DataSourceViewProvider;&lt;br /&gt; import com.sun.tools.visualvm.core.ui.DataSourceViewsManager;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;and, in the &lt;tt&gt;HelloWorldView&lt;/tt&gt; class:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; import javax.swing.ImageIcon;&lt;br /&gt; import com.sun.tools.visualvm.application.Application;&lt;br /&gt; import com.sun.tools.visualvm.core.ui.DataSourceView;&lt;br /&gt; import com.sun.tools.visualvm.core.ui.components.DataViewComponent;&lt;br /&gt; import javax.swing.BorderFactory;&lt;br /&gt; import javax.swing.JEditorPane;&lt;br /&gt; import javax.swing.JPanel;&lt;br /&gt; import org.openide.util.Utilities;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;From here, right-click on the project and select "Run" and you will get an instance of VisualVM.  Selecting an application to monitor will expose your new "Hello World" tab.  That was actually quite easy!&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;Pause for Perspective&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;What have we just done?&lt;br /&gt;&lt;br /&gt;With VisualVM extensions, there are two different paths you can take:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Creating a new tool that you want to make available to VisualVM, a tool that will be available to analyze any Java application.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Providing a plugin for a unique type of application and using VisualVM to expose tooling specific to that application type.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;What we have done in this "Hello World" is an example of #1 above, provided in the form of a new tab.  If you do this, you aren't likely going to be leveraging anything unique about whatever application you are currently thinking of monitoring -- this version of VisualVM will expose the new tab for any and all Java applications to which it attaches.&lt;br /&gt;&lt;br /&gt;Which type you choose will probably depend on what project currently interests you, and your general motivations.  For example, it seems every project I work on could really use an application-specific VisualVM plugin.  I typically use VisualVM on every project I work on, but I have to admit I don't see a lot of other users (unfortunately, because I think it's a great tool).  In a production situation, technical support personnel are usually familiar with a small set of tools specific to their environment.  For example, a WLS shop has support staff who are familiar with the WLS console; switching to JBoss in such a shop is a lot more complex than simply convincing someone of the technical virtues of one platform over another.  There's a training and support issue, too.  Additionally, I don't know of &lt;em&gt;any&lt;/em&gt; support staff who use VisualVM.&lt;br /&gt;&lt;br /&gt;Much as I'd like to provide a unique plugin for the applications I'm currently involved with, it would be a big investment for something that might not get a lot of adoption (and be useless for almost any other application).  So, I probably would be more motivated to build a general-purpose module, or build a module that could be highly configurable for any application.&lt;br /&gt;&lt;br /&gt;I have an idea in mind for just such a project; I'll share it at a later date.  That way, if I get distracted by the guitar or &lt;a href="http://www.meetup.com/Cafe-Brasileira/"&gt;practicing Portuguese&lt;/a&gt; and never get around to doing it, there won't be any 404s from my blog.  But if I do get around to it, I'll update this entry &lt;em&gt;just as soon as I do!&lt;/em&gt;  In the interim, I hope that everyone who sees this will be motivated to add some valuable content to VisualVM.  More later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-4578228059501614021?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/4578228059501614021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/visualvm-extensions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4578228059501614021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4578228059501614021'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/visualvm-extensions.html' title='VisualVM Extensions'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-283913908673952822</id><published>2011-10-02T20:10:00.000-07:00</published><updated>2011-10-15T08:52:37.919-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Getting Started'/><category scheme='http://www.blogger.com/atom/ns#' term='VisualVM'/><category scheme='http://www.blogger.com/atom/ns#' term='Platform Manager'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans 7'/><title type='text'>Extending JVisualVM  -- More on Getting Started</title><content type='html'>I'm not sure when this happened, but at some point the JDK-included VisualVM utility became extensible.  This is really great news for me.  Writing a profiler is a lot of work (although admittedly very interesting and fun).  VisualVM has become such a great tool that I welcome the opportunity to add a plugin to it.&lt;br /&gt;&lt;br /&gt;Oracle has provided a lot of information in this area, which I do recommend reading.  Look at &lt;a href="http://visualvm.java.net/api-quickstart.html"&gt;Getting Started extending VisualVM&lt;/a&gt; and a number of links at the bottom of that page.  It helps a lot to get NetBeans if you don't already have it, as it has significant support built-in to develop VisualVM plugins.&lt;br /&gt;&lt;br /&gt;Rather than repeating "getting started" info, I planned to produce an actual VisualVM plugin in this entry, but I ran into some issues with the "getting started" guide.  So, this is a "getting started" update for NetBeans 7.0.1 users, especially those who have just installed it (as I have) and have not yet created any projects.&lt;br /&gt;&lt;br /&gt;As usual, some things in the "getting started" guides don't turn out as expected.  For example, the guides say to choose "Platform Manager" from the "Tools" menu; in my NetBeans 7.0.1 installation, there was no such menu item. It seems things have changed slightly.  If you are using NetBeans 7.0.1, here is how I worked my way around the problem:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;"File", "New Project..."&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Under "Choose Project", choose "NetBeans Modules"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Under "Projects", choose "Module"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click "Next"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click "Standalone Module"; the dropdown mostly likely says "NetBeans IDE 7.0.1...".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click on the "Manage..." button.  This click will bring up the coveted Platform Manager.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click "Add Platform..."&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now, rather than browse to the root folder of the VisualVM application and select that directory (Platform Manager won't let you use it), instead browse to the root folder of the JDK you are using in NetBeans, drill down into the &lt;tt&gt;lib&lt;/tt&gt; directory, and select "VisualVM".  Click "Next".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you're OK with the default name "VisualVM", click "Finish".  I named mine "VisualVM 1.6u20", to identify which version I chose.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The newly-added platform should be selected in the "Platforms:" dialog.  Click "Close" and then in the "New Module" dialog, choose the VisualVM platform.  Click "Next".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Provide a Code Name Base for the project (an example is given in the dialog) and click "Finish".  You will now have a new project that will be built against the registered VisualVM binary.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;I noticed that once I created a project and opened it (using the above steps), the "Tools" menu in NetBeans 7.0.1 became &lt;em&gt;much&lt;/em&gt; more populated, including a menu item called "NetBeans Platforms".  Apparently it was necessary to create and open one project to populate the "Tools" menu (however, it stays populated even if you close the new project).  The only problem is that I needed for it to be populated &lt;em&gt;before&lt;/em&gt; I created my project, so that I could make it a VisualVM project.  The above steps show you how to achieve this goal if you have a fresh NetBeans deployment.&lt;br /&gt;&lt;br /&gt;Now, on to that plugin I was going to write...  That will have to wait for another day.  Before I write that plugin, I have another post you might want to read that clears up some inconsistencies between the currently-published "getting started" tutorials and my actual experience trying to use them with NetBeans 7.  It's called &lt;a href="http://wayne-adams.blogspot.com/2011/10/visualvm-extensions.html"&gt;VisualVM Extensions&lt;/a&gt;.  After &lt;em&gt;that&lt;/em&gt; post, then I will get around to writing a (hopefully) useful VisualVM extension.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-283913908673952822?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/283913908673952822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/extending-jvisualvm-more-on-getting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/283913908673952822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/283913908673952822'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/extending-jvisualvm-more-on-getting.html' title='Extending JVisualVM  -- More on Getting Started'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-3481192370219968090</id><published>2011-10-01T09:49:00.000-07:00</published><updated>2011-10-15T08:53:08.956-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maxWaitAfterWrite'/><category scheme='http://www.blogger.com/atom/ns#' term='DWR'/><category scheme='http://www.blogger.com/atom/ns#' term='Direct Web Remoting'/><category scheme='http://www.blogger.com/atom/ns#' term='PollHandler'/><title type='text'>Direct Web Remoting tips</title><content type='html'>We use DWR (&lt;tt&gt;&lt;a href="http://www.directwebremoting.org/"&gt;http://www.directwebremoting.org&lt;/a&gt;&lt;/tt&gt;) a lot where I'm working now.  It's a Java library used to integrate JavaScript-based web development with Java middleware.  In addition to providing a servlet that creates a nice JavaScript library (that delegates to your server-side Java beans), it also does server push (reverse Ajax) in a variety of flavors and situations.  I'm really happy with it; you kind of just put it in your application and it works without a lot of trouble.&lt;br /&gt;&lt;br /&gt;I recently had to dig a little into the source to learn how to do something I think might be generally useful (how to change, in real time, parameters which are typically only set via &lt;tt&gt;init-params&lt;/tt&gt; in &lt;tt&gt;web.xml&lt;/tt&gt;), so that's the topic here.  If you aren't a DWR user, this might not be very interesting!&lt;br /&gt;&lt;br /&gt;In my case, I needed to change DWR's &lt;tt&gt;maxWaitAfterWrite&lt;/tt&gt; parameter, a DWR servlet &lt;tt&gt;init-param&lt;/tt&gt;.  Normally you set this once in &lt;tt&gt;web.xml&lt;/tt&gt;, with:&lt;br /&gt;&lt;pre&gt;&amp;lt;init-param&amp;gt;&lt;br /&gt;&amp;lt;param-name&amp;gt;maxWaitAfterWrite&amp;lt;/param-name&amp;gt;&lt;br /&gt;&amp;lt;param-value&amp;gt;5000&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/init-param&amp;gt;&lt;br /&gt;&lt;/pre&gt;(&lt;tt&gt;maxWaitAfterWrite&lt;/tt&gt; refers to the amount of time DWR waits, after output has occurred, before closing the browser connection).  DWR has an &lt;tt&gt;org.directwebremoting.Container&lt;/tt&gt; class which is used to inject properties, including this one, but no immediately obvious API for changing it during an active deployment.&lt;br /&gt;&lt;br /&gt;As it turns out, DWR's IoC container is accessible from its &lt;tt&gt;org.directwebremoting.ServerContext&lt;/tt&gt;, and this is the path to changing this parameter, at least.  The &lt;tt&gt;Container&lt;/tt&gt; holds a number of beans.  Some of these are &lt;tt&gt;java.lang.String&lt;/tt&gt;s (for example, the initial value of &lt;tt&gt;maxWaitAfterWrite&lt;/tt&gt;) and are read-only, but some of these are DWR classes with APIs that you can use to your advantage.&lt;br /&gt;&lt;br /&gt;As I mentioned, the value of &lt;tt&gt;maxWaitAfterWrite&lt;/tt&gt; from &lt;tt&gt;web.xml&lt;/tt&gt; is injected into a &lt;tt&gt;Container&lt;/tt&gt; bean of type &lt;tt&gt;java.lang.String&lt;/tt&gt; and named &lt;tt&gt;maxWaitAfterWrite&lt;/tt&gt;.  However, this parameter is itself injected at deployment time into any DWR class which extends &lt;tt&gt;org.directwebremoting.dwrp.BasePollHandler&lt;/tt&gt;.  You can iterate over the beans in &lt;tt&gt;Container&lt;/tt&gt; and find (on my deployment, at least) two beans which are instances of &lt;tt&gt;BasePollHandler&lt;/tt&gt;.  Below is some code which gets a reference to the &lt;tt&gt;Container&lt;/tt&gt; and iterates over its beans, outputting the details on the &lt;tt&gt;maxWaitAfterWrite&lt;/tt&gt; bean and any instances of &lt;tt&gt;BasePollHandler&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;package com.adamsresearch;&lt;br /&gt;&lt;br /&gt;import java.util.*;&lt;br /&gt;import org.directwebremoting.*;&lt;br /&gt;import org.directwebremoting.dwrp.*;&lt;br /&gt;&lt;br /&gt;public class JavaEndpoint&lt;br /&gt;{&lt;br /&gt;public JavaEndpoint()&lt;br /&gt;{&lt;br /&gt;  ServerContext sc = ServerContextFactory.get();&lt;br /&gt;  Container cont = sc.getContainer();&lt;br /&gt;  Collection&lt;string&gt; beanNamesColl = cont.getBeanNames();&lt;br /&gt;  Iterator&lt;string&gt; beanNames = beanNamesColl.iterator();&lt;br /&gt;  while (beanNames.hasNext())&lt;br /&gt;  {&lt;br /&gt;    String nextBeanName = beanNames.next();&lt;br /&gt;    if (nextBeanName.equals("maxWaitAfterWrite"))&lt;br /&gt;    {&lt;br /&gt;      System.out.println("Bean name:  '" + nextBeanName + "'");&lt;br /&gt;      String staticBean = (String)cont.getBean(nextBeanName);&lt;br /&gt;      System.out.println("  Class:  java.lang.String");&lt;br /&gt;      System.out.println("  Value:  '" + staticBean + "'");&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;      Object nextBean = cont.getBean(nextBeanName);&lt;br /&gt;      if (nextBean instanceof BasePollHandler)&lt;br /&gt;      {&lt;br /&gt;        System.out.println("Bean name: '" + nextBeanName + "'");&lt;br /&gt;        System.out.println("  Class:  " + nextBean.getClass().getName());&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/string&gt;&lt;/string&gt;&lt;/pre&gt;&lt;br /&gt;If you add a method to this Java bean and invoke it from DWR, when the constructor is called, you should see output like the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;Bean name:  'maxWaitAfterWrite'&lt;br /&gt;  Class:  java.lang.String&lt;br /&gt;  Value:  '500'&lt;br /&gt;Bean name: 'url:/call/htmlpoll/'&lt;br /&gt;  Class:  org.directwebremoting.dwrp.HtmlPollHandler&lt;br /&gt;Bean name: 'url:/call/plainpoll/'&lt;br /&gt;  Class:  org.directwebremoting.dwrp.PlainPollHandler&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;As subclasses of &lt;tt&gt;BasePollHandler&lt;/tt&gt;, &lt;tt&gt;HtmlPollHandler&lt;/tt&gt; and &lt;tt&gt;PlainPollHandler&lt;/tt&gt; inherit the method &lt;tt&gt;setMaxWaitAfterWrite()&lt;/tt&gt;.  For my particular situation, then, I just grab all &lt;tt&gt;BasePollHandlers&lt;/tt&gt; from the DWR &lt;tt&gt;Container&lt;/tt&gt; (via their bean names, as output above) and set the parameter as needed.&lt;br /&gt;&lt;br /&gt;This isn't rocket science, but it took me 2 or 3 hours to learn this, and there aren't any hits on the subject AFAIK.  So, hopefully this will be useful to someone out there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-3481192370219968090?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/3481192370219968090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/direct-web-remoting-tips.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3481192370219968090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3481192370219968090'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/10/direct-web-remoting-tips.html' title='Direct Web Remoting tips'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-5071408262527556302</id><published>2011-04-03T11:24:00.001-07:00</published><updated>2011-04-03T20:42:27.958-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Day 7 -- Haskell</title><content type='html'>I've reached the 7th and final language of Bruce Tate's &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;.  While some of the previous languages were functional with some imperative support, Haskell is a purely functional, and statically typed, language.  I'm looking forward to seeing how I will perform tasks with no (or little -- more on that below) state.&lt;br /&gt;&lt;br /&gt;Bruce starts with the usual investigation of types, including looking at Haskell's type inference, then moves on to functions.  Functions are composed of a type declaration and the function declaration.  Because Haskell is statically typed, a function must have a type, but the declaration isn't strictly necessary because of Haskell's type inferencing.  He covers some examples using Erlang-familiar pattern matching and guards.  As with many of the other languages in this book, Haskell uses tail-recursion optimization.  Next we look at programming with tuples, and using tuples to combine functions.  We follow with a discussion of Haskell lists, including generating them with recursion, ranges, and list comprehension (a feature shared with Erlang).  By the way, Bruce's explanation of list comprehension here is one of the many reasons I like this book.  I didn't quite catch it the first time, but his elaboration here is quite articulate.&lt;br /&gt;&lt;br /&gt;Day 1 of Haskell finishes with an interview with Philip Wadler, a member of the committee which designed Haskell.  One thing I took away from this interview was the variety of organizations in which Haskell is being used, which is very encouraging.  I've been doing OO for 20 years now and I suppose I'm just looking around for evidence that it can be safe and effective to give up mutable state.  I may actually decide to learn Haskell first, then pick up more Scala, as a way of disciplining myself to stick with the paradigm.&lt;br /&gt;&lt;br /&gt;Day 2 starts with higher-order functions, including anonymous functions and partially-applied functions.  Bruce then discusses some common functions, like &lt;tt&gt;filter&lt;/tt&gt; and the Haskell versions of fold-left and fold-right.&lt;br /&gt;&lt;br /&gt;Bruce spends a little more time discussing function composition.  Every function in Haskell has only one parameter, which, as you can guess, leads to some interesting functional composition requirements to perform any useful computation.  You can define a function with multiple parameters, but Haskell will split the function into multiple functions, one with each argument, a procedure known as partial application, or currying.  Next he discusses lazy evaluation and how, as in Clojure, it can be used to create infinite lists, where only the parts necessary to perform a task are actually calculated.  He finishes this section by describing how problem solutions can be constructed by chaining/nesting functions.&lt;br /&gt;&lt;br /&gt;Haskell was created by committee.  One side effect of this process is that a number of talented individuals not only contributed to the language, but are potentially available to share their thoughts on the genesis of  the language.  Bruce next interviews Simon Peyton-Jones, another member of the Haskell creation committee, and the lead designer of the GHC compiler.  Peyton-Jones makes one observation that really sticks with me -- Haskell is a useful, successful language, designed by committee!  How often does that happen?&lt;br /&gt;&lt;br /&gt;Day 3 begins with a deeper dive into Haskell's type system, which Bruce calls one of its strongest features.  As I mentioned earlier, the typing is static, but Haskell is smart enough to infer types most of the time, sparing some boilerplate.  Developers can define their own data types with the &lt;tt&gt;data&lt;/tt&gt; keyword.  He then discusses defining polymorphic data types and recursive data types (the latter of which could be used to define a tree, for example).&lt;br /&gt;&lt;br /&gt;Next is a discussion of Haskell classes, with a side note that these are &lt;em&gt;not&lt;/em&gt; object-oriented classes.  There is no data involved in a Haskell class!  So a class, as Bruce puts it, "defines which operations can work on which inputs."  So a type is an instance of a class if it supports all the functions signatures which make up the definition of the class.&lt;br /&gt;&lt;br /&gt;Monads are discussed next.  Bruce describes some example problems which are awkward to formulate in a functional language as a motivation for the use of monads, which are basically a technique of function composition.  When I referred earlier to absence of state, but with a qualification, I was looking ahead to monads.  Monads allow you to simulate state in a Haskell program.  He goes on to outline the components of a monad, which are a container-based type constructor, a &lt;tt&gt;return&lt;/tt&gt; function which wraps a function into a monad, and a bind function that unwraps the function.  He then gives a few non-trivial monad-construction examples, including the use of the Haskell &lt;tt&gt;do&lt;/tt&gt; notation to add some syntactic sugar.  Bruce ends his Day 3 of Haskell with a discussion of the language's core strengths and weaknesses.&lt;br /&gt;&lt;br /&gt;My Personal Wrap-Up&lt;br /&gt;&lt;br /&gt;I started reading this book with some understanding and hands-on experience with Scala, and a slight feeling of lost opportunity as a result (Was this a good idea?  Will I really learn functional programming with a "compromise" language?).  I still feel that way a little, but I still expect to move forward with Scala as my bridge to the FP world, although with a better understanding of what compromises I am making in the process.  I'm considering learning Haskell, at least minimally, to see what it's like for me to work with a language that doesn't have the Java/JVM escape hatch in it, so that I don't automatically reach for that pill just because it's available.  Hopefully that experience will encourage me to use Scala's functional side first, before reaching for the Java escape hatch.&lt;br /&gt;&lt;br /&gt;Concerning this book:  Bruce Tate is a very articulate, clear and engaging writer.  I see a couple of books a year that speak very directly to me.  Maybe I think these books are superior simply because they happen to have been written in a style that is especially suited to the way I think and learn.  With that acknowledgment of likely bias, I have to say &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt; is definitely one of those "once or twice a year" books for me.  I really recommend you pick up a copy if you have a desire for a shallow-dive into a variety of languages.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-5071408262527556302?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/5071408262527556302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/04/day-7-haskell.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5071408262527556302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5071408262527556302'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/04/day-7-haskell.html' title='Day 7 -- Haskell'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-5956629434260223272</id><published>2011-04-02T20:35:00.000-07:00</published><updated>2011-04-02T23:29:01.800-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Clojure'/><title type='text'>Day 6 -- Clojure</title><content type='html'>Today I'm reviewing the discussion of Clojure from Bruce Tate's &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;.  Clojure is Lisp on the Java virtual machine.  Lisp is another language that, despite being around a long time, I have yet to investigate, so this is another new experience.  Bruce starts with a brief review of Lisp itself, then a quick discussion of the link between Clojure and the JVM.  A discussion of Lisp functions and datatypes is followed by a view of Clojure lists, sets, maps and vectors (in Clojure, lists are typically used for data, while vectors are used for data).&lt;br /&gt;&lt;br /&gt;Still on Day 1 of Clojure, we discuss functions, including how to pass parameters, deconstruction using bindings, and then anonymous functions.  The day ends with an interview with Rich Hickey, the creator of Clojure.  One interesting revelation from this interview is that a concerted effort was made to reduce the use of parentheses, to make the language more accessible to the rest of us!&lt;br /&gt;&lt;br /&gt;Day 2 discusses recursion, including interesting syntax Clojure uses to support tail recursion (required because of the fact that Clojure runs on the JVM).  Next, Bruce discusses Clojure sequences, which can be used to wrap all the Clojure collection classes (plus a few more), and functions available to operate on sequences.  He discusses lazy evaluation, used to create infinite sequences.  A little discussion on Java interoperability is followed by an overview of macros, used to extend the Clojure language.&lt;br /&gt;&lt;br /&gt;Bruce's Day 3 discusses concurrency.  Unlike any of the other languages discussed so far in the book, Clojure supports concurrency with an approach that is called software transactional memory, a strategy that uses multiple versions of data to avoid issues surrounding simultaneous mutation.  To use this strategy, Clojure requires that all references be changed within a transaction.  Following are discussions of working with atoms, agents, and futures.  Bruce ends Day 3 with a list of some features of Clojure which were not covered in the book, then ends with the expected discussion of Clojure's strengths and weaknesses.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-5956629434260223272?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/5956629434260223272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/04/day-6-clojure.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5956629434260223272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5956629434260223272'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/04/day-6-clojure.html' title='Day 6 -- Clojure'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-6621224448630611317</id><published>2011-04-01T20:04:00.000-07:00</published><updated>2011-04-01T21:35:43.407-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Day 5 -- Erlang</title><content type='html'>If you are just dropping in on me, I'm reviewing Bruce Tate's &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;, with the slightly lazy (or aggressive, depending on your view) twist of reviewing one language per day.  As you can imagine, shrinking an already-tight one-week study schedule to one day means glossing over some things and skipping the extra exercises.  The idea, though, is to still get a good feel for the topography of the language, and as I've already pointed out, this is a great little book and will be my first contact for the languages I choose to get to know a little better.&lt;br /&gt;&lt;br /&gt;The 5th language of this book is Erlang ("Ericsson Language"), first developed by Joe Armstrong in 1986.  A functional, dynamically-typed language geared toward telecommunications and its high availability requirements, Erlang relies on lightweight processes (rather than threads) as its base model.  It is based on and quite similar to Prolog, something brought out by Bruce's interview with Joe Armstrong.  Have I said I really like the interview portions of this book?  After enough years in this industry, I had started to say "one more language; let me take a look at it and just give me the API docs", but after reviewing these languages I see I've overlooked the huge amount of variety in the development-language world.&lt;br /&gt;&lt;br /&gt;Erlang is a compiled language, but it provides an interpreter which Bruce uses for the earliest, shortest examples.  In his Day 1, Bruce discusses atoms, variables, lists and tuples, and gives a short discussion of pattern matching (including bit matching).  Day 2 starts by discussing control structures, mostly &lt;tt&gt;case&lt;/tt&gt; statements but also including the &lt;tt&gt;if&lt;/tt&gt; statement.&lt;br /&gt;&lt;br /&gt;Bruce then moves on to higher-order functions, starting with anonymous functions, and discusses using functions to manage lists.  Highlights include the &lt;tt&gt;foldl&lt;/tt&gt; and &lt;tt&gt;foldr&lt;/tt&gt; functions, as well as a brief review of Erlang's list comprehension.&lt;br /&gt;&lt;br /&gt;On Day 3 (using Bruce's timeline), he talks about concurrency.  I said earlier that Erlang looked more to lightweight process than  lightweight threads as a base model.  The concurrency primitives in Erlang are sending messages, spawning processes, and receiving messages.  He covers pattern matching in &lt;tt&gt;receive&lt;/tt&gt; loops, which have a syntax similar to &lt;tt&gt;case&lt;/tt&gt; statements, then discusses the use of &lt;tt&gt;spawn&lt;/tt&gt; to spawn a process.  Finally, the returned process ID of the spawned process is used as the destination for messages.  He walks us through an asynchronous example, followed by a simple asynchronous messaging example.  He then discusses linking processes and how to handle death (exit) of a process by its linked process (a technique used to create monitoring and keep-alive services).&lt;br /&gt;&lt;br /&gt;The end of the Erlang section covers strengths and weaknesses of the language.  One weakness, if you can call it that (at least from an adoption point of view) is not being on the Java Virtual Machine.  I thought of this frequently while going through the Erlang section of this book.  Reading about Erlang's support for concurrency is refreshing and quite inspiring for me.  However, I know that I will most likely eventually use Scala.  Why?  That JVM is just going to make it a lot easier to sell to management.  That might be a shame, but it's kind of a fact of life.  I remember really liking Smalltalk, but realizing that summer was coming to an end and going with C++ anyway.  But it doesn't mean I don't still think fondly of my first Smalltalk application.  :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-6621224448630611317?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/6621224448630611317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/04/day-5-erlang.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6621224448630611317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6621224448630611317'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/04/day-5-erlang.html' title='Day 5 -- Erlang'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-4346003925746460697</id><published>2011-03-31T21:20:00.000-07:00</published><updated>2011-04-02T20:35:03.831-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><title type='text'>Day 4 -- Scala</title><content type='html'>Scala is the 4th language in Bruce Tate's &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;.  It is the only language in this book with which I am already familiar, although I've only been learning it for a month or so.  Scala is interesting in that it runs on the Java virtual machine, a feature which may give it a leg up in the language race.  I remember when I and my co-workers "discovered" object orientation.  We studied Coad and Yourdon and prototyped in Smalltalk and C++.  C++ was a great bridge to OO for C programmers, and it wasn't hard to tell from the beginning which language was going to win &lt;em&gt;that&lt;/em&gt; race.&lt;br /&gt;&lt;br /&gt;Of course, Clojure runs on the JVM also, so maybe this time the race will be a little more interesting.  From my own point of view, the JVM connection definitely influenced my decision to start learning Scala rather than some other functional language.&lt;br /&gt;&lt;br /&gt;Bruce covers a lot of material on Day 1, really too much to list here.  As he points out, to explore Scala is to explore both a functional language and an object-oriented language.  So Day 1 is a very dense race through many features of Scala.&lt;br /&gt;&lt;br /&gt;Day 2 begins with a discussion of function definition, and a description of &lt;tt&gt;val&lt;/tt&gt;s and &lt;tt&gt;var&lt;/tt&gt;s, the general concept of mutability, and how important it is to pay attention to mutability if you are going to be a successful functional developer.  As Bruce puts it, "mutable state limits concurrency."  Think of all those &lt;tt&gt;IllegalStateException&lt;/tt&gt;s and &lt;tt&gt;NullPointerException&lt;/tt&gt;s in your multi-threaded Java code.  If your application had no mutable state, it wouldn't matter how many times you called a method, or what you called before you called that method, or how many threads are calling the method.  After years of being sent on-site to diagnose such problems, this is the reason I'm interested in functional programming.&lt;br /&gt;&lt;br /&gt;Next, Bruce introduces Scala's collections, emphasizing Lists, Sets, and Maps.  He then discusses higher-order functions (that is, functions which take functions as arguments and return functions), code blocks and anonymous functions.  Following is a detailed enumeration of list operations.  This is all preparation for Day 3, of course, which primarily covers XML processing and concurrent programming.&lt;br /&gt;&lt;br /&gt;Scala's support for XML involves treating XML as a first-level language construct and providing query support similar to XPath.  A couple of brief query examples are followed by a discussion of Scala pattern matching, including guard conditions and regular-expression support, and then a discussion of using pattern matching in XML processing.  Day 3 ends with a quick discussion of Scala concurrency and a couple of examples.&lt;br /&gt;&lt;br /&gt;As with all the languages, Bruce ends with a discussion of Scala's strengths and weaknesses.  His discussion of the advantages and disadvantages of Scala's Java connection is worth reading even if you decide not to dive deep into Scala, or even dive deep into Bruce's "week with Scala."  As with VHS and Betamax, it probably doesn't make sense to make any predictions at this point concerning what development paradigm and/or representative language will "win" in the developer marketplace.  That's another reason why I like this book, or course -- it's a very thoughtful and non-trivial investigation of a variety of languages. And I didn't even have to choose which languages to investigate!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-4346003925746460697?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/4346003925746460697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-4-scala.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4346003925746460697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4346003925746460697'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-4-scala.html' title='Day 4 -- Scala'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-7175003457282654409</id><published>2011-03-30T07:30:00.000-07:00</published><updated>2011-04-02T20:35:09.072-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Day 3 -- Prolog</title><content type='html'>Prolog is the 3rd language covered in Bruce Tate's &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;, and is a declarative, rather than imperative, language.  Prolog is not new, of course (1972), but I have to admit this is the first time I've taken a look at it.&lt;br /&gt;&lt;br /&gt;Like Bruce, I used GNU Prolog (1.3.1).  As he describes the language, the building blocks are facts and rules (which together form a knowledge base), and queries.  He describes some simple queries, then moves on to substituting variables in queries.  He finishes the first day of the Prolog segment with a discussion of Prolog unification, then an interview with Brian Tarbox, a dolphin researcher who used Prolog both to simulate dolphin behavior and to schedule the personnel needed for each dolphin experiment.  According to Tarbox, Prolog was very well suited for solving both types of problems.&lt;br /&gt;&lt;br /&gt;The first day looked at declaring facts and rules and making simple queries against them.  Day 2 adds some more tools, including recursion, math functions, and lists and tuples (and operations on them).  Day 2 is the day where my experiment in covering one language per day seems the least feasible; I'm not familiar with declarative (programming) languages and although I get the idea, a lot of it went over my head.  Bruce is extremely profuse with examples, deconstructed ones at that.  If I wanted to learn Prolog, I would start with this book first and spend a few more days on it.&lt;br /&gt;&lt;br /&gt;For Day 3, Bruce goes through two detailed examples -- a solution for a small Sudoku puzzle, and the Eight Queens problem.  He then finishes with a discussion of Prolog's strengths and weaknesses, including listing problem spaces for which Prolog is particularly well-suited.   Those areas?  Scheduling constrained resources, natural-language processing, games, semantic web representation and artificial intelligence.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-7175003457282654409?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/7175003457282654409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-3-prolog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7175003457282654409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7175003457282654409'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-3-prolog.html' title='Day 3 -- Prolog'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-5802750547252111109</id><published>2011-03-29T10:09:00.000-07:00</published><updated>2011-04-01T21:37:26.490-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Io'/><title type='text'>Day 2 -- Io</title><content type='html'>Io is the 2nd language in Bruce Tate's &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt;.  Io is a prototyping language, where most of the mass exists in the libraries.  The syntax itself is refreshingly simple, and he is not exaggerating to say you can grasp it in about 15 minutes.&lt;br /&gt;&lt;br /&gt;As with the other languages he discusses, there's no download/install information save for the Io site URL.  I did need a little help getting past this stage; if you click the only "download" link at &lt;a href="http://iolanguage.com/"&gt;http://iolanguage.com&lt;/a&gt;, you'll get a zipped distribution of the Io source.  If you're smart enough to append "/downloads" to the URL (there's no link to this from the home page!), you'll find (in my case, Windows) binaries to spare you the build process (I wasn't smart enough to figure this out; I found another website which pointed me to &lt;a href="http://iolanguage.com/downloads"&gt;http://iolanguage.com/downloads&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Day 1 of Bruce's discussion of Io gets you familiar with the Io interpreter and the process of cloning.  You learn about the "slots" of an object, which are basically the attributes and behavior.  He then covers Io's lists and collections (specifically, &lt;tt&gt;List&lt;/tt&gt; and &lt;tt&gt;Map&lt;/tt&gt;). I was a little surprised to get different results than Bruce did (e.g. sending the &lt;tt&gt;asObject&lt;/tt&gt; message to a Map clone returns &lt;tt&gt;Exception: Map does not respond to 'asObject'&lt;/tt&gt;, whereas in Bruce's output it returns an &lt;tt&gt;Object&lt;/tt&gt; , though the version of Io I'm using appears to be old enough that it certainly should be the same as Bruce's).  He then discusses &lt;tt&gt;true&lt;/tt&gt;, &lt;tt&gt;false&lt;/tt&gt;, &lt;tt&gt;nil&lt;/tt&gt; and singletons, the last of which you create by overriding an Object's &lt;tt&gt;clone&lt;/tt&gt; method.  The ability to override even core methods is a key to Io's potential for creating domain-specific languages.&lt;br /&gt;&lt;br /&gt;He finishes the "day" with an interview with Steve Dekorte, the inventor of Io, asking him about his motivations to create the language.  I really like these interviews, as they give a (usually unavailable) view into the mind behind and motivations for the existence of a language.  Language developers tend to be quite articulate when describing their motivations for creating a language; how often does anyone ask them?&lt;br /&gt;&lt;br /&gt;Day 2 covers conditionals and loops, operators and messages, as well as message reflection and object reflection. Day 3 starts with a discussion of a non-trivial example of a domain-specific language, then discusses changing the language's behavior, by modifying Io's &lt;tt&gt;forward&lt;/tt&gt; method (analogous to the discuss of Ruby's &lt;tt&gt;method_missing&lt;/tt&gt; yesterday).&lt;br /&gt;&lt;br /&gt;Bruce spends the rest of the day discussing Io's support for concurrency (as a longtime Java developer, alternative-language concurrency support is the number-one reason I am reading this book).  He describes coroutines and contrasts them with pre-emptive multi-tasking in Java and C, then describes Io actors and contrasts &lt;em&gt;them&lt;/em&gt; with threads, and shows how easy it is to make an object an actor.  Concluding the concurrency segment is a discussion of Io futures.&lt;br /&gt;&lt;br /&gt;As with Ruby on Day 1, Bruce ends the discussion of Io with a list of strengths and weaknesses, and as with Ruby, he puts a lot of thought into this discussion.  I'll repeat that I am only scratching the surface by covering this "week" in one day (while recognizing that even one week would be scratching the surface), but I really appreciate the compactness of these segments and the density of information contained in them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-5802750547252111109?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/5802750547252111109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-2-io.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5802750547252111109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5802750547252111109'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-2-io.html' title='Day 2 -- Io'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-3686332705908100193</id><published>2011-03-28T19:49:00.000-07:00</published><updated>2011-04-02T20:35:17.116-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Day 1 -- Ruby</title><content type='html'>When I decided to blow through &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt; in only 7 days, I had yet to read even the introduction to the book.  I can tell now that Bruce might prefer that I not do it this way, and I have to admit it would truly be a focused experience to do all the suggested exercises on each language, spending only one day on each.  But...  I'm on a schedule, and I'm not pretending to come out of this with the level of understanding that he aims to cultivate.  At least not on this first run through the book.&lt;br /&gt;&lt;br /&gt;First, some notes about his introduction.  Bruce describes up-front how he'll contrast the different languages:  the typing model, programming model, language constructs, data structures, and any other features that distinguish a language.  I really like this set of abstractions, and the simple fact that he lists and describes them before launching into the first language.  He also says he's not going to burn space describing how to download and set up each language's environment, thus allowing him to focus on the language itself.  It's nice to see a book with this much thought put into it.&lt;br /&gt;&lt;br /&gt;The first language, Ruby, appears to be the language (of these 7) in which he is strongest.  I left scientific development for business development quite a few years ago, at which point I was rather proficient with Perl (version 4, to tell you how long ago that was).  Since then I've been immersed mostly in Java and C# on Windows .  I've always thought that it would be cool to pick up Ruby, but have never got around to it.  Finally, I'm spending one day on it. :)&lt;br /&gt;&lt;br /&gt;Bruce starts by sharing his interview with Yukihiro Matsumoto, the creator of Ruby (nice touch), then talks about Ruby's pure-object-oriented typing model.  After using Java for 14 years, it's refreshing to be able to call a method on what appears to be the numeral 4!  ;-&amp;gt;  Ruby is (mostly) strongly-typed, but also dynamically typed.  He then covers function definition, collections, code blocks, classes, and mixins.  And this is just by the end of the 2nd day of the week he allots to studying Ruby.  This is just my opinion, of course, but it's not often I've seen someone so proficient at introducing relevant features of a language in an order that is so intuitive -- and useful -- to an experienced developer looking to evaluate a new language.&lt;br /&gt;&lt;br /&gt;Day 3 of the Ruby chapter talks about Ruby support for metaprogramming, including open classes and modules.  Here is where you can start to see Bruce's depth of knowledge about Ruby.  He concludes the Ruby discussion with sections on the strengths and weaknesses of Ruby vs other languages.&lt;br /&gt;&lt;br /&gt;In the interest of finishing in one day, I sped over most of the hands-on training.  Following along and doing the suggested exercises would indeed fill a whole week, comfortably.  I like this chapter so much that when the day comes for me to finally really pick up Ruby, I'm sure I'll actually start with this chapter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-3686332705908100193?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/3686332705908100193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-1-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3686332705908100193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3686332705908100193'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/day-1-ruby.html' title='Day 1 -- Ruby'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-6063074177220840266</id><published>2011-03-28T10:06:00.000-07:00</published><updated>2011-03-30T07:33:52.683-07:00</updated><title type='text'>7 Languages in 7... Days???</title><content type='html'>I recently started learning Scala (you know when the New York Times refers to Java as an "older" language, it's time to update!).  As I've started trying to shift my thinking from object orientation to functional programming, I remembered the book &lt;em&gt;Seven Languages in Seven Weeks&lt;/em&gt; by Bruce Tate.  I'm about halfway through Odersky et al.'s (excellent!) Scala book and thought I'd benefit from a look at Bruce's.&lt;br /&gt;&lt;br /&gt;So here I go.  Nothing unusual except that my goal is to go through a language a day and finish the book in a week.  Why a week?  I don't really have seven weeks, and besides, I'm going in to my office for one of my 3-4 times-per-year office visits, and I want to finish before I go in.  Unless I totally flame out, I'll publish an entry each day, for each language.&lt;br /&gt;&lt;br /&gt;One of my motivations is the effort involved to think in terms of functional programming.  I never completed reading the first Scala book I picked up (and have already donated it to my local library book drive).  Why?  The author obviously no longer remembers what it was like to make the switch from Java to Scala.  This makes it difficult for him to relate to someone who hasn't yet made the switch, and the material is presented in an order which is wildly inappropriate for someone who hasn't already learned Scala.  Before &amp;gt;I&amp;lt; learn everything I need to learn, I would like to capture that learning process myself, so I can remember what it was like and possibly be more helpful to someone else (in case you're wondering, Odersky, Spoon and Venners do a great job connecting with object-oriented developers in their Scala book).&lt;br /&gt;&lt;br /&gt;That's it for now.  I see the first language in Bruce's book is Ruby, a language I once downloaded and never got around to using.  Hopefully I'll have a meaningful post on his Ruby section by my late-night deadline.  If not (either it's not there or it's not meaningful!), I'll try to catch up the next day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-6063074177220840266?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/6063074177220840266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/7-languages-in-7-days.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6063074177220840266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6063074177220840266'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2011/03/7-languages-in-7-days.html' title='7 Languages in 7... Days???'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-2669491848164071980</id><published>2010-12-21T09:31:00.000-08:00</published><updated>2010-12-21T13:50:54.436-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java SE web service Endpoint Silverlight Flex crossdomain.xml'/><title type='text'>Java SE Endpoints and Providers</title><content type='html'>Recently I had a repeat of a problem I was unable to solve the first time I encountered it.  When this first occurred, I was happily serving up content from a Java SE-based web service (if you're not familiar with this, it involves specially annotating a class and exposing it by publishing it to a &lt;span style="font-family:courier new;"&gt;javax.xml.ws.Endpoint&lt;/span&gt;).  I ran into a problem when  I tried accessing the web service (I believe from a Flex app), because the Flex runtime really "wanted" to find a &lt;span style="font-family:courier new;"&gt;crossdomain.xml&lt;/span&gt; file at the HTTP server root.  Since it was unable to do so, it obligingly refused to expose my web service to possible attack and would not access the web service.&lt;br /&gt;&lt;br /&gt;Leaving aside for the moment the philosophy of the client's enforcing security upon itself (this doesn't protect my web service from other unscrupulous clients), I was left with a problem.  This approach is a little naive because the client is assuming the web service has something like a root document directory, where you can just drop the &lt;span style="font-family:courier new;"&gt;crossdomain.xml&lt;/span&gt; file and get on with your life.  As you know, when you expose a Java bean as an Endpoint, there is no file system; just an internal HTTP server servicing the web-service requests.  So where do you put the file?&lt;br /&gt;&lt;br /&gt;The answer is:  wherever you want, as long as you figure out how to serve it up!  I ran into this same problem recently as I was building a Silverlight-based application.  Silverlight enforces the same constraints on itself, and indeed will actually look for a &lt;span style="font-family:courier new;"&gt;crossdomain.xml&lt;/span&gt; file (after searching first for a &lt;span style="font-family:courier new;"&gt;clientaccesspolicy.xml&lt;/span&gt; file).  This time I worked a little harder to find an answer, and got a lucky break from an online posting.&lt;br /&gt;&lt;br /&gt;Using &lt;span style="font-family:courier new;"&gt;tcpmon&lt;/span&gt;, I noticed an interesting point.  While my web service was hosted at a URL like &lt;span style="color: rgb(255, 0, 0);font-family:courier new;" &gt;http://www.example.com:8080/WebManager&lt;/span&gt;, the Silverlight runtime actually looks for the policy file at &lt;span style="color: rgb(255, 0, 0);font-family:courier new;" &gt;http://www.example.com:8080/crossdomain.xml&lt;/span&gt;.  In other words, not at the context at which my web service was deployed, but at the root of the HTTP server itself.  This distinction proves to greatly facilitate the solution.&lt;br /&gt;&lt;br /&gt;The solution is to publish two endpoints -- one for the web service, and one for a document server.  The &lt;span style="font-family:courier new;"&gt;javax.xml.ws.Endpoint&lt;/span&gt; class allows you to publish multiple beans&lt;span style="font-style: italic;"&gt; at the same host and port&lt;/span&gt;  (a crucial point, which makes this solution work).  You just need to ensure the context, or full URL, is different for each.  So, while I may publish my web service with the following statement:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;Endpoint.publish("http://www.example.com:8080/WebManager", new WebManager());&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I am able to publish a different endpoint to satisfy Flex/Silverlight with:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;Endpoint.publish("http://www.example.com:8080/", new DocumentProvider());&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When my Silverlight control attempts to access the web service, it will first look for a &lt;span style="font-family:courier new;"&gt;crossdomain.xml&lt;/span&gt; file at the web server root; if it determines it is allowed to access the service, it will then do so.&lt;br /&gt;&lt;br /&gt;What is a &lt;span style="font-family:courier new;"&gt;DocumentProvider&lt;/span&gt;?  It is a class which I've published to an &lt;span style="font-family:courier new;"&gt;Endpoint &lt;/span&gt;much like my actual business logic, but it intercepts the HTTP requests and only processes requests for documents.  In other words, instead of letting the Java SE implementation handle all the requests, delegating them to &lt;span style="font-family:courier new;"&gt;@WebMethod&lt;/span&gt;-annotated methods, it handles all the work itself.  The API for this can be found at &lt;span style="font-family:courier new;"&gt;javax.xml.ws.Provider&lt;/span&gt;, which defines a single method:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;public T invoke(T request);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where &lt;span style="font-family:courier new;"&gt;T&lt;/span&gt; must be either a &lt;span style="font-family:courier new;"&gt;Source&lt;/span&gt;, a &lt;span style="font-family:courier new;"&gt;SOAPSource&lt;/span&gt;, or a &lt;span style="font-family:courier new;"&gt;DataSource&lt;/span&gt;.  This looks a little generic, and it is.  But this is where all the work occurs.  In my case, I'm going to return a &lt;span style="font-family:courier new;"&gt;DataSource &lt;/span&gt;whose input stream is the requested document.&lt;br /&gt;&lt;br /&gt;Following is a complete class which implements only the document server (exposing methods as web service operations is fairly well documented):&lt;br /&gt;&lt;span style="color: rgb(0, 100, 0);font-family:courier new;" &gt;&lt;pre&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import java.io.InputStreamReader;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.OutputStream;&lt;br /&gt;import javax.activation.DataSource;&lt;br /&gt;import javax.annotation.Resource;&lt;br /&gt;import javax.xml.ws.BindingType;&lt;br /&gt;import javax.xml.ws.Endpoint;&lt;br /&gt;import javax.xml.ws.Provider;&lt;br /&gt;import javax.xml.ws.Service;&lt;br /&gt;import javax.xml.ws.ServiceMode;&lt;br /&gt;import javax.xml.ws.WebServiceContext;&lt;br /&gt;import javax.xml.ws.WebServiceException;&lt;br /&gt;import javax.xml.ws.WebServiceProvider;&lt;br /&gt;import javax.xml.ws.handler.MessageContext;&lt;br /&gt;import javax.xml.ws.http.HTTPBinding;&lt;br /&gt;&lt;br /&gt;@WebServiceProvider&lt;br /&gt;@BindingType(HTTPBinding.HTTP_BINDING)&lt;br /&gt;@ServiceMode(value=Service.Mode.MESSAGE)&lt;br /&gt;public class DocumentServer implements Provider&lt;datasource&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;protected static final String CROSSDOMAIN_XML = "&amp;lt;?xml version=\"1.0\" ?&amp;gt;&amp;lt;cross-domain-policy&amp;gt;&amp;lt;allow-access-from domain=\"*\" /&amp;gt;&amp;lt;/cross-domain-policy&amp;gt;";&lt;br /&gt;&lt;br /&gt;@Resource&lt;br /&gt;protected WebServiceContext wsContext;&lt;br /&gt;&lt;br /&gt;public static void main(String [] args)&lt;br /&gt;{&lt;br /&gt;DocumentServer docServer = new DocumentServer();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public DocumentServer()&lt;br /&gt;{&lt;br /&gt;Endpoint.publish("http://localhost:10486/", this);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public DataSource invoke(DataSource ds) throws WebServiceException&lt;br /&gt;{&lt;br /&gt;MessageContext msgCtx = wsContext.getMessageContext();&lt;br /&gt;&lt;br /&gt;String method = (String)msgCtx .get(MessageContext.HTTP_REQUEST_METHOD);&lt;br /&gt;String pathInfo = (String)msgCtx.get(MessageContext.PATH_INFO);&lt;br /&gt;if (method.equals("GET") &amp;amp;&amp;amp; pathInfo.equals("crossdomain.xml"))&lt;br /&gt;{&lt;br /&gt;  return new DataSource()&lt;br /&gt;  {&lt;br /&gt;    public InputStream getInputStream()&lt;br /&gt;    {&lt;br /&gt;      return new ByteArrayInputStream(CROSSDOMAIN_XML.getBytes());&lt;br /&gt;    }&lt;br /&gt;    public OutputStream getOutputStream()&lt;br /&gt;    {&lt;br /&gt;      return null;&lt;br /&gt;    }&lt;br /&gt;    public String getContentType()&lt;br /&gt;    {&lt;br /&gt;      return "text/xml";&lt;br /&gt;    }&lt;br /&gt;    public String getName()&lt;br /&gt;    {&lt;br /&gt;      return "";&lt;br /&gt;    }&lt;br /&gt;  };&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;throw new WebServiceException();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/datasource&gt;&lt;/pre&gt;&lt;/span&gt;Some things to note about the above code:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There is a lot of flexibility in the &lt;span style="font-family:courier new;"&gt;Provider &lt;/span&gt;interface.&lt;/li&gt;&lt;li&gt;How your implementation of &lt;span style="font-family:courier new;"&gt;Provider &lt;/span&gt;is interpreted by the Java compiler depends in great part on the annotations you have added to your implementation.  The &lt;span style="font-family:courier new;"&gt;WebServiceProvider&lt;/span&gt;, &lt;span style="font-family:courier new;"&gt;BindingType&lt;/span&gt;, and &lt;span style="font-family:courier new;"&gt;ServiceMode &lt;/span&gt;annotations are tightly coupled with the specifics of your implementation.  Try compiling the example without them, to see what I mean.&lt;/li&gt;&lt;li&gt;The &lt;span style="font-family:courier new;"&gt;WebContext &lt;/span&gt;is vital but can be obtained by simple injection.&lt;/li&gt;&lt;li&gt;I only process "GET" requests for "&lt;span style="font-family:courier new;"&gt;crosssdomain.xml&lt;/span&gt;", and return a very liberal policy; of course, this is just an example.  You could just as easily create a web-serviceable management interface on your crossdomain policy and create it dynamically, as well as serve it -- and other documents -- from a file system, rather than the way I've done it here.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Finally, I'm no expert in this area but am happy to pass the information along, as it is somewhat difficult to find examples of &lt;span style="font-family:courier new;"&gt;Provider &lt;/span&gt;implementations.  In that spirit, I acknowledge the folks who posted this example:  &lt;span style="font-family:courier new;"&gt;&lt;a href="http://acm2010.cct.lsu.edu/localdoc/java/6-jdk/sample/webservices/EbayClient/"&gt;http://acm2010.cct.lsu.edu/localdoc/java/6-jdk/sample/webservices/EbayClient/&lt;/a&gt;&lt;/span&gt;.  It was greatly appreciated!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-2669491848164071980?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/2669491848164071980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2010/12/java-se-endpoints-and-providers.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/2669491848164071980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/2669491848164071980'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2010/12/java-se-endpoints-and-providers.html' title='Java SE Endpoints and Providers'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-3754346882925330543</id><published>2010-02-17T13:04:00.000-08:00</published><updated>2010-02-17T13:14:39.558-08:00</updated><title type='text'>Gorilla Logic releases the MonkeyWrench Java profiler</title><content type='html'>Hello, everyone:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've posted a number of entries in the last year about profiling Java applications.  Some of this effort went in to a standalone Java profiler with a Swing interface, called the MonkeyWrench.  My company (Gorilla Logic) maintains and has released MonkeyWrench, and you can find it at &lt;a href="http://www.gorillalogic.com/monkeywrench"&gt;http://www.gorillalogic.com/monkeywrench&lt;/a&gt;.  Source code is also available, so if there's some interesting data you want from the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument&lt;/span&gt; package (or the JMX beans that I query) that you don't see, feel free to experiment to suit your needs.  If you're curious but not sure if you need a profiler right now, take a look at the &lt;a href="http://www.gorillalogic.com/userfiles/GettingStartedWithMonkeyWrench.pdf"&gt;Getting Started Guide&lt;/a&gt;, which contains screenshots.  Happy Profiling!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-3754346882925330543?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/3754346882925330543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2010/02/gorilla-logic-releases-monkeywrench.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3754346882925330543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3754346882925330543'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2010/02/gorilla-logic-releases-monkeywrench.html' title='Gorilla Logic releases the MonkeyWrench Java profiler'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-230533967814422882</id><published>2010-01-15T08:44:00.000-08:00</published><updated>2010-01-15T16:33:21.447-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='&quot;'/><title type='text'>Java profiling with DTrace</title><content type='html'>&lt;span style="font-family:verdana;"&gt;DTrace, a dynamic tracing framework on Solaris (see &lt;a href="http://docs.sun.com/app/docs/doc/819-2240/dtrace-1m?a=view"&gt;dtrace(1m)&lt;/a&gt;) is a valuable and extremely easy-to-use tool if you find yourself analyzing Java performance issues on Solaris.  While there is a lot of information on DTrace available (see the &lt;a href="http://wikis.sun.com/display/DTrace/DTrace"&gt;DTrace Wiki&lt;/a&gt;, which includes an extensive user guide), less information is available on using DTrace specifically with Java applications.  My motivation with this post is to focus on profiling Java applications with DTrace.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Quick Tour&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you're not at all familiar with DTrace, look at the &lt;a href="http://wikis.sun.com/display/DTrace/Introduction#Introduction-GettingStarted"&gt;Getting Started&lt;/a&gt; section of the user guide.  In short, DTrace allows you to specify a set of actions you would like performed at a location of interest (in the kernel or an application).  A location of interest is referred to as a &lt;span style="font-style: italic;"&gt;probe&lt;/span&gt;.  In addition to a numerical ID, each probe is identified by the following four pieces of information:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;The probe Provider name&lt;/li&gt;&lt;li&gt;The probe Module&lt;/li&gt;&lt;li&gt;The name of the Function where the probe is located&lt;/li&gt;&lt;li&gt;A Name for the probe, designed for human readability&lt;/li&gt;&lt;/ul&gt;(By the way, if you don't have a Solaris environment but would still like to follow along, you can install &lt;a href="http://download.virtualbox.org/virtualbox/vboxdownload.html"&gt;VirtualBox&lt;/a&gt;, then retrieve the ISO image for &lt;a href="http://www.opensolaris.com/get/index.jsp"&gt;OpenSolaris&lt;/a&gt;, then follow the VirtualBox guide to get up and running on OpenSolaris).&lt;br /&gt;&lt;br /&gt;What probes are available?  Well, a lot.  On my OpenSolaris (2009.06) environment, a count (using  &lt;span style="font-family:courier new;"&gt;pfexec dtrace -l | wc -l&lt;/span&gt;), yields 60068 probes!  (Note: this includes some Java-6-specific probes; more on that later).  Most of these are fairly low-level probes from the point of view of a Java profiler, but let's take one and see what we can do with it.&lt;br /&gt;&lt;br /&gt;Using DTrace, we can perform actions when the &lt;span style="font-family:courier new;"&gt;read&lt;/span&gt; system call is entered, using the following:&lt;br /&gt;&lt;pre&gt;     &lt;span style="font-family:courier new;"&gt;pfexec dtrace -n syscall::read:entry&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;If you enter this, you'll begin to see output such as the following:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;  0  57922                       read:entry &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  0  57922                       read:entry &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  0  57922                       read:entry &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  0  57922                       read:entry &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  0  57922                       read:entry&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Note this doesn't tell you a lot; you don't know the PIDs of the processes making the calls, and so on.  DTrace has a number of built-in functions and variables that you can use to provide meaningful output at these locations.  I won't go into this in any detail because there is a large body of information on these topics at the links I mentioned above.  This is just the very quick tour to get to, and focus on, Java-specific probes.&lt;br /&gt;&lt;br /&gt;At this point, before going any farther, you would begin placing your declarations and logic in a file.  DTrace understands the D programming language, a language that will be familiar to most developers (especially C developers).  The above &lt;span style="font-family:courier new;"&gt;syscall::read:entry&lt;/span&gt; example, placed in a file and enhanced to 1) apply only to a specified PID, and 2) to print out the name of the process, follows:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;syscall::read:entry&lt;br /&gt;/pid == $1/&lt;br /&gt;{&lt;br /&gt;printf("'%s' (PID: %d): entered syscall:read", execname, pid);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;Place the following text in a file called &lt;span style="font-family:courier new;"&gt;blogExample.d&lt;/span&gt;, then find a process to monitor (I picked Firefox) and enter the following, substituting the PID of the process of your choice:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;     pfexec dtrace -s blogExample.d 697&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;and you should see output similar to the following:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;0  57922                       read:entry 'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;0  57922                       read:entry 'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;0  57922                       read:entry 'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;0  57922                       read:entry 'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;Note the predicate (&lt;span style="font-family:courier new;"&gt;/pid == $1/&lt;/span&gt;) in the example which restricts actions to be performed only when &lt;span style="font-family:courier new;"&gt;pid&lt;/span&gt; (a built-in DTrace variable) is equal to the first argument supplied on the command line (&lt;span style="font-family:courier new;"&gt;$1&lt;/span&gt;).  To suppress all output except for that specified in your &lt;span style="font-family:courier new;"&gt;printf()&lt;/span&gt; call, add the -q ("quiet") switch (you'll need to add a newline to the end of your &lt;span style="font-family: courier new;"&gt;printf()&lt;/span&gt; specification, also, as "quiet" mode does not provide one):&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;     pfexec dtrace -q -s blogExample.d 697&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;and you should see output similar to the following:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;'firefox-bin' (PID: 697): entered syscall:read&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;That wraps up the quick tour of DTrace.  Now, on to our main topic!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;DTrace Support in Java&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Java SE 6 now supports DTrace, in the form of a couple of providers (specific to the HotSpot JVM):&lt;br /&gt;&lt;ul&gt;&lt;li style="font-family: courier new;"&gt;hotspot&lt;/li&gt;&lt;li&gt;hotspot_jni&lt;/li&gt;&lt;/ul&gt;For more information, see &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/vm/dtrace.html"&gt;DTrace Probes in HotSpot VM&lt;/a&gt;.  We'll be focusing on the &lt;span style="font-family:courier new;"&gt;hotspot&lt;/span&gt; provider in this post.  Normally, you would expect to find a provider with the &lt;span style="font-family:courier new;"&gt;dtrace -l&lt;/span&gt; command, looking for "&lt;span style="font-family:courier new;"&gt;hotspot&lt;/span&gt;".  This approach gets you most of the way there; actually, providers are on a per-JVM basis, and they are identified by appending the PID to the name "&lt;span style="font-family:courier new;"&gt;hotspot&lt;/span&gt;."   So, for example, if you have a Java process running and its PID is 1234, then there will be a DTrace provider called "&lt;span style="font-family:courier new;"&gt;hotspot1234&lt;/span&gt;".  This naming convention is the reason that you will see references to "&lt;span style="font-family:courier new;"&gt;hotspot$1&lt;/span&gt;" in example D-language scripts -- the author is expecting a PID on the command line and is using it to create the provider name.  This convention also spares us from having to restrict our probe actions to a specific PID, as the restriction is built in to the choice of provider.&lt;br /&gt;&lt;br /&gt;Back to the Java-specific probes.  Enter the following command in a shell:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;pfexec dtrace -l | grep hotspot&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;and you should see a list of all the &lt;span style="font-family: arial;"&gt;hotspot&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;hotspot_jni&lt;/span&gt; probes.  On my system, I got 499 probes with one Java process running; note there will be a complete set for each JVM.  I have 26 "&lt;span style="font-family:courier new;"&gt;hotspot&lt;/span&gt;" probes, and 473 "&lt;span style="font-family:courier new;"&gt;hotspot_jni&lt;/span&gt;" probes.  I will only be looking at "&lt;span style="font-family:courier new;"&gt;hotspot&lt;/span&gt;" probes in this post.  You can also get a list of these probes, along with their arguments, in the &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/vm/dtrace.html#Reference"&gt;Reference&lt;/a&gt; section of &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/vm/dtrace.html"&gt;DTrace Probes in HotSpot VM&lt;/a&gt;.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Some Examples&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Thread Monitoring&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Note the following two probes related to thread activity:&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;pre&gt;  probe thread-start(char* thread_name, uintptr_t thread_name_length,&lt;br /&gt;uintptr_t java_thread_id, uintptr_t native_thread_id, bool is_daemon);&lt;br /&gt;probe thread-stop(char* thread_name, uintptr_t thread_name_length,&lt;br /&gt;uintptr_t java_thread_id, uintptr_t native_thread_id, bool is_daemon);&lt;br /&gt;&lt;/pre&gt;One interesting detail to note with string arguments in DTrace is that they come in pairs, where the first item is a pointer to the un-terminated string and the second item is the length of the string.  Because of this convention, in example code you'll frequently see the following construct, which builds a null-terminated string from the provided information:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;  self-&gt;str_ptr = (char*) copyin(arg0, arg1+1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  self-&gt;str_ptr[arg1] = '\0';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  self-&gt;stringVariable = (string) self-&gt;str_ptr;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note that the above fragment could be used to construct the name of the thread from the above &lt;span style="font-family:courier new;"&gt;thread-start&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;thread-stop&lt;/span&gt; probes.&lt;br /&gt;&lt;br /&gt;To see how easy it is to use DTrace to create a simple thread profiler on Java 6, open a file in a text editor and enter the following:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;pre&gt;     hotspot$1:::thread-start&lt;br /&gt;{&lt;br /&gt;self-&gt;ptr = (char*) copyin(arg0, arg1+1);&lt;br /&gt;self-&gt;ptr[arg1] = '\0';&lt;br /&gt;self-&gt;threadname = (string) self-&gt;ptr;&lt;br /&gt;&lt;br /&gt;printf("thread-start: '%s' (thread ID = %d; native thread ID = %d; is_daemon? %d)\n",&lt;br /&gt; self-&gt;threadname, arg2, arg3, arg4);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;hotspot$1:::thread-stop&lt;br /&gt;{&lt;br /&gt;self-&gt;ptr = (char*) copyin(arg0, arg1+1);&lt;br /&gt;self-&gt;ptr[arg1] = '\0';&lt;br /&gt;self-&gt;threadname = (string) self-&gt;ptr;&lt;br /&gt;&lt;br /&gt;printf("thread-stop: '%s' (thread ID = %d; native thread ID = %d; is_daemon? %d)\n",&lt;br /&gt; self-&gt;threadname, arg2, arg3, arg4);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Note as mentioned earlier the &lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;$1&lt;/span&gt;&lt;span style="font-size:100%;"&gt; macro variable, representing the JVM process ID you will be passing in on the command line.  In this script, we output everything we get from these two probes, which is the thread name, ID, native ID, and a boolean "&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;is_daemon"&lt;/span&gt;&lt;span style="font-size:100%;"&gt;.  Save this file as &lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;threadWatcher.d&lt;/span&gt;&lt;span style="font-size:100%;"&gt; and enter the following:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;pfexec dtrace -q -s threadWatcher.d &lt;span style="font-style: italic;"&gt;pid&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;substituting the process ID of a running JVM.  In my test Java application, I then opened a file chooser and got the following output from DTrace:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;thread-start: 'Basic L&amp;amp;F File Loading Thread' (thread ID = 42; native thread ID = 42; is_daemon? 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;thread-stop: 'Basic L&amp;amp;F File Loading Thread' (thread ID = 42; native thread ID = 42; is_daemon? 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;thread-start: 'Basic L&amp;amp;F File Loading Thread' (thread ID = 43; native thread ID = 43; is_daemon? 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;thread-start: 'Basic L&amp;amp;F File Loading Thread' (thread ID = 41; native thread ID = 41; is_daemon? 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;thread-stop: 'Basic L&amp;amp;F File Loading Thread' (thread ID = 41; native thread ID = 41; is_daemon? 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;thread-stop: 'Basic L&amp;amp;F File Loading Thread' (thread ID = 43; native thread ID = 43; is_daemon? 0)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-style: italic;"&gt;Garbage Collection&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note the following probes relevant to garbage collection:&lt;/span&gt;&lt;br /&gt;&lt;pre  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;probe gc-begin(bool is_full);&lt;br /&gt;probe gc-end();&lt;br /&gt;probe mem-pool-gc-begin(&lt;br /&gt; char* mgr_name, uintptr_t mgr_name_len, char* pool_name, uintptr_t pool_name_len,&lt;br /&gt; uintptr_t initial_size, uintptr_t used, uintptr_t committed, uintptr_t max_size);&lt;br /&gt;probe mem-pool-gc-end(&lt;br /&gt; char* mgr_name, uintptr_t mgr_name_len, char* pool_name, uintptr_t pool_name_len,&lt;br /&gt; uintptr_t initial_size, uintptr_t used, uintptr_t committed, uintptr_t max_size);&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:100%;"  &gt;&lt;span style="font-family:verdana;"&gt;The first two probes provide generic information about the start and stop of a garbage collection, while the latter two provide more detailed information.  We'll output information from both to compare.  Note that the manager name and pool name are provided with the same pointer/length data pairs as we saw earlier.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Open a file called gcWatcher.d in a text editor and enter the following:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;hotspot$1:::gc-begin&lt;br /&gt;{&lt;br /&gt;printf("gc-begin: is_full = %d\n", arg1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;hotspot$1:::gc-end&lt;br /&gt;{&lt;br /&gt;printf("gc-end:\n");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;hotspot$1:::mem-pool-gc-begin&lt;br /&gt;{&lt;br /&gt;self-&gt;ptr1 = (char*) copyin(arg0, arg1+1);&lt;br /&gt;self-&gt;ptr1[arg1] = '\0';&lt;br /&gt;self-&gt;mgr_name = (string) self-&gt;ptr1;&lt;br /&gt;&lt;br /&gt;self-&gt;ptr2 = (char*) copyin(arg2, arg3+1);&lt;br /&gt;self-&gt;ptr2[arg3] = '\0';&lt;br /&gt;self-&gt;pool_name = (string) self-&gt;ptr2;&lt;br /&gt;&lt;br /&gt;printf("mem-pool-gc-begin: mgr: '%s'; pool: '%s'; initial: %d; used: %d; committed: %d; max: %d\n",&lt;br /&gt;    self-&gt;mgr_name, self-&gt;pool_name, arg4, arg5, arg6, arg7);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;hotspot$1:::mem-pool-gc-end&lt;br /&gt;{&lt;br /&gt;self-&gt;ptr1 = (char*) copyin(arg0, arg1+1);&lt;br /&gt;self-&gt;ptr1[arg1] = '\0';&lt;br /&gt;self-&gt;mgr_name = (string) self-&gt;ptr1;&lt;br /&gt;&lt;br /&gt;self-&gt;ptr2 = (char*) copyin(arg2, arg3+1);&lt;br /&gt;self-&gt;ptr2[arg3] = '\0';&lt;br /&gt;self-&gt;pool_name = (string) self-&gt;ptr2;&lt;br /&gt;&lt;br /&gt;printf("mem-pool-gc-end: mgr: '%s'; pool: '%s'; initial: %d; used: %d; committed: %d; max: %d\n",&lt;br /&gt;    self-&gt;mgr_name, self-&gt;pool_name, arg4, arg5, arg6, arg7);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;Save the file, then trace your Java application with the following:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;pre&gt;     pfexec dtrace -q -s gcWatcher.d &lt;span style="font-style: italic;"&gt;pi&lt;span style="font-family:verdana;"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;For my example, after triggering a little activity in my application, I saw a number of minor collections; here is the output from one of them:&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;gc-begin: is_full = 0&lt;br /&gt;mem-pool-gc-begin: mgr: 'Copy'; pool: 'Code Cache'; initial: 163840; used: 1751360; committed: 1769472; max: 33554432&lt;br /&gt;mem-pool-gc-begin: mgr: 'Copy'; pool: 'Eden Space'; initial: 917504; used: 917504; committed: 917504; max: 4194304&lt;br /&gt;mem-pool-gc-begin: mgr: 'Copy'; pool: 'Survivor Space'; initial: 65536; used: 58904; committed: 65536; max: 458752&lt;br /&gt;mem-pool-gc-begin: mgr: 'Copy'; pool: 'Tenured Gen'; initial: 4194304; used: 1406096; committed: 4194304; max: 61997056&lt;br /&gt;mem-pool-gc-begin: mgr: 'Copy'; pool: 'Perm Gen'; initial: 12582912; used: 1144824; committed: 12582912; max: 67108864&lt;br /&gt;mem-pool-gc-begin: mgr: 'Copy'; pool: 'Perm Gen [shared-ro]'; initial: 8388608; used: 6733248; committed: 8388608; max: 8388608&lt;br /&gt;mem-pool-gc-begin: mgr: 'Copy'; pool: 'Perm Gen [shared-rw]'; initial: 12582912; used: 7676960; committed: 12582912; max: 12582912&lt;br /&gt;mem-pool-gc-end: mgr: 'Copy'; pool: 'Code Cache'; initial: 163840; used: 1751360; committed: 1769472; max: 33554432&lt;br /&gt;mem-pool-gc-end: mgr: 'Copy'; pool: 'Eden Space'; initial: 917504; used: 0; committed: 917504; max: 4194304&lt;br /&gt;mem-pool-gc-end: mgr: 'Copy'; pool: 'Survivor Space'; initial: 65536; used: 29648; committed: 65536; max: 458752&lt;br /&gt;mem-pool-gc-end: mgr: 'Copy'; pool: 'Tenured Gen'; initial: 4194304; used: 1458336; committed: 4194304; max: 61997056&lt;br /&gt;mem-pool-gc-end: mgr: 'Copy'; pool: 'Perm Gen'; initial: 12582912; used: 1144824; committed: 12582912; max: 67108864&lt;br /&gt;mem-pool-gc-end: mgr: 'Copy'; pool: 'Perm Gen [shared-ro]'; initial: 8388608; used: 6733248; committed: 8388608; max: 8388608&lt;br /&gt;mem-pool-gc-end: mgr: 'Copy'; pool: 'Perm Gen [shared-rw]'; initial: 12582912; used: 7676960; committed: 12582912; max: 12582912&lt;br /&gt;gc-end:&lt;/pre&gt;&lt;/span&gt;&lt;br /&gt;Note that not a great deal of information is available from the generic garbage-collection &lt;span style="font-family:courier new;"&gt;begin&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;end&lt;/span&gt; probes, while much more information is available from the &lt;span style="font-family:courier new;"&gt;mem-pool&lt;/span&gt; probes.&lt;br /&gt;&lt;br /&gt;You can do much more than simply print the values of probe arguments, of course; see the reference documents for more information.  As an example, you can count and output the number of threads created in a time period, gather statistics on the average lifetime of a thread, output the average memory recovered during a garbage collection, and so on.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other Considerations&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One question you might have is "How expensive are these operations?"  It depends on the operation.  The probes we have looked at above are relatively inexpensive.  Other probes, such as method-entry and method-exit probes, or those monitoring object allocation, are much more expensive and indeed have a significant cost when enabled, even when they are not being used.&lt;br /&gt;&lt;br /&gt;For this reason, there is a JVM option &lt;span style="font-size:130%;"&gt;-- &lt;/span&gt;&lt;/span&gt; &lt;span style=";font-family:courier new;font-size:130%;"  &gt;&lt;code class="small"&gt;-XX:+ExtendedDTraceProbes&lt;/code&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt; &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:verdana;"&gt;-- which when present enables &lt;/span&gt;&lt;/span&gt;these and some other expensive probes.  For more information, see the "Effect of using DTrace with Java Programs" section of the &lt;a href="http://www.sun.com/bigadmin/features/articles/java_se6_observability.jsp"&gt;Observability Using Java Platform, Standard Edition 6, and Solaris OS&lt;/a&gt; article.  If this option is not enabled, DTrace will ignore any of the above-mentioned probes in your profiling application, sparing you from inadvertently slowing down someone's production server.&lt;br /&gt;&lt;br /&gt;That's the end of this quick tour.  As I mentioned earlier, there are a lot of resources available on DTrace, specifically the user guide on the &lt;a href="http://wikis.sun.com/display/DTrace/DTrace"&gt;DTrace wiki&lt;/a&gt; (see the "Documentation" link, or go directly to &lt;a href="http://wikis.sun.com/display/DTrace/Documentation"&gt;this link&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-230533967814422882?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/230533967814422882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2010/01/java-profiling-with-dtrace.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/230533967814422882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/230533967814422882'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2010/01/java-profiling-with-dtrace.html' title='Java profiling with DTrace'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-3766592866222614321</id><published>2009-07-15T04:54:00.000-07:00</published><updated>2009-07-15T05:14:46.237-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='automated testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>FlexMonkey 1.0 Released</title><content type='html'>My entries here are usually about Java, but today I want to call attention to the 1.0 release of FlexMonkey, an Adobe AIR app for testing Flex and Adobe AIR applications (I work for Gorilla Logic, the creator of FlexMonkey).  If you have a need to run automated tests of Flex and AIR apps, please give it a try.  If you are familiar with "old" versions of FlexMonkey (as in, 2008), take another look at it; it has evolved quite a lot during its short lifetime!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To learn about FlexMonkey and to download, go to &lt;a href="http://flexmonkey.gorillalogic.com/"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;http://flexmonkey.gorillalogic.com/&lt;/span&gt;&lt;/a&gt;.  Don't let the "Beta 1" fool you;  I've been using FlexMonkey since its birth and it is significantly more polished than a certain operating system I use every day.  There is also a site describing Gorilla Logic's Flex service offerings at &lt;a href="http://www.gorillalogic.com/what.development.services.flex.html"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;http://www.gorillalogic.com/what.development.services.flex.html&lt;/span&gt;&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally, I should mention that you are not alone should you become a FlexMonkey user.  I've been on a lot of support mailing lists in my time, and I am very impressed by the dedication of the user community (including a number of Gorillas!) who respond to questions.  So by all means give it a try with the confidence that you'll have all the help you need for both "newbie" and more advanced questions!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-3766592866222614321?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/3766592866222614321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2009/07/flexmonkey-10-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3766592866222614321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/3766592866222614321'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2009/07/flexmonkey-10-released.html' title='FlexMonkey 1.0 Released'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-563295510579139086</id><published>2009-07-04T15:37:00.000-07:00</published><updated>2009-07-05T15:54:21.428-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='com.sun.attach Java profiling Javassist'/><title type='text'>Instrumenting running Java processes with the com.sun.tools.attach API</title><content type='html'>In recent posts, I've investigated using the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrumen&lt;/span&gt;t package to instrument Java classes for a simple profiler.  The package summary documentation describes a standard method for instrumenting a target Java application at launch time (using the static &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;premain()&lt;/span&gt; method of the profiling agent).  It also describes the outline of a procedure to attach to, and instrument, an already-running application (using a static &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;agentmain()&lt;/span&gt; method).  As the package documentation says, the details of how to initiate this process attachment are implementation specific.  In this entry I'll describe how this process works for Sun Hotspot JVMs.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This subject has been discussed in a few other blogs (search on the package name); I'm sharing my experience because some of the pitfalls haven't been covered too well in other postings, and the more hits you can get on a particular stack trace, the better.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you've used JDK tools like Java VisualVM or JConsole, you've seen the attach API at work.  If you're going to attach to a running process, you need to get a handle for it (a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;VirtualMachineDescriptor&lt;/span&gt;, specifically), which implies a method for listing processes (namely, VirtualMachine.list()).  These are the process descriptors you see in the above tools' connect dialogs at launch time.  The best place to start is to look at the API documentation for &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;com.sun.tools.attach&lt;/span&gt;.  This information can be found in the tools documentation of your JDK documentation download, or online.  From there, take a look at the documentation for the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;com.sun.tools.attach.VirtualMachine&lt;/span&gt; class -- it provides an outline for getting started.  I'll start with this, pointing out some of the issues you can run into along the way.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The basic process is outlined below:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Create a public static void &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;agentmain()&lt;/span&gt; method in your profiling agent (if you have already created a launch-time profiling agent, this can contain the same logic as your&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; premain() &lt;/span&gt;method).&lt;/li&gt;&lt;li&gt;Add an &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Agent-Class:&lt;/span&gt; attribute to your profiler's manifest file, specifying the fully-qualified name of your profiler class&lt;/li&gt;&lt;li&gt;In your launch application, perform the following steps:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Obtain a descriptor for the target JVM.&lt;/li&gt;&lt;li&gt;Obtain a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;VirtualMachine&lt;/span&gt; instance with the static &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;VirtualMachine.attach()&lt;/span&gt; method.&lt;/li&gt;&lt;li&gt;Load your profiling agent into the target JVM with the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;VirtualMachine.loadAgent()&lt;/span&gt; method.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Detach from the target JVM&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;At this point, your profiler's &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;agentmain()&lt;/span&gt; method will be called and you are in business.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;Note that on Windows, a String version of the target JVM's Windows process ID can be passed as the&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; id &lt;/span&gt;for the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;VirtualMachine.attach()&lt;/span&gt; method.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A number of issues can arise during this process.  First, note that you need the full JDK, not just the JRE, to do this.  The reason is that you need the JDK's &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;tools.jar&lt;/span&gt; file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the first issues you might see is the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.UnsatisfiedLinkError: no attach in java.library.path&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;AttachNotSupportedException: no providers installed&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;com.sun.tools.attach.AttachNotSupportedException: no providers installed&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My diagnosis of this problem is that I was executing &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java&lt;/span&gt; on the command line, which as a result of my JDK and JRE installation choices was pointing to the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.exe&lt;/span&gt; in the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;%JAVA_HOME%/jre/bin&lt;/span&gt; directory.  While this is technically the same executable, you will find that when using the instrumentation packages, the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java &lt;/span&gt;executable expects to find &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;tools.jar&lt;/span&gt; using a relative path, and that path is relative to the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.exe&lt;/span&gt; in the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;%JAVA_HOME%/bin&lt;/span&gt; directory.  So ensure at launch time that you are running the java executable in the JDK bin, not the JRE bin, directory.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another more interesting problem you can run into when adding your agent jar to the target JVM is that the target JVM doesn't necessarily know about the dependencies of your agent.  For example, all agents will have a dependency on &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;tools.jar&lt;/span&gt;.  The one I have been building has an additional dependency on the Javassist &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;javassist.jar&lt;/span&gt; file.  If your target application does not have these files on its classpath, it will fail to start your agent.  For the record, in the console window (if you have one) for your target JVM (not the console from which you are trying to attach), you'll see something like&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exception in thread "Attach Listener" java.lang.NoClassDefFoundError: com/sun/tools/attach/AgentInitializationException&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;But you can't very well require that all potential target applications be launched with your dependencies on their classpath.  So what to do?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The answer lies in the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Boot-Class-Path:&lt;/span&gt; attribute in the profiling agent manifest file (see the package summary documentation for &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument&lt;/span&gt;).  Entries in this attribute are space-separated jar files.  So to get past this issue, I added the paths to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;tools.jar&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;javassist.jar&lt;/span&gt; to this attribute in my profiler's manifest file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At this point, you should be able to launch your agent.  When you launch your profiler agent at target JVM launch time, your class transformer will be called as each class is loaded.  When you launch your profiler by attaching to an already-running JVM, you will need to transform classes which have already been loaded.  In my profiler, I do this by calling the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getAllLoadedClasses()&lt;/span&gt; method of the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument.Instrumentation&lt;/span&gt; instance, then calling &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;retransformClasses()&lt;/span&gt; on them.  As you retrieve this set of classes, you might notice that you can check to see if the class is modifiable (using another method in the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Instrumentation&lt;/span&gt; instance).  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that according to the java.lang.instrument package summary documentation, you need the manifest attribute &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Can-Retransform-Classes:&lt;/span&gt; to be able to &lt;b&gt;re&lt;/b&gt;transform a class.  This attribute is not related to instrumenting at launch time versus after launch time (in either case, you could instrument the target application by transforming its classes only one time), but rather is related to the issue of transforming the same files multiple times (for example, to remove your profiling code).  I'll discuss retransforming classes a little later.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another important point to keep in mind is the call to add your transformer to your &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Instrumentation &lt;/span&gt;instance:  this should set the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;canRetransform &lt;/span&gt;attribute to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;true &lt;/span&gt;(use the 2-argument signature &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;addTransformer(ClassFileTransformer, boolean)&lt;/span&gt;, since the default value for the attribute is &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;false&lt;/span&gt;).  Although the class files had not yet actually been transformed at attach time (when I launch my profiler by attaching to an already-running JVM), I noticed in my own case that if the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;canRetransform&lt;/span&gt; attribute is &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;false&lt;/span&gt;, none of my methods get instrumented.  I believe the reason for this behavior is simply that I am calling &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;retransformClasses()&lt;/span&gt; when I attach to an already-running JVM (I see no other available method to use), and that method will not invoke the transformer's transform() method if the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;canRetransform &lt;/span&gt;attribute is &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;false&lt;/span&gt;. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I specifically ignore the classes of my own profiler when I perform this operation -- in my case I get a stack overflow error if I try to method-entry and method-exit instrument the very methods which process these events!  You may have similar issues if you are building a similar type of profiler.  I also sometimes get odd and unrepeatable (including core-dumping) behavior if I attempt to instrument core Java classes, so I am more inclined to exempt those from profiling (at least of the method-entry/exit kind).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An interesting question to consider is what happens when you terminate your profiling agent.  Mine is included in a Swing application.  Note that since your agent is launched in the same JVM as the target, you might not want to call &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;System.exit()&lt;/span&gt; anywhere -- your profiler users (including yourself) may not want to kill their target application just to close your profiler.  But thinking about this brings up another interesting question -- when you close your profiler, what happens to the instrumented classes in your target application?  The short answer is that they continue to be instrumented, possibly at significant cost to performance.  You don't want to force your profiler users to bounce their application to rid themselves of your bytecodes.  So the question is: how to get the target application back to its pre-instrumented state?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some clues to this question can be found (again!) in the package documentation, specifically the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;retransformClasses()&lt;/span&gt; method of &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument.Instrumentation&lt;/span&gt;.  The description of this method states that this method starts with the intial class bytes of the class, before it was transformed (some differences may exist with the original class bytes, but they are considered cosmetic in the classfile-structure sense).  Further reading of this description suggests that we should be able to revert to the original class bytes by (1) removing our current bytecode-manipulating transformer from our &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Instrumentation &lt;/span&gt;instance, and (2) calling &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;retransformClasses()&lt;/span&gt; on all classes.  Doing this should result in reversion to uninstrumented code, something that we should politely do before closing our profiler.  Besides, not doing so results in strange behavior if you launch another profiler against the same running JVM, since you will be re-instrumenting classes you had already instrumented with your previous profiler instance.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Looking at what we need to do to make this work, probably the safest thing to do is to always outfit the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Instrumentation &lt;/span&gt;class with no &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ClassFileTransformer &lt;/span&gt;and call &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;retransformClasses()&lt;/span&gt; first, before then attempting to instrument the target JVM's classes.  This behavior will ensure that you are always starting with the original class bytes (at target JVM launch time) before you transform.  Then, at profiler-close time, perform the same instrumentation-clearing operation.  In other words, the code would look something like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // initialization code:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     MyTransformer transformer = new MyTransformer();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     instrumentationInstance.addTransformer(transformer);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // to instrument, first revert all added bytecode:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     instrumentationInstance.removeTransformer(transformer);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // call retransformClasses() on all modifiable classes...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     instrumentationInstance.addTransformer(transformer);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // call retransformClasses() on all modifiable classes...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     ...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // before exiting application:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     instrumentationInstance.removeTransformer(transformer);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // call retransformClasses() on all modifiable classes...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next, I will verify that this approach works by implementing the above code and running a debug version of my profiler to see if my instrumentation code has been removed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My first concession to efficiency was to skip the initial revert-to-uninstrumented step, and only revert when I know that the classes have actually been instrumented.  The reason is that this is a fairly expensive operation and it isn't necessary to perform when the target application is being instrumented for the first time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second issue I had was specific to Javassist.  Once certain operations have been performed on a Javassist class model, that class is "frozen" and cannot be retransformed without first "defrosting" it (see &lt;a href="http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html"&gt;Getting Started with Javassist&lt;/a&gt; for details).  I noticed that, in spite of the fact that I was creating a new Javassist class instance from classfile bytecodes, I get a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;"class is frozen"&lt;/span&gt; &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;RuntimeException&lt;/span&gt; when I attempt to transform classes an additional time, so I got around the issue with code like the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     CtClass cc = cp.get(javassistClassName);&lt;/span&gt;&lt;/div&gt;&lt;code&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // for repeated instrument/uninstrument cycles, &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // make sure the class is unfrozen before we&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     // attempt to do anything to it:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     if (cc.isFrozen())&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  cc.defrost();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: georgia; font-size: 16px; "&gt;Looking at the above code reminds me of a minor point you should know -- the fully-qualified class names that the Java runtime passes to your class file transformer's &lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: 16px; "&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;transform()&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: georgia; font-size: 16px; "&gt; method are slash delimited, while Javassist expects dot (".") delimiters. So to match names, you need to something like the following:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:verdana;font-size:130%;"&gt;&lt;span class="Apple-style-span" style="font-size: 16px;"&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     String javassistClassName = className.replace('/', '.');&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;where &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;className &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;is the class name as passed in to &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;t&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ransform()&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;The above procedure should allow you to stop and start profiling (by un-instrumenting and instrumenting classes) and also to clean up before you close your profiler application, so you don't leave expensive profiling code in your target application at profiler disconnect time. I tested this procedure in my profiler with a pair of stop/start buttons and using Javassist (and the &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;defrost()&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt; method shown above) and verified that the target application does indeed revert to pre-instrumented bytecodes.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;I keep saying I'm going to do something really interesting with this profiling data (and I will!), but in the process of investigating this API I decided it merited its own entry. Soon, and maybe in my next post, I'll discuss generating events from this data and running them through an event processor.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/code&gt;&lt;/div&gt;&lt;code&gt;&lt;/code&gt;&lt;/div&gt;&lt;code&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-563295510579139086?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/563295510579139086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2009/07/instrumenting-running-java-processes.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/563295510579139086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/563295510579139086'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2009/07/instrumenting-running-java-processes.html' title='Instrumenting running Java processes with the &lt;tt&gt;com.sun.tools.attach&lt;/tt&gt; API'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-5195758438952506764</id><published>2009-06-29T10:32:00.000-07:00</published><updated>2009-06-29T21:57:21.442-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java performance profiling'/><title type='text'>Java Profiling, continued</title><content type='html'>I've been building a Java profiler lately, partly to address what I think are shortcomings in the current set of free/shareware profilers, and also to enjoy the flexibility of obtaining only the profiling information I need.  If you've spent much time with profilers, you already know they can have quite an impact on the application they're profiling!  My goal with my own profiler is to obtain a narrow set of information, having more control over the size and frequency of the data collection.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One feature I really like about &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof&lt;/span&gt; (see &lt;a href="http://java.sun.com/developer/technicalArticles/Programming/HPROF.html"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;http://java.sun.com/developer/technicalArticles/Programming/HPROF.html&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;) is the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;heap=sites&lt;/span&gt; option.  If you're not familiar with this option, it is described in the above link, but in short, &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof &lt;/span&gt;can provide a profile of the allocation of objects per &lt;i&gt;site&lt;/i&gt;, where a site is a unique Java stack trace of a fixed depth.  This can be very handy information when you are investigating the heap usage of an allocation, but it is extremely costly to get with &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof &lt;/span&gt;(in one recent case I was investigating, starting an application with the hprof agent slowed the application down by &lt;i&gt;several &lt;/i&gt;orders of magnitue).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today I'll discuss how I get this same information without the overhead of &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof&lt;/span&gt;.  I'll build on my last blog entry about the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument&lt;/span&gt; package and combine bytecode injection with the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ThreadMXBean &lt;/span&gt;to get this same information.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The basic outline is:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Create a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument&lt;/span&gt; profiling agent.&lt;/li&gt;&lt;li&gt;Intercept all constructors as they are loaded, instrumenting them on constructor entry and constructor exit.  Information passed back to the profiler application will include the thread ID and the size of the object created.&lt;/li&gt;&lt;li&gt;In the profiling agent, keep track of the total memory allocated for each object type, as well as a list of stack trace signatures at object instantiation, with frequency of each.  The stack trace is obtained via the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ThreadMXBean &lt;/span&gt;of the JVM.&lt;/li&gt;&lt;li&gt;Rank objects by total amount of memory allocated, the set of unique stack trace signatures for each constructor, and the number of times the object was instantiated via each stack trace.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;This information will approximate the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;heap=sites&lt;/span&gt; output of &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof&lt;/span&gt;, and can be obtained more economically for a number of reasons:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;We can restrict the classes (constructors) instrumented.  Note that if we do not instrument every class, we may not see &lt;i&gt;every &lt;/i&gt;instance of a particular object's instantiation, but in practice what you usually care about are objects instantiated by &lt;i&gt;your &lt;/i&gt;application.  Learning in &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof&lt;/span&gt; that 20 MB of &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.Object&lt;/span&gt;s were created as a side effects of a java.* method call usually doesn't help diagnose performance problems.&lt;/li&gt;&lt;li&gt;The custom profiler can get this information in a very small fraction of the same time that &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof &lt;/span&gt;would require to get it, as it is a much more targeted application.&lt;/li&gt;&lt;li&gt;With the custom profiler, we have a lot more control over the interval during which the data is collected.  For example, we can clear our profiler's data, initiate an operation in the profiled application, and see just the allocation history for the time period of interest.  I actually do not know how to obtain this information with &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;hprof&lt;/span&gt;; the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;heap=sites&lt;/span&gt; option dumps its summary at application termination (as a snapshot of the heap at that point in time), which may not be what you want.&lt;/li&gt;&lt;/ul&gt;As I mentioned in my last entry, I use Javassist (see &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=22866&amp;amp;package_id=80766"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;http://sourceforge.net/project/showfiles.php?group_id=22866&amp;amp;package_id=80766&lt;/span&gt;&lt;/a&gt;).  Javassist will create a Java class representation from the bytecode array, and from there it is very easy to obtain the constructors, using &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;CtClass.getConstructors()&lt;/span&gt;.  The &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;CtConstructor.insertBefore()&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;insertAfter()&lt;/span&gt; methods round out all you will need from Javassist to instrument your code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Object size is a pesky issue in Java, especially if you have experienced the convenience of the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;sizeof()&lt;/span&gt; operator.  I use the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument.Instrumentation&lt;/span&gt; instance, supplied by the JVM in the call to the profiler's &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;premain()&lt;/span&gt; method, to get the size of the objects (using &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getObjectSize(Object)&lt;/span&gt;).  It isn't exactly clear what size this method returns; the javadocs are a little cagey and it's safe to safe this value isn't a deep copy.  While it is possible to drill down through object references in a class and attempt to accumulate a deep-copy value, this operation itself can be very time-consuming, incomplete (due to inaccessible attributes) and slightly misleading (static references, anyone?).  Not to mention you can easily get a stack overflow error in the process.  It may not be perfect, but I have chosen to simply use the value returned by &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Instrumentation.getObjectSize(Object&lt;/span&gt;), and to keep in mind that what I'm seeing is useful in a rough, rather than a precise, sense.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since the profiler runs in the same JVM as the profiled application, it is fairly simple to get a reference to the JVM &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ThreadMXBean&lt;/span&gt;, using &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.management.ManagementFactory.getThreadMXBean()&lt;/span&gt;.  Given a thread ID (which you can arrange for your instrumented constructor to pass back to your profiler), you can get the stack trace for the thread with &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ThreadMXBean.getThreadInfo(long,int). N&lt;/span&gt;ote that there are several signatures for this method call; remember to pick the one where you specify the maximum depth of the stack trace, as the default value is zero!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The value of collecting information like this in a profiler should be self-evident; however, there are greater opportunities available for this data.  For example, a variety of profiling information can be used to generate events which can be used to monitor the health of the profiled system.  These don't all need to be just events generated by the profiler; they could include SCM and system-maintenance events, with the result being that maybe you could see that your ASN.1 parser suddenly takes three times as long to parse a switch file since the last change was checked in and rolled out to production.  In a later posting, I'll look at how such a system could be implemented, looking at the open-source tools available to analyze this kind of data and make associations between events that can provide much faster resolution of operational and performance issues.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-5195758438952506764?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/5195758438952506764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2009/06/java-profiling-continued.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5195758438952506764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/5195758438952506764'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2009/06/java-profiling-continued.html' title='Java Profiling, continued'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-7400868899454383141</id><published>2009-05-15T12:59:00.000-07:00</published><updated>2009-06-29T12:03:39.788-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java performance profiling'/><title type='text'>Java Profiling with the java.lang.instrument Package</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;Lately I've been looking at profilers and wondering how easy it would be to write one, mostly to be able to provide a little more sophisticated guidance to performance investigations.  For example, while it is useful to pop a profiler and see what methods are consuming the most time in an application, wouldn't it be even more interesting if your profiler could generate an event any time your application spent more than a specified amount of time in a method, like 25% more than the average time (or fell more than 2 sigma outside the mean)?&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;In general, getting events when something interesting happens is more helpful than watching a display and waiting for anomalies (how many monkeys does &lt;span class="Apple-style-span" style="font-style: italic;"&gt;that&lt;/span&gt; employ?!).  That's why I'm also a little disappointed in the JVM's built-in JMX beans, only two of which (&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;MemoryMXBean&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt; and &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;MBeanServerDelegateMBean&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;) implement the&lt;/span&gt; NotificationEmitter &lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;interface.  I would much prefer registering for notifications from the garbage collector JMX bean than triggering verbose gc output (with command-line options) and then following and parsing log output!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;In this posting I'm going to show you how quickly you can instrument a Java application, and hopefully it will look easy enough that you will give it a try.  First, I'd recommend reading the package documentation for &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.instrument.&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;  It isn't a large package and the time spent is well worth it.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;As usual, let's get the setup out of the way.  For pre-requisites (such as Java SDK, Maven, etc.), please see one of my earlier posts.  Assuming you have the Java SDK and Maven 2 (along with the usual Maven environment variables created), you're ready to go.  In a directory containing your development projects, enter the following:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;mvn archetype:generate -DgroupId=com.example.profiler -DartifactId=JavaProfiler&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;Accept all the defaults and wait for your project directory to be generated.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;Change into the new project directory, open the &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;pom.xml&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt; file and add the following build plugins:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &amp;lt;build&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    &amp;lt;plugins&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;plugin&amp;gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;configuration&amp;gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;/configuration&amp;gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      &amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      &amp;lt;plugin&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;artifactId&amp;gt;maven-jar-plugin&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;configuration&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          &amp;lt;archive&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;            &amp;lt;manifestFile&amp;gt;src/main/resources/META-INF/MANIFEST.MF&amp;lt;/manifestFile&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          &amp;lt;/archive&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        &amp;lt;/configuration&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      &amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    &amp;lt;/plugins&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &amp;lt;/build&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;The first plugin specifies Java SE6 (rather than the default 1.3!) and the second one says we're going to be supplying our own manifest file.  More on that below.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Our basic profiler is responsible for doing a couple of things:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;It must supply a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;premain&lt;/span&gt; method, per the requirements discussed in the package documentation;&lt;/li&gt;&lt;li&gt;It must implement the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ClassFileTransformer &lt;/span&gt;interface (or delegate to a class which does; we're keeping it simple here).&lt;/li&gt;&lt;/ol&gt;Rename the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;App.java&lt;/span&gt; class to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.java&lt;/span&gt;.  For our first cut, we will not bother parsing agent arguments (again, see the package documentation), and our interface-specified transform class will simply print the name of the class and return &lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;null&lt;/span&gt;.  In other words, as the runtime passes us the bytecodes of each class, rather than manipulate them and return an instrumented version, we'll just note the class name and size and let it go.  To save you some time, here is what a simple implementation would look like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;package com.example.profiler;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import java.lang.instrument.ClassFileTransformer;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import java.lang.instrument.IllegalClassFormatException;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import java.lang.instrument.Instrumentation;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import java.security.ProtectionDomain;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; * Simple java.lang.instrument profiler&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; *&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; */&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public class SimpleProfiler implements ClassFileTransformer&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  protected String agentArgString = "";&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  protected Instrumentation instrumentation;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  public static void premain(String agentArgs, Instrumentation inst)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    SimpleProfiler profiler = new SimpleProfiler(agentArgs, inst);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  public SimpleProfiler(String agentArgs, Instrumentation inst)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    agentArgString = agentArgs;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    instrumentation = inst;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    instrumentation.addTransformer(this);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  public byte[] transform(ClassLoader loader,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          String className,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          Class&amp;lt;?&amp;gt; classBeingRedefined,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          ProtectionDomain protectionDomain,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          byte[] classfileBuffer)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    throws IllegalClassFormatException&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    System.out.println("SimpleProfiler.transform(): class: " + className + " (" + classfileBuffer.length + " bytes)");&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    return null;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This class&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;provides the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;premain &lt;/span&gt;method that the runtime needs to launch this profiling agent when the target application launches&lt;/li&gt;&lt;li&gt;adds itself as a class file transformer using the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Instrumentation &lt;/span&gt;object passed to it by the runtime&lt;br /&gt;&lt;/li&gt;&lt;li&gt;implements a very simple &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;transform &lt;/span&gt;method (returning&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt; &lt;/span&gt;null&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt; &lt;/span&gt;means the transformer does not modify the class file)&lt;/li&gt;&lt;/ol&gt;Now, the runtime will need to know how to launch the profiler, and that is why you need a manifest file.  Create the directory structure &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;resources/META-INF&lt;/span&gt; under the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;src/main&lt;/span&gt; directory, and add the following single-line &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;MANIFEST.MF&lt;/span&gt; file:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;     &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Premain-Class: com.example.profiler.SimpleProfiler&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now you should be able to build with&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;     &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;mvn clean install&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To see our profiler in action, modify the command line of any Java application you have with the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  -javaagent:&lt;i&gt;&amp;lt;path to your profiler project directory&amp;gt;&lt;/i&gt;/target/JavaProfiler-1.0-SNAPSHOT.jar&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This option will cause the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;premain &lt;/span&gt;method of the profiler to be called before the target application's classfiles are loaded, and will give the profiler an opportunity to modify their bytecodes as they are loaded.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;I ran a simple Java-based JDBC query tool with this agent and my output from the transform method looked like the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: Query (21580 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: java/sql/SQLException (2836 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: java/awt/Component$2 (854 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: java/awt/Component$4 (777 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: java/sql/ResultSet (8938 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: java/sql/Wrapper (337 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: java/sql/ResultSetMetaData (1045 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: java/awt/AWTEvent$1 (539 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: sun/awt/AWTAccessor$AWTEventAccessor (270 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: sun/reflect/misc/Trampoline (482 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: sun/reflect/GeneratedConstructorAccessor1 (1277 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: sun/reflect/GeneratedMethodAccessor1 (918 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: javax/swing/text/WrappedPlainView (7040 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: javax/swing/text/BoxView (8593 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: javax/swing/text/CompositeView (6079 bytes)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SimpleProfiler.transform(): class: javax/swing/text/WrappedPlainView$WrappedLine (5054 bytes)'&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;and so on.  You are probably thinking it would be nice to restrict the set of classes that are inspected (and possibly instrumented).  This is where the agent argument string (passed to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;premain&lt;/span&gt;) comes in handy.  This is a single &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;java.lang.String&lt;/span&gt;, rather than the usual array as in the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;main &lt;/span&gt;method, but it's a simple matter to parse one.  For example, you could pass in a comma-delimited list of regular expressions to determine what classes get inspected and which do not.  If we don't do a little filtering, our profiler's performance will suffer and any output we create on the instrumentation process will be overwhelming, so I will provide sample argument-parsing code in the example without spending time discussing it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I should say at this point that I've seen a number of blog postings on this subject, all of which stop here and say "Next, we'll use an open-source package to insert bytecodes etc.!".  I have yet to see a follow-on where this actually occurs.  I was thinking of putting this in a follow-on posting, but I got here (Starbucks) by bus, and on the off chance I get run over catching one home, let's go ahead and do something meaningful with the bytecodes before we end this post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I looked at ASM, BCEL and Javassist, and decided on Javassist (Why?  Not too much -- and not too little -- 'getting started' documentation.)  Having tried it, it was so easy to use I haven't tried any of the others yet.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As you would expect, Javassist builds a representation of the class file by inspecting the bytecode array.  It also includes some very handy methods for inserting blocks of code (which you specify in &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;String &lt;/span&gt;form) at the beginning and ending of methods (among many other possibilities, of course).  "Insert before" and "insert after" are exactly what I want for this profiler.  I want to insert code to print out an "entry" or "exit" message in every method.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A simple way to do this with Javassist is to modify the transform method as below (preceded by some import statements).  Note the addition of the regular-expression-processing code:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import java.util.regex.Matcher;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import java.util.regex.Pattern;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import java.util.regex.PatternSyntaxException;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;import javassist.CannotCompileException;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import javassist.ClassPool;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import javassist.CtClass;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import javassist.CtConstructor;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import javassist.ByteArrayClassPath;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;import javassist.CtMethod;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;There is a new attribute for the profiler:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    protected Pattern[] classRegexPatterns = null;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;which gets initialized at the end of the constructor:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    // agentArgString is list of regexes of classes to instrument:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    if (agentArgString != null &amp;amp;&amp;amp; agentArgString.length() &amp;gt; 0)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      String[] classRegexes = agentArgString.split(",");&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      classRegexPatterns = new Pattern[classRegexes.length];&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      for (int i=0; i&amp;lt;classRegexes.length; i++)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        classRegexPatterns[i] = Pattern.compile(classRegexes[i]);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, for the new transform method:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  public byte[] transform(ClassLoader loader,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          String className,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          Class&amp;lt;?&amp;gt; classBeingRedefined,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          ProtectionDomain protectionDomain,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;                          byte[] classfileBuffer)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    throws IllegalClassFormatException&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    for (int i=0; i&amp;lt;classRegexPatterns.length; i++)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      Matcher matcher = classRegexPatterns[i].matcher(className);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      if (matcher.matches())&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        try&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          // first modify the class name for javassist.  convert slashes to dots:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          String javassistClassName = className.replace('/', '.');&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          // turn bytecodes into a Javassist CtClass&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          ClassPool cp = ClassPool.getDefault();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          cp.insertClassPath(new ByteArrayClassPath(javassistClassName, classfileBuffer));&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          CtClass cc = cp.get(javassistClassName);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          // add output at the beginning and end of each method&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          CtMethod[] methods = cc.getMethods();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          for (int k=0; k&amp;lt;methods.length; k++)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;            // do not instrument inherited methods:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;            if (methods[k].getLongName().startsWith(javassistClassName))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;            {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;              methods[k].insertBefore("System.out.println(\"Entering " + methods[k].getLongName() + "\");");&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;              methods[k].insertAfter("System.out.println(\"Exiting " + methods[k].getLongName() + "\");");&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;            }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          // return the new bytecode array:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          byte[] newClassfileBuffer = cc.toBytecode();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          return newClassfileBuffer;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        catch (Exception exc)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          System.err.println(exc.getClass().getName() + ": " + exc.getMessage());&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          if (!(exc instanceof CannotCompileException))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;            // don't care about the stack trace if there was no method body, etc.:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;            exc.printStackTrace();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;          }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    return null;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Note that the Java runtime returns class names slash-delimited, while Javassist expects them to be dot-delimited.  Other than that detail, Javassist has no trouble creating and manipulating class file objects from our byte arrays.  Also note that I have chosen not to instrument all methods.  The Javassist full method name starts with the Javassist class name.  To avoid instrumenting methods in parent classes (which normally results in Javassist's throwing an exception because it does not have access to the method body), I have chosen to restrict instrumentation to the methods defined for the class in question.  You can remove the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;if &lt;/span&gt;statement and see what happens...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Note the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;insertBefore()&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;insertAfter()&lt;/span&gt; methods.  These are also available for your target application's constructors (retrieved by &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;CtClass.getConstructors())&lt;/span&gt;, but I left constructor instrumentation out of this profiler to keep it as short as possible.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To build the profiler, add the following dependency to your &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;pom.xml&lt;/span&gt; file:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      &amp;lt;groupId&amp;gt;javassist&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      &amp;lt;artifactId&amp;gt;javassist&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      &amp;lt;version&amp;gt;3.8.0.GA&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;and rebuild with &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;mvn install&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Your target application launch will now need to include the Javassist &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;jar &lt;/span&gt;file in its classpath.  If you have Javassist installed, just point to the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;jar &lt;/span&gt;file there.  If not, you can find it in your local Maven repository, as Maven downloaded it to perform the updated build.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, relaunch your target application.  Note from the package documentation that you pass in your agent argument string at the end of the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;-javaagent&lt;/span&gt; option, following an equals sign.  For example, I used:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;-javaagent:&lt;i&gt;&amp;lt;path to your profiler project directory&amp;gt;&lt;/i&gt;/target/JavaProfiler-1.0-SNAPSHOT.jar=.*Query.*&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note as it runs that you are now seeing console output when methods are entered and exited.  In my query-tool example, I see the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query.main(java.lang.String[])&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query.layOutTool()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query.layOutTool()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query.initializeTool()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query.loadQueries()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query.loadQueries()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query.initializeTool()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query.addListeners()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query.addListeners()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query.setInitialDividerLocations()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query.setInitialDividerLocations()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query.main(java.lang.String[])&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Entering Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Exiting Query$DatabaseConnection.toString()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;and so on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Following the log output from &lt;span class="Apple-style-span" style="font-style: italic;"&gt;this&lt;/span&gt; profiler isn't that exciting, either!  But note what is now available to you.  First of all, the profiler is loaded by the same classloader as your target application.  This means that if you have methods in your profiler to process method-entry and method-exit events, you can insert bytecodes into the target application to call your profiler (I used a singleton pattern, with a static &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;getInstance()&lt;/span&gt; method, etc., in my in-house profiler application).  You can insert code to send along the system time stamp, and your profiler can keep a running total of the execution time, number of invocations, percentage of total time, and so on, of the target application.  If you do something like this, be sure to include the full method signature in your output, as well as the calling thread's ID, to correctly match your entry and exit events.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once you are collecting sufficient information, you can start monitoring it for anomalies and generate events (e.g. JMS messages) for incidents you find interesting, and customize your profiler for specific problems and customer situations.&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-7400868899454383141?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/7400868899454383141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2009/05/java-profiling-with-javalanginstrument.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7400868899454383141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/7400868899454383141'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2009/05/java-profiling-with-javalanginstrument.html' title='Java Profiling with the java.lang.instrument Package'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-6134226774173117661</id><published>2009-03-24T14:03:00.000-07:00</published><updated>2009-03-24T21:18:36.964-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlassFishESB OpenESB JBI BPEL4People WorklistManager'/><title type='text'>Tapping into the GlassFishESB Worklist Manager</title><content type='html'>I recently investigated the Worklist Manager in GlassFish ESB and want to share some of the details here.  GlassFish is based on the Java Business Integration (JBI) specification and includes service engines for Java EE, BPEL and so on.  The Worklist Manager is one of these service engines.  It is not based on BPEL4People as far as I know but basically meets the same need -- providing a way to integrate human/workflow tasks into a business-process environment.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that there is a Wiki for this service engine at &lt;tt&gt;&lt;a href="http://wiki.open-esb.java.net/Wiki.jsp?page=WLMSE"&gt;http://wiki.open-esb.java.net/Wiki.jsp?page=WLMSE&lt;/a&gt;&lt;/tt&gt;.  My goal when investigating the WLMSE was to demonstrate accessing it from a web service client external to the GlassFish environment.  The documentation in this area is rather spotty, and hence this post.  I started at the above Wiki and took things from there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An important consideration here is that there are a number of versions of GlassFishESB, OpenESB, NetBeans, and so on, and the combination makes a difference.  If you peruse enough online tutorials, you'll finally begin wondering what version, exactly, you need to download to see the same functionality as you are seeing in the tutorial.  For example, the latest release, recommended on the  WorkList Manager Service Engine (WLMSE) Wiki, is GlassFish ESB V2.1 Milestone 1.  The download for this release includes NetBeans 6.5.  It does &lt;span class="Apple-style-span" style="font-style: italic;"&gt;not &lt;/span&gt;include the WLMSE, however, which the Wiki recommends obtaining as a separate download.  The only problem with the provided download is that it is only compatible with the latest patch of NetBeans 6.1, and lower.  So you will need an earlier version of NetBeans in order to install the WLMSE!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For reference, I used GlassFish V2 UR2 and NetBeans 6.1 Patch 4.  It does not appear feasible at this time to use V2.1M1 with the WLMSE based on the above issue, so I recommend trying something a little older.  My pre-requisites below send you to the older version that I used to develop this post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Pre-requisites:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Get NetBeans 6.1 at &lt;tt&gt;&lt;a href="http://www.netbeans.org/downloads/6.1/index.html"&gt;http://www.netbeans.org/downloads/6.1/index.html&lt;/a&gt;&lt;/tt&gt;, selecting the "All" column, which includes SOA support.&lt;/li&gt;&lt;li&gt;Java SE 6 installed:  &lt;tt&gt;&lt;a href="http://java.sun.com/javase/downloads/index.jsp"&gt;http://java.sun.com/javase/downloads/index.jsp&lt;/a&gt;&lt;/tt&gt;.  Be sure to get the JDK, not the JRE, as there are utilities you will need from the JDK.&lt;/li&gt;&lt;li&gt;Maven 2 installed:  &lt;tt&gt;&lt;a href="http://maven.apache.org/download.html"&gt;http://maven.apache.org/download.html&lt;/a&gt;&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;The following environment variables:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;tt&gt;JAVA_HOME&lt;/tt&gt;:  top-level Java SE 6 directory&lt;/li&gt;&lt;li&gt;&lt;tt&gt;M2_HOME&lt;/tt&gt;:  top-level Maven 2 directory&lt;/li&gt;&lt;li&gt;&lt;tt&gt;M2&lt;/tt&gt;:  &lt;tt&gt;$M2_HOME/bin&lt;/tt&gt; or &lt;tt&gt;%M2_HOME%\bin&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;&lt;tt&gt;MAVEN_OPTS:  -Xms256m -Xms512m&lt;/tt&gt; (optional)&lt;/li&gt;&lt;li&gt;&lt;tt&gt;PATH&lt;/tt&gt;:  &lt;tt&gt;$JAVA_HOME/bin:$M2:$PATH&lt;/tt&gt; or &lt;tt&gt;%JAVA_HOME%\bin;%M2%;%PATH%&lt;/tt&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;The Java SE JDK, Maven 2 and the environment-variable settings are for the Java-based web-service client we'll be building after we deploy an instance of the Worklist Manager.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Create a Worklist Application&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Start NetBeans.  Once the IDE is up, select the Services tab, expand "Servers", then right-click on "GlassFish V2" and select "Start".  Once the GlassFish server has started, select the Projects tab.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From the "File" menu, select "New Project...", then select category "SOA", then select "Worklist Module".  Enter "TutorialWorklistApp" for the project name and click "Finish".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Our worklist application will start with a single operation.  Just as an example, assume this is an ETL system and we want to create a trouble ticket on failure of a file to load.  The creation of the application will be a lot smoother if we first create the XML Schema for the request and response messages, then create the WSDL definition to define the operation, then create the worklist Task itself.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;The XML Schema&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Right-click on the "WorklistFiles" directory under "TutorialWorklistApp", select "New" -&gt; "XML Schema...".  If "XML Schema..." is not listed, select "Other...", then "XML", then "XML Schema", then "Next".  Name the schema &lt;tt&gt;tutorial_worklist&lt;/tt&gt; (NetBeans will supply an .xsd extension) and click "Finish".  The schema will open in a graphical schema editor.  Provide elements for the request and response messages and base them on complexTypes containing information that might be needed for this application.  An example schema is below:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;tt&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;tt&gt;&lt;div&gt;&amp;lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;/div&gt;&lt;div&gt;            targetNamespace="http://xml.netbeans.org/schema/tutorial_worklist"&lt;/div&gt;&lt;div&gt;            xmlns:tw="http://xml.netbeans.org/schema/tutorial_worklist"&lt;/div&gt;&lt;div&gt;            elementFormDefault="qualified"&amp;gt;&lt;/div&gt;&lt;div&gt;  &amp;lt;xsd:element name="loadFailureActionRequest" type="tw:LoadFailureActionRequestType"/&amp;gt;&lt;/div&gt;&lt;div&gt;  &amp;lt;xsd:element name="loadFailureActionResponse" type="tw:LoadFailureActionResponseType"/&amp;gt;&lt;/div&gt;&lt;div&gt;  &amp;lt;xsd:complexType name="LoadFailureActionRequestType"&amp;gt;&lt;/div&gt;&lt;div&gt;    &amp;lt;xsd:sequence&amp;gt;&lt;/div&gt;&lt;div&gt;      &amp;lt;xsd:element name="feedName" type="xsd:string"/&amp;gt;&lt;/div&gt;&lt;div&gt;      &amp;lt;xsd:element name="fileName" type="xsd:string"/&amp;gt;&lt;/div&gt;&lt;div&gt;      &amp;lt;xsd:element name="timestamp" type="xsd:date"/&amp;gt;&lt;/div&gt;&lt;div&gt;    &amp;lt;/xsd:sequence&amp;gt;&lt;/div&gt;&lt;div&gt;  &amp;lt;/xsd:complexType&amp;gt;&lt;/div&gt;&lt;div&gt;  &amp;lt;xsd:complexType name="LoadFailureActionResponseType"&amp;gt;&lt;/div&gt;&lt;div&gt;    &amp;lt;xsd:sequence&amp;gt;&lt;/div&gt;&lt;div&gt;      &amp;lt;xsd:element name="troubleTicketID" type="xsd:string"/&amp;gt;&lt;/div&gt;&lt;div&gt;    &amp;lt;/xsd:sequence&amp;gt;&lt;/div&gt;&lt;div&gt;  &amp;lt;/xsd:complexType&amp;gt;&lt;/div&gt;&lt;/tt&gt;&lt;div&gt;&lt;tt&gt;&amp;lt;/xsd:schema&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Save the schema and check it with the "Validate XML" button.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;The WSDL definition&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Right-click on the "WorklistFiles" directory under "TutorialWorklistApp", select "New" -&gt; "WSDL Document...".  If "WSDL Document..." is not listed, select "Other...", then "XML", then "WSDL Document", then "Next".  Name the WSDL document "tutorial_worklist"  (NetBeans will supply a .wsdl extension) and click "Finish".   Select "Concrete WSDL Document", then "SOAP" Binding and "Document Literal" for the Type.  Click "Next".&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the "Abstract Configuration" panel, clean up some of the names a little.  Change the port type name to &lt;tt&gt;worklistPortType&lt;/tt&gt;, the operation name to &lt;tt&gt;processLoadFailure&lt;/tt&gt;, then click the ellipses ("...") for the Input and Output messages to select the input and output messages we defined in the XML Schema above (namely, &lt;tt&gt;loadFailureActionRequest&lt;/tt&gt; and &lt;tt&gt;loadFailureActionResponse&lt;/tt&gt;; you will need to scroll up in the dialog to find the definition, and expand the "Elements" node).  Leave the "Generate partnerlinktype automatically" box checked.  Click "Next".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On the "Concrete Configuration" panel, clean up the names a little, using &lt;tt&gt;worklistBinding&lt;/tt&gt;, &lt;tt&gt;worklistService&lt;/tt&gt;, and &lt;tt&gt;worklistPort&lt;/tt&gt; for Binding Name, Service Name, and Port Name, respectively.  Click "Finish".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;The Task definition&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Right-click on the "WorklistFiles" directory under "TutorialWorklistApp", select "New" -&gt; "Worklist Task Definition...".  If "Worklist Task Definition..." is not listed, select "Other...", then "SOA", then "Worklist Task Definition", then "Next".  Name the file &lt;tt&gt;processLoadFailure&lt;/tt&gt; (no need for an extension), click the ellipsis by the empty Operation name, expand the WSDL definition down to the &lt;tt&gt;processLoadFailure&lt;/tt&gt; operation, and click "OK".  Click "Finish".  The Task definition will now open in a graphical editor.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Build&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Right click on the name of the Worklist Application ("TutorialWorklistApp") and select "Build".  You should get a successful build.  This application is now a JBI module which can be deployed to a composite application, which is our next step.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Create a Composite Application&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From the "File" menu, select "New Project...", then project category "SOA", then "Composite Application".  Click "Next".  Name the project &lt;tt&gt;TutorialCompositeApp&lt;/tt&gt;.  Click Finish.  The Service Assembly file &lt;tt&gt;TutorialCompositeApp.casa&lt;/tt&gt; will open in a graphical editor containing three sections:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;WSDL Ports&lt;/li&gt;&lt;li&gt;JBI Modules&lt;/li&gt;&lt;li&gt;External Modules&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;Drag the Worklist Application (TutorialWorklistApp) over to the "JBI Modules" section of the service assembly and drop it.  At this point, your service assembly will look as follows:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_dNjU9gI9Js0/SclqUGPDTLI/AAAAAAAAABA/nMnMz-9N4KM/s1600-h/compositeAppPreBuild.jpeg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 269px;" src="http://3.bp.blogspot.com/_dNjU9gI9Js0/SclqUGPDTLI/AAAAAAAAABA/nMnMz-9N4KM/s400/compositeAppPreBuild.jpeg" border="0" alt="" id="BLOGGER_PHOTO_ID_5316897728591252658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Right-click on the project name and select "Build".  You will see the service-assembly view reload, with the following results:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_dNjU9gI9Js0/SclqG0V_qyI/AAAAAAAAAA4/SEw7KYWCj8k/s1600-h/compositeAppPostBuild.jpeg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 269px;" src="http://2.bp.blogspot.com/_dNjU9gI9Js0/SclqG0V_qyI/AAAAAAAAAA4/SEw7KYWCj8k/s400/compositeAppPostBuild.jpeg" border="0" alt="" id="BLOGGER_PHOTO_ID_5316897500450237218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that the &lt;tt&gt;processLoadFailure&lt;/tt&gt; operation has a configured SOAP/HTTP binding, as we expected (we just configured it in some detail), but notice that we also have a &lt;tt&gt;TaskCommonPort&lt;/tt&gt;, with no binding.  This is the Worklist Manager.  We will add a SOAP/HTTP binding for this port so that we will be able to access the items in the Worklist from a simple demonstration Java client.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Create the Worklist Manager binding&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From the "WSDL Bindings" section of the Palette, drag and drop a "soap" binding on the "WSDL Ports" section of the service assembly.  You will see an additional binding similar to the one already configured for the Worklist application.  Select the purple (right-pointing) arrow in the binding and drag over to and connect to the &lt;tt&gt;TaskCommonPort&lt;/tt&gt; port.  Now, right-click on this binding and select "Properties".  Change &lt;tt&gt;casaPort1&lt;/tt&gt; to &lt;tt&gt;worklistManagerPort&lt;/tt&gt;, then click on the ellipsis ("...") by the soap:address Location.  You should see the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;http://localhost:${HttpDefaultPort}/casaService1/worklistManagerPort&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Simplify this a little by changing it to&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;http://localhost:${HttpDefaultPort}/worklistManager&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that the URL for the Worklist application is similarly wordy.  If you want to shorten it, you can in similar manner, but you'll have to first right-click on the binding and select "Clone WSDL Port to edit...".  Confirm on the dialog which follows, then right-click and select "Properties" to edit, and change the soap:address Location from&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;http://localhost:${HttpDefaultPort}/tutorial_worklistService/tutorial_worklistPort&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;to&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;http://localhost:${HttpDefaultPort}/worklistApp&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;then click "Close" to save.  Your service assembly should now look as follows:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_dNjU9gI9Js0/Sclucq9dWGI/AAAAAAAAABI/j7zDHUAhdt4/s1600-h/compositeAppPostConfigure.jpeg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 270px;" src="http://3.bp.blogspot.com/_dNjU9gI9Js0/Sclucq9dWGI/AAAAAAAAABI/j7zDHUAhdt4/s400/compositeAppPostConfigure.jpeg" border="0" alt="" id="BLOGGER_PHOTO_ID_5316902273935038562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Deploy the Composite Application&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before we deploy the application, you're probably wondering what ${HttpDefaultPort} means.  You might guess that it is the default port of the GlassFish web services, but actually each of the binding components in GlassFish has their own unique default port.  This can be a problem if you are trying to access a binding component from outside of GlassFish and don't know the port number, but these can be found in the Admin console.  For more information, see "Understanding the ${HttpDefaultPort} Token" at &lt;tt&gt;&lt;a href="http://wiki.open-esb.java.net/Wiki.jsp?page=ClusteringSupportForHTTPBindingComponent"&gt;http://wiki.open-esb.java.net/Wiki.jsp?page=ClusteringSupportForHTTPBindingComponent&lt;/a&gt;&lt;/tt&gt;.  But I will walk you through the process here.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To determine what the default port is for a binding component (in this case, the HTTP BC):&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Open the Admin console (in Netbeans, open Services tab, expand "Servers", right click on Glassfish, select "View Admin Console".  Unless you changed values, the username/password pair is "admin"/"adminadmin".&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Under "Common Tasks", expand "JBI", "Components", "sun-http-binding".&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Select the "Configuration" tab.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Second entry is "Default HTTP Port Number".  If you did not change this on installation, it will probably be 9080.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;If you choose to, you can always select an unused port number and hard-code it into the bindings before you deploy.  If you're like me, all you care about is being able to find out where the service is deployed!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, right-click on the composite application name in the "Projects" tab, select "Build", then again right-click on the application name and select "Deploy".  The project should deploy successfully.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To verify that the two services are correctly deployed, and assuming you used the soap:address Locations I used above, navigate to the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;&lt;a href="http://localhost:9080/worklistManager?wsdl"&gt;http://localhost:9080/worklistManager?wsdl&lt;/a&gt;&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;&lt;a href="http://localhost:9080/worklistApp?wsdl"&gt;http://localhost:9080/worklistApp?wsdl&lt;/a&gt;&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;where I have substituted the HTTP default port for my deployment.  Note you may have to view the page source to see the WSDL definition, but you should see both.  Note the &lt;tt&gt;worklistApp&lt;/tt&gt; has a single operation available (&lt;tt&gt;processLoadFailure&lt;/tt&gt;), while the &lt;tt&gt;worklistManager&lt;/tt&gt; has a number of operations related to the processing of tasks, as we might expect.  For example, &lt;tt&gt;GetTaskList&lt;/tt&gt;, &lt;tt&gt;RevokeTask&lt;/tt&gt;, &lt;tt&gt;CompleteTask&lt;/tt&gt;, and so on.  We will be calling these operations from the simple Java web-service client which we will create next.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Create a simple Java client&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All we'll be doing here is generating the minimal Java client necessary to exercise some operations on the Worklist Manager.  The steps involved are almost identical to those under the heading "Create a client for the web service" at my earlier post &lt;a href="http://wayne-adams.blogspot.com/2009/03/java-se-based-web-services.html"&gt;Java-SE-Based Web Services &lt;/a&gt;.  The only difference will be the URL of the web service, of course.  Because the WSDL definition of the Worklist Manager contains a URL to the TaskCommon.wsdl file (the latter is the abstract WSDL, and the former imports it and contains the necessary information to make the WSDL definition concrete), we will copy both files to a &lt;tt&gt;wsdl&lt;/tt&gt; directory in our client build.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Expand the NetBeans project directory for the composite application and retrieve the following files:&lt;/div&gt;&lt;tt&gt;&lt;/tt&gt;&lt;div&gt;&lt;tt&gt;     src/JbiServiceUnits/TutorialCompositeApp.wsdl&lt;/tt&gt;&lt;/div&gt;&lt;tt&gt;&lt;/tt&gt;&lt;div&gt;&lt;tt&gt;     src/JbiServiceUnits/TutorialWorklistApp/TaskCommon.wsdl&lt;/tt&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style=" ;font-family:-webkit-monospace;font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Copy these files into the &lt;tt&gt;wsdl&lt;/tt&gt; directory (under your Maven project &lt;tt&gt;src&lt;/tt&gt; directory).  Open the &lt;tt&gt;TutorialCompositeApp.wsdl&lt;/tt&gt; file and change the import path for &lt;tt&gt;TaskCommon.wsdl&lt;/tt&gt; to reflect the fact that it is now in the same directory as &lt;tt&gt;TutorialCompositeApp.wsdl&lt;/tt&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;&amp;lt;import namespace="http://jbi.com.sun/wfse/wsdl/TaskCommon" location="TaskCommon.wsdl"&amp;gt;&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, edit the soap:address, replacing &lt;tt&gt;${HttpDefaultPort}&lt;/tt&gt; with the actual port number (defaults to 9080, or use whatever value you hard-coded, if any).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then, instead of configuring a WSDL URL in your pom.xml file, configure a WSDL file as follows:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;           &amp;lt;configuration&amp;gt;&lt;br /&gt;             &amp;lt;wsdlFiles&amp;gt;&lt;br /&gt;               &amp;lt;wsdlFile&amp;gt;TutorialCompositeApp.wsdl&amp;lt;/wsdlFile&amp;gt;&lt;br /&gt;             &amp;lt;/wsdlFiles&amp;gt;&lt;br /&gt;             &amp;lt;packageName&amp;gt;com.example.webservice.service&amp;lt;/packageName&amp;gt;&lt;br /&gt;           &amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The client of course instantiates a different service and invokes different operations than in my previous post.  Here is an example Java client that exercises a couple of operations on the Worklist Manager:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;package com.example.webservice.client;&lt;br /&gt;&lt;br /&gt;import com.example.webservice.service.QueryType;&lt;br /&gt;import com.example.webservice.service.CasaService1;&lt;br /&gt;import com.example.webservice.service.TaskCommonPortType;&lt;br /&gt;import com.example.webservice.service.TaskFaultMsg;&lt;br /&gt;import com.example.webservice.service.TaskListType;&lt;br /&gt;import com.example.webservice.service.TaskType;&lt;br /&gt;&lt;br /&gt;public class WLMClient&lt;br /&gt;{&lt;br /&gt; public static void main(String[] args) throws TaskFaultMsg&lt;br /&gt; {&lt;br /&gt;   CasaService1 service = new CasaService1();&lt;br /&gt;   TaskCommonPortType port = service.getWorklistManagerPort();&lt;br /&gt;   System.out.println("Getting Task List:");&lt;br /&gt;   QueryType qt = new QueryType();&lt;br /&gt;   QueryType.Users users = new QueryType.Users();&lt;br /&gt;   users.getUser().add("john");&lt;br /&gt;   qt.setUsers(users);&lt;br /&gt;   QueryType.Groups groups = new QueryType.Groups();&lt;br /&gt;   groups.getGroup().add("CustomerServiceRep");&lt;br /&gt;   qt.setGroups(groups);&lt;br /&gt;   TaskListType tasks = port.getTaskList(qt, "john", 0, 100);&lt;br /&gt;   System.out.println("  Total record count: " + tasks.getTotalRecords());&lt;br /&gt;   System.out.println("  Returned record count: " + tasks.getReturnedRecords());&lt;br /&gt;   for (TaskType nextTask: tasks.getTask())&lt;br /&gt;   {&lt;br /&gt;     System.out.println("Task ID: " + nextTask.getTaskId() + "; title: " + nextTask.getTitle() + "; " +&lt;br /&gt;                        "Claimed by: " + nextTask.getClaimedBy() + "; Assigned to: " + nextTask.getAssignedTo());&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Build and run this application and you should see output like the following:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;C:\Users\wayne.adams\Blogger\GlassfishWLMJavaClient&gt;java -cp target\glassfishWLMJavaClient.jar com.example.webservice.client.WLMClient&lt;br /&gt;Getting Task List:&lt;br /&gt; Total record count: 0&lt;br /&gt; Returned record count: 0&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;In this case, there are no tasks, but we can create some by exercising the other service, the worklistApp service.  More on that in a subsequent post!&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-6134226774173117661?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/6134226774173117661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2009/03/tapping-into-glassfishesb-worklist.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6134226774173117661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/6134226774173117661'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2009/03/tapping-into-glassfishesb-worklist.html' title='Tapping into the GlassFishESB Worklist Manager'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_dNjU9gI9Js0/SclqUGPDTLI/AAAAAAAAABA/nMnMz-9N4KM/s72-c/compositeAppPreBuild.jpeg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-4600095691666628002</id><published>2009-03-24T10:34:00.000-07:00</published><updated>2009-03-24T12:42:50.741-07:00</updated><title type='text'>Java-SE-based Web Services</title><content type='html'>This isn't exactly late-breaking news, as Java SE6 has been out for a while, but the Standard Edition now includes support for non-trivial web-service development and deployment, no Java-EE application server necessary.  The purpose of this very quick introduction is to produce a working web service and a web service client, in as few lines of Java as possible, without relying on heavy infrastructure (namely, an IDE and/or an application server).  The output of this post will re-appear in subsequent posts, for example when I need a quick client to kick off a BPEL (Business Process Execution Language) process, or simply to exercise a web service to verify deployment.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Pre-requisites:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Java SE 6 installed:  &lt;tt&gt;&lt;a href="http://java.sun.com/javase/downloads/index.jsp"&gt;http://java.sun.com/javase/downloads/index.jsp&lt;/a&gt;&lt;/tt&gt;.  Be sure to get the JDK, not the JRE, as there are utilities you will need from the JDK.&lt;/li&gt;&lt;li&gt;Maven 2 installed:  &lt;tt&gt;&lt;a href="http://maven.apache.org/download.html"&gt;http://maven.apache.org/download.html&lt;/a&gt;&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;The following environment variables:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;tt&gt;JAVA_HOME&lt;/tt&gt;:  top-level Java SE 6 directory&lt;/li&gt;&lt;li&gt;&lt;tt&gt;M2_HOME&lt;/tt&gt;:  top-level Maven 2 directory&lt;/li&gt;&lt;li&gt;&lt;tt&gt;M2&lt;/tt&gt;:  &lt;tt&gt;$M2_HOME/bin&lt;/tt&gt; or &lt;tt&gt;%M2_HOME%\bin&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;&lt;tt&gt;MAVEN_OPTS:  -Xms256m -Xms512m&lt;/tt&gt; (optional)&lt;/li&gt;&lt;li&gt;&lt;tt&gt;PATH&lt;/tt&gt;:  &lt;tt&gt;$JAVA_HOME/bin:$M2:$PATH&lt;/tt&gt; or &lt;tt&gt;%JAVA_HOME%\bin;%M2%;%PATH%&lt;/tt&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Create a Web Service project and launch the service&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As you've guessed, I'm using Maven to build this service.  Maven will generate the project directory for you, so there's no need to create it first.  Just open a command prompt or shell in a development directory and enter the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;     mvn archetype:generate -DgroupId=com.example.webservice -DartifactId=JavaSEWebService&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;substituting your desired package name for &lt;tt&gt;groupId&lt;/tt&gt;.  The &lt;tt&gt;artifactId&lt;/tt&gt; will be the name of the project directory Maven will create in your current working directory.  You will be asked for an archetype, where the default is 15, or &lt;tt&gt;maven-archetype-quickstart&lt;/tt&gt;.  Select defaults by hitting "Enter" until Maven generates the project.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next, create a simple web service.  Note:  I prefer to start with a WSDL definition first, then generate the server and client-side artifacts from it, but for this quick example we'll go in the opposite direction, taking a small piece of business logic and exposing it as a service.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;cd&lt;/tt&gt; to the the &lt;tt&gt;groupId&lt;/tt&gt;-defined package under the source branch (&lt;tt&gt;./{artifactId}/src/main/java/...&lt;/tt&gt;) of the newly-created project.  There will be a class called &lt;tt&gt;App.java&lt;/tt&gt;.  We will ignore this class and create our own.&lt;div&gt;&lt;ol&gt;&lt;li&gt;Create a directory called &lt;tt&gt;service&lt;/tt&gt; and &lt;tt&gt;cd&lt;/tt&gt; into it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create a Java class called &lt;tt&gt;Tutorial.java&lt;/tt&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add a couple of methods; one called &lt;tt&gt;getHelloWorld&lt;/tt&gt; that takes no arguments and returns the String "Hello, World!" and a second one called &lt;tt&gt;getPersonalizedHelloWorld&lt;/tt&gt; that takes a String and returns a personalized greeting.&lt;div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Add a &lt;tt&gt;main&lt;/tt&gt; method, and in it, instantiate a &lt;tt&gt;Tutorial&lt;/tt&gt; and publish it, using the  &lt;tt&gt;javax.xml.ws.Endpoint&lt;/tt&gt; class, on your machine.  Annotate the class as a &lt;tt&gt;WebService&lt;/tt&gt; and the methods as &lt;tt&gt;WebMethod&lt;/tt&gt;s.&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;An example class is shown here:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;tt&gt;package com.example.webservice.service;&lt;br /&gt;&lt;br /&gt;import javax.jws.WebMethod;&lt;br /&gt;import javax.jws.WebService;&lt;br /&gt;import javax.xml.ws.Endpoint;&lt;br /&gt;&lt;br /&gt;@WebService&lt;br /&gt;public class Tutorial&lt;br /&gt;{&lt;br /&gt;public static void main( String[] args )&lt;br /&gt;{&lt;br /&gt;  Tutorial wsInstance = new Tutorial();&lt;br /&gt;  Endpoint.publish("http://localhost:8282/tutorial", wsInstance);&lt;br /&gt;}&lt;br /&gt;@WebMethod&lt;br /&gt;public String getHelloWorld()&lt;br /&gt;{&lt;br /&gt;  return "Hello, World!";&lt;br /&gt;}&lt;br /&gt;@WebMethod&lt;br /&gt;public String getPersonalizedHelloWorld(String yourName)&lt;br /&gt;{&lt;br /&gt;  return "Hello, " + yourName + "!";&lt;br /&gt;}&lt;br /&gt;}&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Next we'll modify the Maven "pom" (Project Object Model) file, first to use Java SE 6 (Maven defaults to 1.3) and secondly to specify the &lt;tt&gt;wsgen&lt;/tt&gt; Maven plugin.  &lt;tt&gt;wsgen&lt;/tt&gt; creates all the artifacts necessary to build and deploy the web service.  &lt;tt&gt;cd&lt;/tt&gt; into the project directory and open the &lt;tt&gt;pom.xml&lt;/tt&gt; file.  Add the following to your pom:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;finalName&amp;gt;tutorialWebService&amp;lt;/finalName&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;&lt;br /&gt;        &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;jaxws-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;executions&amp;gt;&lt;br /&gt;          &amp;lt;execution&amp;gt;&lt;br /&gt;            &amp;lt;goals&amp;gt;&lt;br /&gt;              &amp;lt;goal&amp;gt;wsgen&amp;lt;/goal&amp;gt;&lt;br /&gt;            &amp;lt;/goals&amp;gt;&lt;br /&gt;            &amp;lt;configuration&amp;gt;&lt;br /&gt;            &amp;lt;sei&amp;gt;com.example.webservice.service.Tutorial&lt;br /&gt;            &amp;lt;/sei&amp;gt;&lt;br /&gt;            &amp;lt;genWsdl&amp;gt;true&amp;lt;/genWsdl&amp;gt;         &lt;br /&gt;       &amp;lt;keep&amp;gt;true&amp;lt;/keep&amp;gt;&lt;br /&gt;            &amp;lt;/configuration&amp;gt;&lt;br /&gt;          &amp;lt;/execution&amp;gt;&lt;br /&gt;        &amp;lt;/executions&amp;gt;&lt;br /&gt;      &amp;lt;/plugin&amp;gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;Save and close the file.  From the project directory, enter &lt;tt&gt;mvn install&lt;/tt&gt;.  You should get a clean build.  Note that the name of the produced &lt;tt&gt;.jar&lt;/tt&gt; file is obtained from the &lt;tt&gt;finalName&lt;/tt&gt; element in the &lt;tt&gt;pom.xml&lt;/tt&gt; file.  Start the web service from the project-level directory with:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;java -cp target/tutorialWebService.jar com.example.webservice.service.Tutorial&lt;/tt&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;and verify that the service is available by retrieving the WSDL description in a browser.  Append &lt;tt&gt;?wsdl&lt;/tt&gt; to the endpoint URL you defined in your Java class, in this case&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;http://localhost:8282/tutorial?wsdl&lt;/tt&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Note that depending on the browser you are using, you may need to view the page source to see the WSDL description.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Create a client for the web service&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We'll create a new Maven project for the client.  Open another command prompt or shell in your development directory (again, no need to create the project directory, as Maven will do this for you), and enter the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;mvn archetype:generate -DgroupId=com.example.webservice -DartifactId=JavaSEWebServiceClient&lt;/tt&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;substituting your desired package name for &lt;tt&gt;groupId&lt;/tt&gt;.  The &lt;tt&gt;artifactId&lt;/tt&gt; will be the name of the project directory Maven will create in your current working directory.  As for the web service example, you will be asked for an archetype, where the default is 15, or &lt;tt&gt;maven-archetype-quickstart&lt;/tt&gt;.  Select defaults by hitting "Enter" until Maven generates the project.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;tt&gt;cd&lt;/tt&gt; into the project directory, given by the value you supplied for &lt;tt&gt;artifactId&lt;/tt&gt; (for this example, &lt;tt&gt;JavaSEWebServiceClient&lt;/tt&gt;).  Open the &lt;tt&gt;pom.xml&lt;/tt&gt; (Maven Project Object Model) file.  Add the following to the POM; &lt;tt&gt;wsimport&lt;/tt&gt; is used to generate client stubs for your web service:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;tt&gt;  &amp;lt;build&amp;gt;&lt;br /&gt;   &amp;lt;finalName&amp;gt;tutorialWebServiceClient&amp;lt;/finalName&amp;gt;&lt;br /&gt;   &amp;lt;plugins&amp;gt;&lt;br /&gt;     &amp;lt;plugin&amp;gt;&lt;br /&gt;       &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;       &amp;lt;configuration&amp;gt;&lt;br /&gt;         &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;&lt;br /&gt;         &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;&lt;br /&gt;       &amp;lt;/configuration&amp;gt;&lt;br /&gt;     &amp;lt;/plugin&amp;gt;&lt;br /&gt;     &amp;lt;plugin&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;jaxws-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;         &amp;lt;executions&amp;gt;&lt;br /&gt;            &amp;lt;execution&amp;gt;&lt;br /&gt;              &amp;lt;goals&amp;gt;&lt;br /&gt;                &amp;lt;goal&amp;gt;wsimport&amp;lt;/goal&amp;gt;&lt;br /&gt;              &amp;lt;/goals&amp;gt;&lt;br /&gt;              &amp;lt;configuration&amp;gt;&lt;br /&gt;                &amp;lt;wsdlUrls&amp;gt;&lt;br /&gt;                  &amp;lt;wsdlUrl&amp;gt;http://localhost:8282/tutorial?wsdl&amp;lt;/wsdlUrl&amp;gt;&lt;br /&gt;                &amp;lt;/wsdlUrls&amp;gt;&lt;br /&gt;            &amp;lt;packageName&amp;gt;com.example.webservice.service&lt;br /&gt;            &amp;lt;/packageName&amp;gt;&lt;br /&gt;              &amp;lt;/configuration&amp;gt;&lt;br /&gt;            &amp;lt;/execution&amp;gt;&lt;br /&gt;         &amp;lt;/executions&amp;gt;&lt;br /&gt;       &amp;lt;/plugin&amp;gt;&lt;br /&gt;   &amp;lt;/plugins&amp;gt;&lt;br /&gt; &amp;lt;/build&amp;gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Save and close the file.  Note that you are directing Maven to obtain the WSDL description via the URL we used earlier to verify that the web service was correctly deployed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Create a simple web service client:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;tt&gt;cd&lt;/tt&gt; to the &lt;tt&gt;groupId&lt;/tt&gt;-defined package under the source branch (&lt;tt&gt;./{artifactId}/src/main/java/...&lt;/tt&gt;) and create a &lt;tt&gt;client&lt;/tt&gt; directory; &lt;tt&gt;cd&lt;/tt&gt; into this directory.&lt;/li&gt;&lt;li&gt;Create a Java class called &lt;tt&gt;TutorialWebServiceClient.java&lt;/tt&gt;.&lt;/li&gt;&lt;li&gt;Create a &lt;tt&gt;main&lt;/tt&gt; method which gets a reference to the tutorial web service and exercises its two operations.  For example:&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;package com.example.webservice.client;&lt;br /&gt;&lt;br /&gt;import com.example.webservice.service.Tutorial;&lt;br /&gt;import com.example.webservice.service.TutorialService;&lt;br /&gt;&lt;br /&gt;public class TutorialWebServiceClient&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    TutorialService service = new TutorialService();&lt;br /&gt;    Tutorial port = service.getTutorialPort();&lt;br /&gt;    System.out.println("Calling getHelloWorld(); returns '" + port.getHelloWorld() + "'");&lt;br /&gt;    System.out.println("Calling getPersonalizedHelloWorld(\"Bob\"); returns '" +&lt;br /&gt;                       port.getPersonalizedHelloWorld("Bob") + "'");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Note that the wsimport utility will create an interface named &lt;tt&gt;TutorialService.java&lt;/tt&gt; and a class named &lt;tt&gt;Tutorial.java&lt;/tt&gt;.  It will do this before the client is compiled, but if you want to see the stub classes before you build the client, just execute &lt;tt&gt;mvn install&lt;/tt&gt; before creating the client.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The web service interface name is obtained by prepending the package name from the POM to the name of the web service &lt;tt&gt;portType&lt;/tt&gt; from the WSDL description, and the name of the service itself is the &lt;tt&gt;serviceName&lt;/tt&gt; from the WSDL description, if you want to reference the classes before they are generated by &lt;tt&gt;wsimport&lt;/tt&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also note that the endpoint URL of the web service was embedded into the generated client-side classes by the setup in the Maven POM file, as I mention above.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From the project directory, enter&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;mvn install&lt;/tt&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This will generate the client-side stubs you need in your client, followed by the client itself.  You can safely ignore the &lt;tt&gt;"[INFO] Nothing to do, no WSDL found!"&lt;/tt&gt; log message; it is misleading and if you get a &lt;tt&gt;"BUILD SUCCESSFUL"&lt;/tt&gt; message, then all is well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Test the client and the web service with:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;        java -cp target/tutorialWebServiceClient.jar  com.example.webservice.client.TutorialWebServiceClient&lt;/tt&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You should see output like the following:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;tt&gt;        Calling getHelloWorld(); returns 'Hello, World!'&lt;/tt&gt;&lt;/div&gt;&lt;tt&gt;&lt;/tt&gt;&lt;div&gt;&lt;tt&gt;        Calling getPersonalizedHelloWorld("Bob"); returns 'Hello, Bob!'&lt;/tt&gt;&lt;/div&gt;&lt;div&gt;       &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You now have a working web-service/client pair, which will come in handy in future entries as we explore Flex web-service clients, BPEL and JBI.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-4600095691666628002?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/4600095691666628002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2009/03/java-se-based-web-services.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4600095691666628002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/4600095691666628002'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2009/03/java-se-based-web-services.html' title='Java-SE-based Web Services'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6625574524734878463.post-8521131247536553690</id><published>2009-03-24T09:48:00.000-07:00</published><updated>2009-03-24T10:31:49.213-07:00</updated><title type='text'>Introductions</title><content type='html'>Hello, everyone!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before I start posting, I should tell you a little about where I'm going.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My main software interest is enterprise Java, and more specifically business process modeling, either on top of Java or a slightly higher level of abstraction.  So I'm really interested in Web Services, Business Process Execution Language (BPEL), Java Business Integration (JBI), and (at this time, to a lesser extent) the Service Component Architecture (SCA).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm much more practical than theoretical.  I like to get things working first and ruminate later.  I like tutorials!  I like finding good ones, and I like creating them, especially when it seems there's a hole in the tutorial offerings.  Most of what you see posted here will be in the form of tutorials.  Some of them will be really simple, as they will serve as building blocks for subsequent posts that you'll hopefully find more interesting.  For example, sometimes it's handy to have a 25-line Java-SE-based web service, or an even briefer web service client, to test an application in development (in fact, this will be the topic of my next post).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With that, I hope you enjoy what's forthcoming and that you also find it useful!  Ciao!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wayne&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6625574524734878463-8521131247536553690?l=wayne-adams.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wayne-adams.blogspot.com/feeds/8521131247536553690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wayne-adams.blogspot.com/2009/03/introductions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/8521131247536553690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6625574524734878463/posts/default/8521131247536553690'/><link rel='alternate' type='text/html' href='http://wayne-adams.blogspot.com/2009/03/introductions.html' title='Introductions'/><author><name>Wayne Adams</name><uri>http://www.blogger.com/profile/09270397008640035520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_dNjU9gI9Js0/TAf5WqJhkRI/AAAAAAAAABY/IoaFkVuoHJg/S220/headShot_700x700.jpeg'/></author><thr:total>0</thr:total></entry></feed>
