Zsolt,

Below is a fairly straightforward implementation example from my project's code 
(this email will probably line-wrap it badly...)  This example ignores the 
requested lease duration and uses a fixed value.  The reaper is not included in 
this example, but it's implementation is trivial: a TimerTask that runs 
periodically via Timer.schedule() and removes expired leases from my Map.  The 
exposed service that allows clients to request initial leases is also not 
included, but it simply invokes getLease() in the code below.



package com.avid.workgroup.notification;

import java.rmi.RemoteException;
import java.rmi.server.ExportException;
import java.util.HashMap;
import java.util.Map;

import net.jini.core.lease.Lease;
import net.jini.core.lease.LeaseDeniedException;
import net.jini.core.lease.UnknownLeaseException;
import net.jini.export.Exporter;
import net.jini.id.Uuid;
import net.jini.id.UuidFactory;

import com.avid.workgroup.notification.NotificationException;
import com.sun.jini.landlord.Landlord;
import com.sun.jini.landlord.LandlordLease;
import com.sun.jini.landlord.LeaseFactory;

class SubscriptionLandlord implements Landlord {
    private final LeasingProducerTopicTable m_producerTopicTable;
    private final Exporter m_exporter;
    private final LeaseFactory m_leaseFactory;
    private final long m_leaseMilliseconds;

    /** constructor for a SubscriptionLandlord.
     * @param producerTopicTable the producerTopicTable into which we'll place 
subscription info.
     * @param exporter the exporter we should use to export ourselves.
     * @param leaseMilliseconds when we generate or extend a Lease, the number 
of milliseconds we grant.
     * @throws NotificationException if anything goes wrong.
     */
    SubscriptionLandlord(LeasingProducerTopicTable producerTopicTable, Exporter 
exporter, long leaseMilliseconds)
            throws NotificationException {

        m_producerTopicTable = producerTopicTable;
        m_exporter = exporter;
        m_leaseMilliseconds = leaseMilliseconds;
        Uuid ourUuid = UuidFactory.generate();
        Landlord proxy;
        try {
            proxy = (Landlord) m_exporter.export(this);
        } catch (ExportException e) {
            throw new NotificationException("Unable to export lease landlord", 
e);
        }
        m_leaseFactory = new LeaseFactory(proxy, ourUuid);
    }

    /**
     * Get a new lease for a subscription to return to a Notification Consumer.
     * @param topic The topic for the subscription.
     * @param producerLeaseData Data stored about the subscription by the 
producer.
     * @throws NotificationException if anything goes wrong.
     * @return the lease.
     */
    Lease getLease( Class<? extends AbstractNotification> topic, 
IProducerLeaseData producerLeaseData ) throws NotificationException {
        Uuid leaseUuid = UuidFactory.generate();
        LandlordLease retLease = m_leaseFactory.newLease(leaseUuid,
                                                         
System.currentTimeMillis() + m_leaseMilliseconds);
        // put the lease into the Producer Topic Table
        m_producerTopicTable.addLease( topic, producerLeaseData, retLease);
        return retLease;
    }

    /**
     * get rid of any resources being held by this landlord.
     * <p>
     * Note that this method unexports the
     * exporter even if there are pending remote calls to it.  The caller (the 
Notification Consumer)
     * must be prepared for this (I would guess it results in RemoteExceptions).
     * </p>
     */
    void dispose() {
        m_exporter.unexport(true);
    }

    /**
     {...@inheritdoc}
     */
    public long renew(Uuid uuid, long duration) throws LeaseDeniedException, 
UnknownLeaseException, RemoteException {
        // whatever they ask for, we renew for m_leaseMilliseconds.
        return m_producerTopicTable.renewLease(uuid, m_leaseMilliseconds);
    }

    /**
     {...@inheritdoc}
     */
    public void cancel(Uuid uuid) throws UnknownLeaseException, RemoteException 
{
        m_producerTopicTable.removeLease(uuid);
    }

    /**
     {...@inheritdoc}
     */
    public RenewResults renewAll(Uuid[] uuids, long[] durations) throws 
RemoteException {
        long[] granted = new long[uuids.length];
        Exception[] denied = new Exception[uuids.length];

        for (int i = 0; i < uuids.length; i++){
            try {
                granted[i] = renew(uuids[i], durations[i]);
                denied[i] = null;
            } catch (Exception e) {
                granted[i] = -1;
                denied[i] = e;
            }
        }
        return new Landlord.RenewResults(granted, denied);
    }

    /**
     {...@inheritdoc}
     */
    @SuppressWarnings("unchecked") // jini 2.1 doesn't support generics
    public Map cancelAll(Uuid[] uuids) throws RemoteException {
        Map<Uuid, Exception> failures = new HashMap<Uuid, Exception>();
        for (Uuid uuid : uuids) {
            try {
                cancel(uuid);
            } catch (Exception e) {
                failures.put(uuid, e);
            }
        }
        // cancelAll is supposed to return null, not an empty Map, if no cancel 
fails
        return failures.isEmpty() ?  null : failures;
    }
}

-----Original Message-----
From: Kúti Zsolt [mailto:[email protected]] 
Sent: Thursday, July 08, 2010 7:45 AM
To: [email protected]
Subject: Re: lease grantor example

Thu, 8 Jul 2010 13:24:14 +0200 -n
Kúti Zsolt <[email protected]> írta:

> Hello,
> 
> Can somebody point me to a simple example of a lease grantor?
> Outrigger and mahalo seems rather complex for getting hints.
> 
> I develop a service that is to offer remote listeners notificiations
> on its working.
> 
> Thanks!
> Zsolt

OK, in the meantime I figured out what seems to be the essence for my
case:
- use LandLord and implementations around it to back up the Lease
  instance returned in EventRegistration
- organize own service implementation so that lease operations happen
  via the service remote reference
- apply additional application specific logic in Lease methods, if
needed, in the above own service implementation
- use a reaper thread to expunge expired leases

I hope this is it.

Zsolt

Reply via email to