Sun GlassFish Mobility Platform 1.1 Developer's Guide for Enterprise Connectors

The MyBusinessObjectResource Class

The MyBusinessObjectResource class implements the CUD operations create, update, and delete, using the HTTP operations PUT and DELETE.

The putBusinessObject method either creates or updates a business object, returning the serialized object. The method looks like this:

    @PUT
    @Consumes("application/octet-stream")
    public void putBusinessObject(
            @QueryParam("username") @DefaultValue("username") String user,
            @QueryParam("password") @DefaultValue("password") String password,
            @QueryParam("sessionId") @DefaultValue("") String sessionId,
            @QueryParam("lastModified") @DefaultValue("0") long lastModified,
            @PathParam("id") String id, byte[] object)
    {
        // INSERT CODE: create/update object from client
    }

The deleteBusinessObject method removes a business object from the back-end system, given its identifier and, optionally, the object contents. The method signature looks like this:

    @DELETE
    public void deleteBusinessObject(
            @QueryParam("username") @DefaultValue("username") String user,
            @QueryParam("password") @DefaultValue("password") String password,
            @QueryParam("sessionId") @DefaultValue("") String sessionId,
            @QueryParam("lastModified") @DefaultValue("0") long lastModified,
            @PathParam("id") String id, byte[] object)

The mergeBusinessObjects method, like the MyBusinessObjectsResource.lifeCycle method, goes beyond the simple CRUD operations to implement the HTTP POST operation:

    @POST
    @Produces("application/octet-stream")
    public byte[] mergeBusinessObjects(
            @QueryParam("username") @DefaultValue("username") String user,
            @QueryParam("password") @DefaultValue("password") String password,
            @QueryParam("sessionId") @DefaultValue("") String sessionId,
            @PathParam("id") String id, BusinessObjects objects)

Two business objects are passed in the argument objects: the server object followed by the client object.

The Gateway can call this method when there is an update conflict. If an object is updated on both the client and the server, the Gateway asks the Enterprise Connector to provide a merged object containing updated information for both objects.

Because the getBusinessObject method is not currently used, it is not described here.

Example: The MusicAlbumResource Class

In the MusicDB example, the MusicAlbumResource class is the item class. The MusicAlbumResource class implements the CUD methods specified by the MyBusinessObjectResource template.

The putBusinessObject method begins by adding an additional boolean parameter, useTimestamps, to the method signature:

    @PUT
    @Consumes("application/octet-stream")
    public void putBusinessObject(
            @QueryParam("username") @DefaultValue("username") String user,
            @QueryParam("password") @DefaultValue("password") String password,
            @QueryParam("sessionId") @DefaultValue("") String sessionId,
            @QueryParam("lastModified") @DefaultValue("0") long lastModified,
            @QueryParam("useTimestamps") @DefaultValue("false") boolean useTimestamps,
            @PathParam("id") String id, byte[] object)

The useTimestamps parameter allows the method to instantiate a MusicAlbum using its three-argument constructor. The method code begins by declaring two JDBC statements and creating a connection pool instance. It then instantiates the MusicAlbum object and deserializes its byte array argument into this object:

	Statement stmt1 = null, stmt2 = null;
	try {
            // Get connection pool
            ConnectionPool pool = ConnectionPool.getInstance();
            
            // Map to connector object to generate SQL statement
            MusicAlbum album = new MusicAlbum(id, user, useTimestamps);
            album.deserialize(object);

Next, the method determines whether the album already exists by executing the select statement for the MusicAlbum object.

            // Check if album already exists
            boolean isInsert = true;
            stmt1 = pool.getConnection(sessionId).createStatement();
            ResultSet rs = stmt1.executeQuery(album.getSelectString());
            if (rs.next()) {
                isInsert = false;
            }
            rs.close();

If the select statement returns a non-empty result set, the boolean value isInsert is set to false, indicating that the method will perform an update. Otherwise, the method will perform an insert to create the object in the database. The following code executes either the insert statement or the update statement for the MusicAlbum object, then closes the two JDBC statements.

            // Run INSERT or UPDATE  against database
            stmt2 = pool.getConnection(sessionId).createStatement();
            stmt2.executeUpdate(isInsert ? album.getInsertString()
                    : album.getUpdateString());
        } 
        catch (Exception ex) {
            throw new RuntimeException(ex);
        } 
        finally {
            if (stmt1 != null) {
                try { stmt1.close(); } catch (Exception e) { /* ignore !*/ }
            }
            if (stmt2 != null) {
                try { stmt2.close(); } catch (Exception e) { /* ignore !*/ }
            }
        }        
    }

The deleteBusinessObject method for MusicAlbum, like putBusinessObject, adds a useTimestamps parameter to its signature:

    @DELETE
    public void deleteBusinessObject(
            @QueryParam("username") @DefaultValue("username") String user,
            @QueryParam("password") @DefaultValue("password") String password,
            @QueryParam("sessionId") @DefaultValue("") String sessionId,
            @QueryParam("lastModified") @DefaultValue("0") long lastModified,
            @QueryParam("useTimestamps") @DefaultValue("false") boolean useTimestamps,
            @PathParam("id") String id, byte[] object)

The method declares a JDBC statement, then instantiates a MusicAlbum object using its three-argument constructor and deserializes its byte array argument into this object:

    {
        Statement stmt = null;
        try {
            // Map to connector object to generate SQL statement
            MusicAlbum album = new MusicAlbum(id, user, useTimestamps);
            album.deserialize(object);

The code creates a connection pool instance and a JDBC statement, then executes the delete statement for the MusicAlbum object to remove it from the database:

            ConnectionPool pool = ConnectionPool.getInstance();
            stmt = pool.getConnection(sessionId).createStatement();
            stmt.executeUpdate(album.getDeleteString());
        } 
        catch (Exception ex) {
            throw new RuntimeException(ex);
        } 
        finally {
            if (stmt != null) {
               try { stmt.close(); } catch (Exception e) { /* ignore !*/ }
            }
        }
    }

The MusicAlbum Enterprise Connector does not implement the mergeBusinessObjects method. This means that the object on the server always wins if there is a conflict.

The getBusinessObject method is implemented in the MusicAlbumResource class, but it is never invoked.