Controlling Both Ends of the Communications Channel: From Cocoa to Servlets
Objective-C is a superset of C; when tied with the Cocoa libraries it produces a very functional and easy to use language/API pair that drives Apple’s OS X. Unfortunately, this language is not as common as some others that are in widespread use and has not gathered its share of third-party libraries. Specifically, libraries involving Internet communications are curiously absent from Objective-C and force the developer to rely on libraries built for either C or C++. Although it is certainly possible to use libraries from C++ (in fact, Objective-C makes this deceptively easy), ideally a developer would prefer a native Objective-C library that is as easy to use and as functional as Apache’s Axis is for Java.
Unfortunately, there is no SOAP API available for Objective-C that is as easy to use as Apache’s Axis. However, if you are developing the client side as well as the server side of the equation (as many independent software vendors do), you can design your servlets with Objective-C in mind and make the client side much easier to work with. To demonstrate how to accomplish this I have written a servlet that accesses a simple entity bean and formats the results so that they can be easily read by Objective-C.
Entity Bean
For this example, I used a very simple entity bean that stores client names and when that client was created. To avoid repeating myself, I designed the bean using XDoclet, which generates all the interfaces for me.
package com.zarrastudios.example.entity; import com.zarrastudios.example.util.CustomerUtil; import com.zarrastudios.example.data.CustomerValue; import javax.ejb.EntityBean; import javax.ejb.CreateException; import java.sql.Timestamp; /** * @ejb.bean local-jndi-name="zds/local/Customer" * jndi-name="zds/remote/Customer" * primkey-field="guid" * cmp-version="2.x" * view-type="both" * * @ejb.interface local-class="com.zarrastudios.example.entity.CustomerLocal" * remote-class="com.zarrastudios.example.entity.CustomerRemote" * @ejb.home local-class="com.zarrastudios.example.entity.CustomerLocalHome" * remote-class="com.zarrastudios.example.entity.CustomerRemoteHome" * * @ejb.finder signature="java.util.Collection findAll()" * query="select object(o) from Customer o" * * @ejb.value-object */ public abstract class CustomerEJB implements EntityBean { /** * @ejb.create-method */ public String ejbCreate(String name) throws CreateException { setName(name); setGuid(CustomerUtil.generateGUID(this)); setCreateDate(new Timestamp(System.currentTimeMillis())); return null; } /** * @ejb.interface-method * @ejb.persistence */ public abstract String getGuid(); public abstract void setGuid(String s); /** * @ejb.interface-method * @ejb.persistence */ public abstract String getName(); /** * @ejb.interface-method */ public abstract void setName(String s); /** * @ejb.interface-method * @ejb.persistence */ public abstract Timestamp getCreateDate(); public abstract void setCreateDate(Timestamp t); /** * @ejb.interface-method */ public abstract CustomerValue getCustomerValue(); /** * @ejb.interface-method */ public abstract void setCustomerValue(CustomerValue cv); }
This bean stores only three values: the unique identifier (guid), the customer name (name), and the creation date of the account (createDate). In addition, this bean is capable of returning a value object representing itself. Although it is not strictly necessary in this example, it is always a good habit to be in. I have also defined one finder method that will retrieve all the client records. This finder method will be used by the servlet.