Sunday, March 27, 2011

Web Services in Java

I am attempting to learn about web services in Java.

Working with NetBeans

In general, web services have two flavors: RESTful and (SOAP, WSDL). RESTful are supposed to be easier to consume. WSDL are more robust.
http://netbeans.org/kb/docs/websvc/intro-ws.html

There is an implementation named Axis, based on SOAP, also has services for RESTful.
http://netbeans.org/kb/docs/websvc/gs-axis.html

Creating Axis2 Web Service in NetBeans

I have created a web service using Axis2 and have accessed the service through a browser. It returns an XML file. http://netbeans.org/kb/docs/websvc/gs-axis.html

Creating Files to Access an Existing Web Service

I will now follow the tutorial to create a JAX-WS client that can access the service.
http://netbeans.org/kb/docs/websvc/client.html

First, I created the files to access an existing web service.
  1. Create web application
  2. New.Web Services.Web Service Client
  3. Specify URL of WSDL file: http://ws.cdyne.com/SpellChecker/check.asmx?wsdl
  4. Leave package blank, so it will be read friom WSDL
  5. Select JAX-WS as the client style.
  6. Many source files are generated.
  7. A local copy of the WSDL is generated.
Creating a Client to Access the Web Service

Second, I created a client to access it.
  1. Create web application.
  2. Create user interface in JSP.
  3. Create servlet.
  4. Drag service component into servlet. The tutorial is wrong about the code that is inserted: a method is inserted. Call the method to run the service.
  5. Modify the servlet to call the service and update the UI.
Brilliant!

The above approach uses NetBeans and Metro.

Working with Eclipse

I will now try to use Eclipse and Apache CXF.

Update Eclipse so it can use Tomcat to Run Servlets


First, add ability to run servlet in Eclipse.
  1. Download Eclipse with Java EE.
  2. Add extensions for JAX-WS from
    http://wiki.eclipse.org/images/b/bf/Jaxws-1.0.0-201003201732.psf
  3. Add them to Eclipse with File->Import->Team->Team Project File. The username is anonymous and the password is an email address.
  4. Create a Dynamic Web Application. Create a New Runtime (Server) for Tomcat. Select Create local server, to save a step later.
  5. Create servlet from New -> Servlet.
  6. Works perfectly.
  7. After I had to restore my computer, the eclipse installation was no longer working. Tomcat was not recognized. I switched workspaces (File->Switch Workspace) and reinstalled the Tomcat plugin. It is working again, but there are still some red Xs for some packages.
Install CXF and Create a Web Service (Did not work!!! Don't do this!!!)

Second, download Apache CXF.
  1. http://www.apache.org/dyn/closer.cgi?path=/cxf/2.3.3/apache-cxf-2.3.3.zip
  2. Download Apache Ant: http://ant.apache.org/bindownload.cgi
  3. Follow video at:
    http://repo.fusesource.com/videos/service-creation/Java2WSClientServer.wmv
  4. The video is outdated. Click Add to enter the location of CXF. Be sure to check the new entry.
  5. In Eclipse: Window.Preferences.Web Services
    1. ...CXF Preferences; browse to install dir, select installation, export at runtime.
    2. ...JAX-WS; enable annotations; do not enable validation
    3. ..Spring Config; use Spring
  6. Create web app; select configuration as CXF; my install does not have springframework list, but is shown in video. Video shows for runtime. To select CXF, I had to select Tomcat.
  7. The Libraries are different from the video: jar files are in CXF, not Web App.
  8. Add converter for celsius and farenheit
  9. Make into web service: video shows Button Up POJO. That is not in my option list.
Failed miserably!!!

Creating Axis2 Web Service in Eclipse

Second attempt at Eclipse. New Tutorial:
http://www.softwareagility.gr/index.php?q=node/28
  1. Install Apache Axis2
  2. Create Dynamic web app; set configuration to include Axis2; define service class.
  3. Right-click service class and select Web Services.Create Web Service; set runtime to Axis2
  4. Run service; default Axis2 page appears; view service methods
  5. In Eclipse: Run.Launch Web Service Exporer; enter URL for WSDL; run methods
Brilliant! I now have a web service in Eclipse using Axis2 (like NetBeans)

Creating Client to Access Web Service using Eclipse

Now, to create a client in Eclipse:
http://www.eclipse.org/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html
  1. Tutorial creates another web service, like above.
  2. Tutorial then goes on to explain how to create client in separate app. In the first part, there was a check box for creating the client files. They were created in a separate app: same name as before, appended with Client; however, it does not have all the files as explained in the tutorial.
  3. Only one stub is created, not three (Http, Soap11, Soap12) as in tutorial.
  4. Imported the code to the client. Cannot be accessed in Tomcat.
  5. Try creating test case. They don't work either.
I have reached a road block with Eclipse.
  1. I was planning to redo it all, when I noticed the stubs I had created inadvertently, when I first created the service. I decided to delete these. When I did, I received a lot of errors, so I undeleted them. At that moment, I noticed the return type on the celsiusFarenheit method. It was not a float; this was good, because that was a problem I was having with the others.
  2. I copied the client code from the web again and modified it with ClientStub.
  3. It worked!
  4. Solution: use the ConverterStub class, not any of the ones that have Soap in the name.
  5. Update on solution: it seems that you must create a completely new app for the client, do not import the stubs into a current app. The correct stubs were only created when creating a new client app.

Monday, March 14, 2011

Shoemaker Proof

I am working as a coach for our programming team.

One of the problems is the Shoemaker problem. The complete description can be found at Shoemaker Description.

The simple solution is to sort the jobs in order by the cost/delay ratio, then do the jobs in decreasing order.

It is a simple solution, but I was not convinced that it was correct, so I proved it as follows.

I will use the following annotations to indicate sums, costs and delays.

cost(m) will be the cost for each day that job m is delayed.
delay(m) will be the number of days it takes to complete job m. All jobs that are completed after m will incur a cost for this delay. Job m does not pay a penalty for itself.
sum_cost(i,j) will be the sum of all the costs for jobs i through j.

It is easy to validate if there are only two jobs. The cost for each job is

Do 1 first: delay(1)*cost(2)
Do 2 first: delay(2)*cost(1)

The first formula will be less than the second, when cost(2)/delay(2) < cost(1)/delay(1)

The difficulty arises when there are more terms.

Assume that the jobs have been sorted by cost/delay.

The proposed minimum sum is
delay(1)sum_cost(2,n) + delay(2)sum_cost(3,n) + ... + delay(n-1)sum_cost(n,n)

Consider any other sum than this one. A position m can be found such that

cost(m)/delay(m) < cost(m+1)/delay(m+1)

In other terms,

formula 1 (f1): delay(m+1)cost(m) - delay(m)cost(m+1) < 0

By switching the order of these two in the sum, then a smaller cost will result.

Term m: delay(m)sum_cost(m+1,n) + delay(m+1)sum_cost(m+2,n) =

Effect of switching term m and term m+1:
delay(m)sum_cost(m+1,n) - delay(m)cost(m+1) + delay(m+1)sum_cost(m+2,n) + delay(m+1)cost(m)

The difference between this new term and the original is:
delay(m+1)cost(m) - delay(m)cost(m+1)

By the above formula (f1), this term is less than 0. The conclusion is that any sum that has terms that are out of order can be rearranged to find a smaller sum. It follows that the sum formed from the jobs in descending order by cost/delay is the minimum. QED.

Followers