2006/11/05

Calculator.java revisted

As discussed yesterday, while implementing the CalulatorService, doubles are not good enough for precision —see the following lecture recommended by Ken Anderson: Floating point.

To fix this problem, the first thing to do is to re-implement the Calculator.java object to accept and return strings, instead of doubles, and operate with BigDecimals:
import java.math.BigDecimal;

public class Calculator extends Object {

public static String add(String addend1, String addend2) {

BigDecimal x = new BigDecimal(addend1);
BigDecimal y = new BigDecimal(addend2);
BigDecimal z = x.add(y);

return z.toString();
}

Re-make the stubs and then, re-implement our CPO.m to use, also, strings:
@implementation CPO
- (IBAction)add:(id)sender
{
id x = [[form cellAtIndex:0] stringValue];
id y = [[form cellAtIndex:1] stringValue];
id z = [CalculatorService add:x in_addend2:y];

[[form cellAtIndex:2] setStringValue:z];
}
@end

I wonder... how does types travel through the Web Service protocols?
Let us find out...

2006/11/04

Consuming Calculator.java WS

A well-known example, which is included in /Developer/ADC Reference Library/documentation/WebObjects/Web_Services/Web_Services.tar.gz, is a simple Calculator. To publish it is as simple as compile and run... however, to consume it inside Cocoa requires some extra knowledge; let us focus on the add method —the rest is completely analogous.

Once the service is running, the first step is to produce the "stubs"; this can be done using the command-line argument
Szamitogep# /Developer/Tools/WSMakeStubs
-x ObjC
-name Calculator
-url http://localhost:4210/WebObjects/
Calculator.woa/ws/Calculator?wsdl

which generates two objects: WSGeneratedObj.m and Calculator.m

Include these objects in a new Cocoa App project. Run Interface Builder by double-clicking the MainMenu.nib icon and, in the classes pane, create a new object, say CPO, with an NSForm *form outlet and an add: action. Create files, instantiate and connect. (of course I am supposing that you know how to do these =:o)

In the implementation of the -add: method, write the obvious line:
[[form cellAtIndex:2]
setDoubleValue:[[CalculatorService
add:[[form cellAtIndex:0] doubleValue]
in_addend2:[[form cellAtIndex:1] doubleValue]]
doubleValue]];

compile and run... you see?
It does not work!!

The problem is in the implementation of the -resultValue method of the object add:WSGeneratedObj (defined in Calculator.m, and generated by WSMakeStubs). If you change that implementation line from
return ... objectForKey: @"addReturn"];
to
return ... objectForKey: @"ns1:addReturn"];
it will work...

But, how to find out the correct key to use?

Simple... just before the return line of the -getResultDictionary method, inside WSGeneratedObj.m, add the line
NSLog(@"getResultDictionary>fResult = %@",fResult);
and bingo!

Finally, just for the record: I used this service to add 3.4 to 6.6... can you guess the result? Wrong! Sadly, my computer, a G4 Mac mini, does not know how to add... it brings as a result
9.999998099999999

2006/11/01

Intel inside: first view

I'd just acquired my first Intel Mac; a modest 17" super iMac running a 2 GHz Xeon. My first surprise was to find Xcode 2.4 with WO included. My second surprise was to find out that Cocoa EO remains there; even more surprising was that, by importing and compiling an "old" Cocoa EO project, the app simply runs... this means that the Java Bridge remains there which implies, by the way, that I can slow down my discovery on how to replace it.

The bad news is that new projects —created inside the Intel machine— does not compile (yet) in a PPC machine... I am not sure about the reasons, but I will find out!

For the record: to start a new Cocoa EO app inside this new machine was not straight forward. Here the steps to accomplish this.


1. install Xcode and WebObjects.
2. run Interface Builder and import the EnterpriseObjects.palette (which is inside /Developer/Extras/Palettes).
3. create or import an EOModel.
4. in Finder, go to
/Library/Application Support/Apple/Developer Tools/Project Templates/Application/Cocoa-Java Application/
and change the extension of the file —indeed the folder— CocoaApp.xcodeproj to .pbproj .
5. run Xcode and create a new project of type
Cocoa Enterprise Objects Application
and follow the wizard's instructions.
6. define your interface and add your code.
7. compile and run.


One more thing... for me was more convenient to change a Preference: in the File Types pane, change the folders>wrapper>wraper.eomodel to be edited with EOModeler (which is inside the folder /Developer/Applications/WebObjects/).

Suerte!