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!

2006/10/04

What's NeXT?

The next step to successfully use Web Services to substitute Cocoa EOF is to publish into a service an EOEditingContext. In this way, Core Data should be able to use EOF, via those services offered by the Editing Context, as a persistence media.

I am not quite sure where to put the line (the service); on top of the Editing Context? or, even below it?
To transfer Enterprise Objects? or, shall I transfer Dictionaries?... it will depend in the performance... we will see.

By the moment, the idea is to have, in the server side, the persistence mechanisms offered by EOF; and in the client side, a Cocoa app running Core Data to manage Display Groups and all the consistency necessary in a complex db-model. For, the model will have to be duplicated in the two formats: .eomodeld and .xcdatamodel ...

... welcome to a new nightmare!

Finally

It was much more easy than I thought...
following LeBer's advice, I went to the wikibooks and found that I better use the tool /Developer/Tools/WSMakeStubs.
It creates two objects (in my case Account.[hm] and WSGeneratedObject.[hm]) which I simply imported in a new project and, via some controller, they can invoke the service... I had to write the following two lines of code to see what was going on:

@implementation CPO
- (IBAction)servicio:(id)sender
{
id valor = [AccManagerService newAcc:[nombre stringValue]
in_who:[quien stringValue]];
NSRunAlertPanel(@"Servicio",
@"El valor es = %@",
nil,nil,nil,valor);
}
@end


Nice and beauty...

2006/09/17

I am back...

I had been away trying to tame a PLC which call for me to remember how to code in binary... finally the beast surrender.

So, now I have again time to continue my experiments with Web Services. An e-friend from WOdev-list at apple (David LeBer) suggests the following lecture:
Consuming with WebServicesCore.framework
I will take a look and come back later!

2006/08/22

Direct to Web Services: first view

Well, what can I say, with Direct2... life is ease. I had created a simple service just in few minutes. I created a new database — in my Sybase server — with 3 tables, each adopting a basic BAProtocol, establishing a 3-depth 1toN relation:

Account<—>>Document<—>>Details

EOModeler did its work — I really hope Apple is planning a good alternative to this, now that they are deprecating the Java Bridge. From there, Xcode nicely creates a Web service which can be customised with WebServicesAssistant. Inside the later I created a service called newAcc — which inserts a new account...

All this took me no more than 40 minutes... not bad for a completely new newbie =;o)

Now I just have to have to learn how to consume this service within Cocoa... so, let's try!

2006/08/19

Web Services Documentation.

I found that the basic references to start to integrate WO's Web Service Provider with Cocoa Web Service Consumer are WebObjects Web Services and Cocoa Web Services, respectively. Both represent long readings, so I will have to be back later...

...some indications that this can be done are:

Jeremy's Little Corner...
iTod Hi-Fi

Where to go from CEO?

My first impression is that there is no other technology like Cocoa EO so integrated to OS X, however I may be wrong. In the last two releases of the OS X, vers. 3 and 4 (better known as Panther and Tiger, resp.), two nice technologies had been included in the "free" DevTools: namely, Bindings and Core Data. Watching the big picture, these frameworks looks like an attempt from Apple to rediscover Enterprise Objects, but now fully integrated into Cocoa — like if they were porting EOF back from Java to Objective-C again. To this to become a reality, one piece is still missing: the connectivity to a RDBM (like Sybase, Oracle, MySQL...); in EO terms, EOAccess layer...

The question is now: is Apple including this missing piece into Leopard (OS X 10.5)? NDA aside, no one knows for sure. WWDC was held a few days ago and, at least in the public statement, there is no light that this will happen soon.

On the other hand, Web Objects has become a natural citizen of OS X since it was integrated to Tiger — into Xcode 2.2.x — and it includes a nice technology called Web services, which is based on SOAP. I have not tried yet, but it may be a possibility to code a "service provider/consumer framework" to emulate the Access layer... let us try that for the moment.

2006/08/17

On Java & Objective-C

The main source of Objective-C frameworks is Steve Jobs and his team. They started to use this language since they were selling the NeXT machine. When NeXT buys Apple (for a negative amount of money ;^) they recompiled the operating system OpenStep to run into Apple's hardware; since then, it is know as Mac OS X. These are all old news. One more: Java becomes fashioned more or less in the same time — a bit before, to be more precise.

NeXT was forced to move one of its most valuable pieces of software, WebObjects, from Objective-C to Java; but they wanted to keep it "native" inside OS X... so, they coded the so called Java Bridge, a (never too nice, but useful) piece of software which allows to communicate the JVM and the Obj-C runtime. With this tool at hand it is possible to code (to develop) applications which have the beauty interfaces (and useful) frameworks of Cocoa (the front-end of OS X) and have also all the database connectivity developed for WebObjects, the so called Enterprise Objects Framework. The result: the best client/server apps in the market.

The bad news (well, not so new) is that Apple is giving up on the Java Bridge... this means that I will have to port all my code to use something else in order to provide nice and useful interfaces to my users, while keeping the database connectivity easy to manage... not an easy task, but it has to be done =:o(