Monday, March 28, 2011

Visiting a Foreign Land

This past week I took a trip to a foreign country, MacLand. I have many friends who either live there or are frequent visitors and they all love it, despite the very high cost of living there. I decided it was time to see what all the fuss was about.

When I first got off the plane and opened up my new 13" MacBook Pro, it was welcoming. I was through security and on the internet in almost no time at all. However, it didn't take long for me to become discombobulated. The customs here are strange, like the fact that they drive on the left side of the road here with their window controls and they don't leave the menus at the tables as I am used to. I'm obviously going to have to learn the local dialect. What is a "Finder" or "Preview" anyway, and what are the funny symbols (arrows and cloverleafs?) I am seeing on many of the menus? And my instincts as to what to do in any given situation tend to be wrong. I am worried that I'll commit a serious faux pas and end up in trouble. Well, I guess I'll just have to trust that my friends that live here will bail me out if that happens.

To achieve some level of comfort, I installed Chrome and Emacs. It's always nice to see a familiar face when abroad. In the lobby of my MacBook there are a number of brochures of local activities, like going on Safari, that I suppose I should try out. When I get up some courage, I guess I will try to branch away from the strictly familiar.

So why did I decide to take this journey? Well some years ago, there was a revolution in MacLand, and the new government, OS X, was based on Unix. I have long preferred Unix to other approaches, but historically, Unix run places were not places for individuals to dwell, unless they had a strong Do It Yourself mentality. My own hobby interests lie elsewhere, I just want my infrastructures to work. My couple personal trips to Unix resulted in more hassles than it was worth to me. With OS X, MacLand promised the power of Unix while also providing a nice friendly infrastructure that just works.

Between this promise, the numerous friends I have who love it, and the fact that Ruby on Rails is supposed to be easier in MacLand, I decided it was time to take the trip. We'll see how I like it, but so far I am cautiously optimistic that this will be a good land.  (as long as there are no betrayals)

Monday, March 14, 2011

When Does X Not Equal X and Other Oddities

In many programming languages:
  • For what value of x is the condition (x == x) false?
  • For what integer value of y is the condition (y < 0) && (-y < 0) true?
i.e. define x on line 3 and y on line 10  in the following Java code sample so that lines 7 and 12 execute:
  1 public class Odd {
  2   public static final void main(String[] arg) {
  3     // define x here 
  4     if (x == x) { 
  5       System.out.printf("Reflexive%n"); 
  6     } else { 
  7       System.out.printf("Not Reflexive%n"); 
  8     } 
  9  
 10     int y = 0; // change 0 to something else
 11     if (y < 0 && -y < 0) { 
 12       System.out.printf("How can they both be negative?%n"); 
 13     } 
 14   } 
 15 }
In SQL:
  • What database value x is the condition (x = x) false?
  • What about values y and z such that ((y = z) OR (y != z)) is false?











These next few lines are intentionally left blank, in case you wan to think about these before viewing possible answers.











Answers
In mathematics, one of the properties of the equality operator is that it is reflexive. It turns out that the Java (and almost every other language) equality operator does not have this property.  If you put the following on line 3:
double x = 0.0/0.0;
and run the program, it'll print out "Not Reflexive".  Why is this?  Well, according to the IEEE standard 754, 0/0 = NaN. What is NaN?  Well, it is not a number, corresponding to the mathematical concept of an indeterminate number. Because it could be any number, the powers that be decided that NaN != NaN.

So what about the second example? Well, in a 2's complement system of encoding numbers, there is room for one more negative number than positive numbers. (e.g. a 16 bit signed value encodes the values -32,768 to 32,767). What this means is that if you try to negate the most negative number (e.g. -32,768), the corresponding positive number won't fit in the memory location, and so you actually get the same number back. This means an answer to line 10 is:
int y = Integer.MIN_VALUE;

What about the SQL questions? Well, it turns out that SQL treats NULL like NaN, i.e. it is an indeterminate value. SQL goes even further than Java.  Not only is the expression (NULL = NULL) result in false, but (NULL != NULL) also results in false. Well, actually that's not quite true. SQL uses three-valued logic, and so both the expressions actually evaluate to undefined, but undefined is treated as false when it comes to matching rows.

Why does this matter?
Have you ever written code where it is assumed that if two numbers have the same value they will be equal? How about that Math.abs() will always return a negative value? Eric Lippert had a blog post showing how this assumption can cause the standard sort functions to fail.

I personally have generated two reports by running queries like:
SELECT * FROM Table WHERE columnA = columnB -- report 1
SELECT * FROM Table WHERE columnA != columnB -- report 2
and then was mightily confused when, at some point during the analysis, I realized that there were rows in my database table that weren't in either report.

These may feel like nitpicky details that only show up on those gotcha type quizzes. However, not understanding these details can lead to bugs in your code. If you are going to be an expert programmer, you have to know and understand the rough edges of your language.

Monday, March 7, 2011

Crop and Upload Image - Server Side

Previously I showed some HTML and JavaScript for cropping and uploading an image. Here is what I did on the server side to support this.

First I make sure I had rails 3 installed, configured for HAML and jquery. I also download the jqueryui and jcrop javascript and css files and add them to my project.  Then, I use the rails scaffolding functionality to get started:

ruby script\rails generate scaffold image content:binary width:integer height:integer name:string

After running:

rake db:migrate

I have a database table for storing an uploaded image, including the binary content, the height and width of the image and a name. Now that I have a place to store the image, I need to modify the generated web pages, so I can upload it.

Since I prefer HAML, the first thing that I do is rename the two erb files that I need to change: views/layouts/applications.html.erb to views/layouts/applications.html.haml and app/views/images/_form.html.erb to app/views/images/_form.html.haml.  The applications.html file is the template for all the pages, and I need to modify that to allow pages to add their own javascript into the header. _form.html is the partial that is used for both uploading new images and editing images.

Converting the applications.html file from erb to haml is just a straightforward transformation. Here is what it looks like when I am done:
  1 !!! 
  2 %html 
  3   %head 
  4     %title Image Upload 
  5     = stylesheet_link_tag :all 
  6     = javascript_include_tag :defaults 
  7     = csrf_meta_tag 
  8     = yield :head 
  9   %body 
 10     = yield
The only real line of note is the named yield on line 8. This is what will allow me to insert custom stylings and javascript into specific pages.

The only thing left is to rewrite _form.html.haml so that it generates HTML and Javascript like discussed in the client side post. Here is what this looks like.
  1 - content_for :head do 
  2   = stylesheet_link_tag 'jquery.Jcrop' 
  3   = javascript_include_tag  'jquery.Jcrop.min'
  4   %style 
  5     -# insert styling described in client post here 
  6   :javascript 
  7     // insert javascript described in client post here
  8 = form_for(@image) do |f| 
  9   - if @image.errors.any? 
 10     #error_explanation 
 11       %h2 
 12         = pluralize(@image.errors.count, "error") 
 13         prohibited this image from being saved:
 14       %ul 
 15         - @image.errors.full_messages.each do |msg|
 16           %li= msg 
 17   .field 
 18     = f.label :name 
 19     %br 
 20     = f.text_field :name 
 21  
 22   Drag and drop image here: 
 23   #cropWidget{:width=>400, :height=>400} 
 24     #surface 
 25     %canvas#canv1{:width=>400, :height=>400} 
 26  
 27   = f.hidden_field :content64 
 28   Uploaded image is here: 
 29   %canvas#canv2{:width=>200, :height=>200} 
 30   .field 
 31     = f.label :width 
 32     %br 
 33     = f.text_field :width, :readOnly=>true 
 34   .field 
 35     = f.label :height 
 36     %br 
 37     = f.text_field :height, :readOnly=>true 
 38   .actions 
 39     = f.submit :id=>"imageSubmit", :onClick=>"uploadSelection();", :disabled=>true;
I left out the specific CSS styles and JavaScript as they are described in the previous post. Notice that lines 1-7 are inserted into the head of the template as described by yield :head on line 8 of the application.html.haml file above. Lines 9-16 are the boilerplate error handling that was generated by the scaffold command. The remainder just generates the HTML for displaying the image and for entering the name of the image.

We are now almost, but not quite, done. If you notice the field that we are storing the image content in is content64, while the database column for the binary data is just called content. We need to take the base64 encoding of the image that is sent over the wire as part of the HTML POST and decode it to binary before saving in the database. To do that, we just need to add new methods in our app/models/image.rb Image class.
  1 require "base64" 
  2 class Image < ActiveRecord::Base 
  3   def content64 
  4     return nil unless content 
  5     return "data:image/png;base64," + Base64.encode64(content); 
  6   end 
  7  
  8   def content64=(c64) 
  9     index = c64.index(','); 
 10     self.content = Base64.decode64(c64[index..-1]); 
 11   end 
 12 end
This way when the content64 attribute is assigned in our controller class, it'll actually write the binary data to the content field so it can be saved to the database. The only clever part of this is that the content64 data that is passed from the HTML form has the initial string "data:image/png;base64,".  Lines 9-10 calculate where this prefix ends and just decodes the remainder of the string. Line 5 adds this prefix back on to the encoded binary content.

Other Work
So the above will allow you to upload a new image that has been cropped and save it to the database. However, to be able to view that image or edit it, more work is needed. Probably the most important thing to do is to add a new action which will return the image's binary content. The url for this action can be used in the src attribute of <img> tags. The other scaffold generated pages for viewing and listing the uploaded images are then modified to display the image rather than showing the binary content. The last step is to modify the javascript described previously to check if an image already exists (i.e. we are editing an existing uploaded image rather than uploading a new image), and preload that. Since this post has gone on long enough, I will leave all of those details as an exercise for the reader.

Monday, February 28, 2011

The Problem with Component Based Web Architectures

Imagine the following scenario:
  1. You browse to a web site and log in.
  2. After doing whatever you needed to do, you log out.
  3. You keep your browser tab (which is now sitting at a login page) open.
  4. The next day you return to this browser tab and enter your username and password.
Assuming that you enter your username and password correctly, I think it is a safe assumption that the behavior you would expect is for the site to log you in. Anything else could be considered a bug.

Why do I bring up such a simple scenario?  Because if the website was written using JSF and they just used out of the box settings (for example what you would get if you use seam-gen with a Seam application), the above scenario will result in an error!

Component Web Architecture
Both JSF and ASP.NET use a component based web architecture. What this means is that the developer's markup language, whether it is aspx, jsp, or facelets, doesn't directly define HTML. Rather it describes a tree of components. The HTML is generated after the component tree has been built and populated, either by asking the components to render themselves, or by having a separate renderer that traverses the component tree.

Advantages
Component based architecture attempts to leverage the fact that almost all modern programming languages are object oriented. Components are just objects. By using a paradigm that most developers are familiar with the hope is that it'll be easy to use, maintain, extend, etc.

Problem
As you know, the web is stateless. The browser and web server interact by sending messages back and forth. However, the client (browser) and server are two completely disconnected entities. The conversation between them might not actually even be between two entities. A user might save a hyperlink from one page, and then follow the link from a different browser on an entirely different computer. Because of load balancing, or server restarts, the server that handles one message in a conversation isn't necessarily the same as the one that handled the previous message. And even if its the same server, the server might be in a very different state due to handling requests from other clients or other external changes like database state changes.

This presents a myriad of challenges to web developers. Web frameworks provide tools to overcome the above difficulties and still write useful applications. JSF and ASP.NET protect the developers from all of the ugliness through their use of components. Through clever use of cookies, hidden form variables, and session information, these frameworks provide the illusion that you have objects which persist from one page request to the next and that links, form fields, and buttons change the state and or perform actions on these objects.

The problem is that the long lived object model is a leaky abstraction over the reality of stateless messages being sent back and forth. My previous complaints about ASP.NET are caused by trying to paper over this leak.

Component Web Mismatch
To correctly process any form submission (for example login), the first thing the webserver has to do is recreate the exact same component tree structure that was used to generate the page. The appropriate components then get loaded with whatever form data data was submitted, and the component corresponding to the button that was clicked then can have its action called. The challenge is ensuring that the component tree structure that was used when the page was created is the EXACT SAME as the component structure on the form submission. For the simple cases, this is easy. But imagine that the component tree is based on a database query (e.g. listing of items on sale). It's possible that the database has changed between page load and form submission (e.g. items sold to another user). If you naively build the component tree the same way you did originally (e.g. by iterating over results from database), you will get a different component tree which can cause all types of wonky behavior. For example if the user tried to buy the 5th item on the list, they may end up purchasing the wrong item, since the 5th item they saw on the screen isn't the same as the 5th item currently returned by the database.

To solve this problem, when a form is created JSF saves the component tree so that it can be recreated when the form is submitted. This can be stored in a hidden field in the form sent to the client, but since this can be quite large it typically isn't done. By default, JSF saves this in a server session variable. However, if the session times out, this data is lost, and you can no longer recreate the state. This is the cause of the javax.faces.application.ViewExpiredException that happens in the scenario at the top of this post.

Solution
We need web frameworks that don't try to recreate the exact same state on two different requests. There are some very smart people who have (and continue to) work on JSF and ASP.NET. The fact that their solutions are so complex and still tend to drop people through the cracks (based on the questions out there on message boards) is indicative that the approach is flawed, rather than just the implementations. Frameworks like Ruby on Rails which ease the process of writing web apps without hiding the fact that each web request is its own independent action are the long term future.

Monday, February 21, 2011

Crop and Upload Image - Client Side

I want to be able to extend my moving icon program to allow a user to upload their own icon. However, I want to give the user the ability to crop the image so they just upload the portion that they want. Here is how I do that.

Technologies Used
I use the HTML 5 file capabilities to upload the image to the browser. I use the Jcrop plugin to jQuery to actually specify the crop region. I also leaned heavily on another demo I found on the web (http://www.pandamatak.com/people/anand/blog/2010/11/clientside_image_crop_and_then.html) to figure out how to do it, though I have tweaked it some.

HTML
First you need a place to drag the image too.
<div id='cropWidget' height='400' width='400'>  
  <div id='surface'></div>  
  <canvas id='canv1' height='400' width='400'></canvas>  
</div>
The surface is where an image can be dragged from your file system and dropped to. canv1 is the canvas object that will handle image manipulation.

Next we need a place to show the cropped portion of the image.
<canvas id='canv2' height='200' width='200'></canvas>  
The only other portion is a control to put the content, two text controls which will show the size of the cropped image, and a button to upload the image.
<input id="content64" name="content64" type="hidden" />
<div class='field'>  
  <label for="width">Width</label>  
  <br /> 
  <input id="width" name="width" readOnly="true" size="5" type="text" />  
</div>  
<div class='field'>  
  <label for="height">Height</label>  
  <br /> 
  <input id="height" name="height" readOnly="true" size="5" type="text" />  
</div>  
<div class='actions'>  
  <input disabled="disabled" id="imageSubmit" name="commit" 
         onClick="uploadSelection();" type="submit" value="Create Image" />  
</div>
There are a couple of things to note here. First the "readOnly" attribute on the text inputs. The user won't be entering the width and height, they will be calculated by JavaScript. Also, the imageSubmit button is disabled. It does not become enabled until an image has been uploaded. And then on click, the JavaScript function uploadSelection will be called.

CSS
The surface element and the canv1 element need to be superimposed on top of each other for this to look right. This CSS accomplishes this, plus adds a little bit of styling.
<style>  
  #cropWidget {position:relative; width 400px; height:400px; padding:5px;} 
  #surface {position:absolute; top:0px; left: 0px; background:blue;  
            width:400px; height:400px; z-index:100; opacity: 0.50;} 
  #canv1 {position:absolute; top:0px; left: 0px; border:1px solid blue; 
          width:400px; height:400px;} 
  #canv2 {position:relative; border:1px solid yellow; width:200px; height:200px;} 
</style>

JavaScript
Here is all of the javascript. I will explain the parts below.
  1 var cropWidget = document.getElementById('cropWidget');
  2 var surface = document.getElementById('surface');
  3 var canv1 = document.getElementById('canv1');
  4 var canv2 = document.getElementById('canv2');
  5 var imageSubmit = document.getElementById('imageSubmit');
  6 var ctx1 = canv1.getContext('2d');
  7 var ctx2 = canv2.getContext('2d');
  8  
  9 function resize(comp, width, height) { 
 10   comp.width = width; 
 11   comp.height = height; 
 12   comp.style.width = img.width + 'px'; 
 13   comp.style.height = img.height + 'px';
 14 } 
 15  
 16 function displayImage(img) { 
 17   resize(canv1, img.width, img.height); 
 18   resize(surface, img.width, img.height); 
 19   resize(cropWidget, img); 
 20   while(surface.childNodes[0]) surface.removeChild(surface.childNodes[0]);
 21   surface.appendChild(img); 
 22   ctx1.drawImage(img, 0, 0, img.width, img.height);
 23   jQuery("#" + img.id).Jcrop({ aspectRatio: 1, onSelect: cropImage });
 24 } 
 25  
 26 function loadImg(imgFile) { 
 27   if (!imgFile.type.match(/image.*/)) return;
 28   var img = document.createElement("img"); 
 29   img.id = "pic"; 
 30   img.file = imgFile; 
 31  
 32   var reader = new FileReader();
 33   reader.onload = function(e) { 
 34     img.onload = function() { displayImage(img); }; 
 35     img.src = e.target.result; 
 36     resize(canv2, 200, 200);
 37   }; 
 38   reader.readAsDataURL(imgFile); 
 39 } 
 40  
 41 function cropImage(c) { 
 42   var w = c.x2-c.x; 
 43   var h = c.y2-c.y; 
 44   resize(canv2, w, h); 
 45   ctx2.drawImage(canv1, c.x, c.y, w, h, 0, 0, w, h);
 46   $("#width").val(w); 
 47   $("#height").val(h); 
 48   imageSubmit.disabled = false; 
 49 } 
 50  
 51 function uploadSelection() { 
 52   var imgData = document.getElementById('canv2').toDataURL("image/png"); 
 53   $("#content64").val(imgData); 
 54   alert("This would've upload your image to a server, if there was one."); 
 55   return false;
 56 } 
 57  
 58 surface.addEventListener("dragover", function(e) {e.preventDefault();}, true); 
 59 surface.addEventListener("drop", function(e) {e.preventDefault();  
 60                                            loadImg(e.dataTransfer.files[0]);},
 61                          true); 
 62 ctx1.fillText("Drop image here", 60, 100); 
 63 ctx2.fillText("Preview", 60, 100);
Lines 1-5 just create variables for the various HTML objects, and 6-7 get the drawing contexts for the canvases. resize (lines 9-14) is a helper method for changing the size of an HTML component. Lines 12-13 resize the display of the component, while lines 10-11 resize its internal structures, if the component is a canvas. displayImage (lines 16-24) first resizes the HTML components to fit the image. Then any previous image is removed from the surface. Then the image is added to the surface and drawn to the canvas. Finally jcrop is called to enable cropping of this image, calling the function cropImage when a region is selected. cropImage (lines 41-49) resizes canv2 and then draws the portion of the image onto this canvas. Then it stores the width and height into the HTML width and height components and enables the submit button.

Jumping to the end, lines 62-63 put some text onto the canvases. Lines 58-61 enable the drag and drop functionality, setting loadImg as the function that is called when a file is dropped. loadImg (26-39) first ensures that it is actually an image being dropped. Then it creates an HTML <img> tag to contain the image. Line 32 creates an HTML5 FileReader and line 38 reads the file that was dropped. The function defined on lines 33-37 is called when the file has been read. Line 35 sets the source of the <img> tag that was created a few lines above. Line 34 calls the displayImage function once the image has been loaded fully by the browser, and line 38 resizes the crop canvas to a fixed size of 200x200, which also has the effect of erasing any previous image drawn on it.

That is basically the extent of the drag and drop functionality. The only remaining method is uploadSelection (lines 51-56) which is called when the "Create Image" button is clicked. This function gets the base64 encoding of the cropped image and copies it to the HTML element content64 where, if this were actually connected to a server, it would be posted as part of the form back to the server.

Demo
Here is what all of this looks like.

Image Cropper

Drag and drop image here:

Cropped image is here:

Monday, February 14, 2011

Unit Testing - the Ugly

So you've weighed the benefits and drawbacks to unit testing and decided to do some unit testing. Now you will learn a rarely talked about fact, unit testing is ugly.

A unit test is composed of 3 steps:
  1. Set up state
  2. Execute component
  3. Validate state
For any type of complex components, the code for setting up the state and validating the state can be quite large and tedious. If you look at a set of tests for a single component you'll also find that they tend to be very redundant.

To a certain extent, there is nothing you can do. Comprehensive tests, by necessity, will contain a lot of data and a lot of validation. If you are a believer in the DRY principle, the redundancy will drive you batty. Through standard refactoring ideas you can pull out the common setup and validation code into their own methods and helper classes. However, there are two catches.

Almost the Same
Each of your unit tests are presumably testing different aspects of your component. As such the state will have to be different for each test. And the validation steps will be different for each test. Trying to parameterize your extracted setup and validation methods to support your scenarios can be as challenging a design problem as any portion of your application proper.

Self Contained
One goal of unit testing is that each test is self descriptive. That way when the testFrombulatorWithNull fails you can quickly narrow down the problem. Unfortunately, if you have refactored your unit tests according to the DRY principle, the setup/validation information won't be solely in the specific test method. You'll have to understand how the helper methods and classes interact so you can understand the test so you can understand what went wrong.

Example
Imagine we modify the PhoneFormatter example from before to now take a formatting string in its constructor. Now, we have a lot more cases to test, which might look something like this:
  1 import static org.junit.Assert.*;
  2 import org.junit.Test; 
  3 import org.junit.Before; 
  4  
  5 public class PhoneFormatterTest {
  6  
  7   private PhoneFormatter mFormatter; 
  8  
  9   @Test public void testWithSpace() {
 10     mFormatter = new PhoneFormatter("(###) ###-####"); 
 11     check("(757) 555-1234", "7575551234"); 
 12     check("(757) 555-1234", "17575551234"); 
 13     check("555-1234", "5551234"); 
 14     check("911", "911"); 
 15   } 
 16  
 17   @Test public void testNoSpace() {
 18     mFormatter = new PhoneFormatter("(###)###-####"); 
 19     check("(757)555-1234", "7575551234"); 
 20     check("(757)555-1234", "17575551234"); 
 21     check("555-1234", "5551234"); 
 22     check("911", "911"); 
 23   } 
 24  
 25   @Test public void testNoParen() {
 26     mFormatter = new PhoneFormatter("###-###-####"); 
 27     check("757-555-1234", "7575551234"); 
 28     check("757-555-1234", "17575551234"); 
 29     check("555-1234", "5551234"); 
 30     check("911", "911"); 
 31   } 
 32  
 33   @Test public void testDots() {
 34     mFormatter = new PhoneFormatter("###.###.####"); 
 35     check("757.555.1234", "7575551234"); 
 36     check("757.555.1234", "17575551234"); 
 37     check("555.1234", "5551234"); 
 38     check("911", "911"); 
 39   } 
 40  
 41   /* Test more formats here */ 
 42  
 43   private void check(String expected, String number) {
 44     checkImpl(expected, number); 
 45     checkImpl(expected, "9" + number); // check leading 9 
 46   } 
 47  
 48   private void checkImpl(String expected, String number) {
 49     PhoneNumber pn = new PhoneNumber(number);
 50     assertEquals(expected, mFormatter.format(pn)); 
 51   } 
 52 }
As you can see the unit test is now a lot longer. And this is for testing a very simple class that takes a very simple input and has a very simple output. Imagine how much uglier this would be if PhoneFormatter took more complex objects as parameters to its methods and returned objects?

Even with such a simple class under test there is a ton of duplication, each unit test method is almost identical to each other. This has the usual problems of cut-and-paste. For example, if you want to add international numbers to your test, you need to make sure you add this to each and every method, and it could be easy to miss one.

There's also the possibility for confusion. Notice the method check (lines 43-46) checks numbers both with and without a leading 9. A future developer, if they don't carefully follow the code, may not expect this, making it unclear why a particular test fails. In this case, it is probably worth this extra indirection to cut the size of the test class almost in half, but you are bound to come up with examples that aren't so clear.

Conclusion
Obviously, the goal to find the happy medium where your test code is structured to minimize redundancy while still maximizing readability, just like writing any other code. However, the goals of unit testing (test component, find bugs, show example of how component is used) are not the same as writing other code. This means that you may make different decisions as part of your design trade-offs than you would elsewhere in code. When combined with the fact that comprehensive unit tests can't be concise (otherwise they wouldn't be comprehensive), it is likely that at least some of your unit tests will be ugly.

Monday, February 7, 2011

Java Web Services Without Code Generation

With Java 6 it is possible to use annotations to create web services and to create clients to consume those web services without using 3rd party libraries like Axis. If you have control of both the server and the client code you can easily write these pieces without any code generation tools. Here is an example of that.

Server
To create your web service, perform the following steps.
  1. Create a directory for the project.  (mkdir server;  cd server)
  2. Create a package for your code.  (mkdir hello)
  3. Create the interface for the web service.  (hello/HelloPort.java)
      1 package hello; 
      2  
      3 import javax.jws.WebService; 
      4  
      5 @WebService 
      6 public interface HelloPort {
      7   String talk(String msg); 
      8 }
  4. Create the web service.  (hello/Hello.java)
      1 package hello; 
      2  
      3 import javax.jws.WebService; 
      4 import javax.xml.ws.Endpoint; 
      5  
      6 @WebService 
      7 public class Hello implements HelloPort {
      8   public String talk(String msg) { 
      9     return "Hello, " + msg; 
     10   } 
     11  
     12   public static void main(String[] argv) {
     13     Endpoint.publish("http://localhost:8080/Hello", new Hello()); 
     14   } 
     15 }
  5. Compile your code.  (javac hello/Hello.java)
  6. Run the server.  (java hello.Hello)
Now that your server is running, you can view the wsdl by going to http://localhost:8080/Hello?wsdl. If you wanted to, you could've skipped the step where you created the HelloPort interface (and had Hello not implement any interface), but we will use HelloPort in the client.

Client
To create a client that consumes this web service:
  1. Create a directory for the project.  (mkdir client;  cd client)
  2. Create a directory for the Hello interface.  (mkdir hello)
  3. Copy the interface.  (cp ../server/hello/HelloPort.class hello)
  4. Create the client code (Client.java)
      1 import java.net.URL; 
      2 import javax.xml.namespace.QName; 
      3 import javax.xml.ws.Service; 
      4 import hello.HelloPort; 
      5  
      6 public class Client {
      7  
      8   static class HelloService extends Service {
      9     public HelloService() throws Exception {
     10       super(new URL("http://localhost:8080/Hello?wsdl"), 
     11             new QName("http://hello/", "HelloService")); 
     12     } 
     13     public HelloPort getHelloPort() { 
     14       return super.getPort(new QName("http://hello/", "HelloPort"), 
     15                            HelloPort.class); 
     16     } 
     17   } 
     18    
     19   public static void main(String[] args) throws Exception {    
     20     HelloService hs = new HelloService(); 
     21     HelloPort port = hs.getHelloPort(); 
     22     System.out.printf("ws returns [%s]%n", port.talk(args[0])); 
     23   } 
     24 }
  5. Compile the client  (javac Client.java)
  6. Run the program  (java Client <message>)  or
    java -Djava.util.logging.config.file=log.prop Client <message>
And just like that you have written both a client and a server which talk to each other via SOAP. The secondary run line (with the -Djava.util... option) is there in case you don't want to see the logging messages that get printed by default when you run the client.

The URL specified on line 10 is the same URL that you specified on line 13 of the server up above, except with a "?wsdl" parameter. The QName defined on line 11 comes directly from the WSDL. If you look at the wsdl, http://localhost:8080/Hello?wsdl, it'll look something like:
  1 <?xml version="1.0" encoding="UTF-8"?> 
  2 <!--  
  3   Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. 
  4 --> 
  5 <!--  
  6   Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. 
  7 --> 
  8 <definitions  
  9   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
 10   xmlns:tns="http://hello/" 
 11   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
 12   xmlns="http://schemas.xmlsoap.org/wsdl/" 
 13   targetNamespace="http://hello/" 
 14   name="HelloService"> 
 15   <!-- service definition here --> 
 16 </definitions
The targetNamespace and the name (lines 13 and 14 above) correspond to the QName used in the client.

Final Thoughts
This example was for a very specific case where you control both the client and server code and want it to be standalone. Of course, your web service needs may not match this model. If you already have a web container (Tomcat, etc), you can always deploy the Hello web service in that, rather than running it as a standalone application. And, of course, you could write your client in any language, as long as it conforms to the WSDL. Or you can just give customers the WSDL and let them write their own client.

If you have to write a client and don't have handy interface classes (hello.HelloPort in the above example), you can do that as well. You'll just have to generate classes using the wsimport command which comes with Java, but that is beyond the scope of this particular blog post.