Update of /cvsroot/cweb/bigdata/src/java/com/bigdata/service In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv20431/src/java/com/bigdata/service Modified Files: package.html DataService.java MetadataService.java MapReduceService.java AbstractService.java IMetadataService.java Log Message: Working on services. Added some JARs for dependencies to simplify deployment. Index: DataService.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/DataService.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** DataService.java 18 Mar 2007 22:29:43 -0000 1.3 --- DataService.java 22 Mar 2007 15:04:15 -0000 1.4 *************** *** 140,144 **** * directory. */ ! public class DataService extends AbstractService implements IDataService, IWritePipeline, IResourceTransfer { protected Journal journal; --- 140,145 ---- * directory. */ ! public class DataService extends AbstractService implements IDataService, ! IWritePipeline, IResourceTransfer { protected Journal journal; Index: package.html =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/package.html,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** package.html 17 Mar 2007 23:14:58 -0000 1.1 --- package.html 22 Mar 2007 15:04:15 -0000 1.2 *************** *** 1,13 **** <html> <head> ! <title>Services</title> </head> <body> <p> ! This package provides implementations of services (data service, transaction ! manager service, metadata locator service). </p> </body> ! </html> \ No newline at end of file --- 1,176 ---- <html> <head> ! <title>services</title> </head> <body> <p> ! This package provides implementations of bigdata services (metadata ! service, data service, transaction manager service. ! </p> ! ! <p> ! A bigdata federation is comprised of the following essential ! services: ! ! <dl> ! ! <dt>metadata service</dt><dd>The metadata service manages indices and ! is used to locate index partitions.</dd> ! ! <dt>data service</dt><dd>The data service supports reads and writes on ! index partitions.</dd> ! ! <dt>transaction manager service</dt><dd>Clients use the transaction ! manager service to start new transactions and to coordinate the ! distributed commit protocol. The transaction manager also provides a ! centralized timestamp factory.</dd> ! ! </dl> ! ! Clients are responsible for discovering the metadata service. Clients ! then use the metadata service to manage scale-out indices and to ! locate and cache leases for data service instances having data for key ! range partitions that the client will read or write. If a client will ! use transactions (vs ACID batch operations), then the client must also ! locate the transaction manager service. Service location is performed ! using JINI, but other service locator protocols are possible. ! </p> ! ! <p> ! ! bigdata provides the following value added services. These are not ! considered essential since (a) they are not required by clients that ! make direct use of bigdata as a distributed database; and (b) they are ! themsevles applications of the services briefly described above. ! ! <dl> ! ! <dt>map/reduce service</dt><dd>Manages the distributed execution of a ! functional program.</dd> ! ! </dl> ! ! </p> ! ! <h2>deployment</h2> ! ! <p> ! ! In order to deploy a bigdata federation, the following preconditions ! must be met (a standalone deployment can be realized by meeting these ! preconditions on a single host). This will go more smoothly if JINI ! is running before you start the various bigdata services since they ! will then be able to register themselves immediately on ! startup. Service discovery by default uses the local network and the ! "public" group. If you want to run more than one bigdata federation on ! the same network, then you MUST edit the configuration file. ! ! </p> ! ! <p> ! Hosts: ! ! <ul> ! ! <li>java 5 or better is installed. The use of a server VM is highly ! recommended. The following options are recommended for some well ! known VMs: <dl> ! ! <dt>Sun</dt><dd>-server -Xms1g -Xmx1g -XX:MaxDirectMemorySize=256M</dd> ! ! <dt>JRockit</dt><dd>-Xms1g -Xmx1g</dd> ! ! </dl> ! ! @todo review the use of -Xms (sets the initial heap size). How much ! of a difference does this make? Note that JRockit defaults to 75% of ! physical memory or 1G, which ever is less.</li> ! ! <li>the bigdata-server distribution is installed.</li> ! ! <li>the data service is running.</li> ! ! </ul> ! ! </p> ! ! <p> ! In addition, there must be at least one host on which the following ! preconditions are true (a different host could be used for each of ! these services, and more than one instance of these services may be ! running on the network). These services should be started during the ! boot procedure so that they are available whenever the host is up and ! running. ! ! <ul> ! ! <li>jini 2.x is installed and running. This will be used to register ! and lookup services. It helps if jini is running before you try to ! start the bigdata sercices since they will be able to register ! themselves immediately in that case.</li> ! ! <li>the metadata service is running (this is part of the ! bigdata-server distribution).</li> ! ! <li>the transaction manager service is running (this is part of the ! bigdata-server distribution).</li> ! ! <li>the optional map/reduce service is running (this is part of the ! bigdata-server distribution).</li> ! ! </ul> ! ! </p> ! ! <p> ! Clients: ! ! <ul> ! ! <li>java 5 or better is installed. The use of a server VM ! is highly recommended</li> ! ! <li>the bigdata-client deployment package is installed. This includes ! bigdata-client.jar, but also support for generating unicode keys ! (ICU4J), etc.</li> ! ! </ul> ! ! </p> ! ! <h2>downloaded code</h2> ! ! <p> ! ! While bigdata makes use of jini for service registration and ! discovery, it does not use downloaded code for executing its basic ! services (the necessary interfaces and implementation classes are ! already bundled in bigdata.jar). However, clients MAY use downloaded ! code in order to have data servers execute remote procedures or ! extension batch operations. In this scenario, the client will create ! and register a JINI service. The service should perform <em>all</em> ! of its operations locally. The data server will lookup the service ! using jini and then execute it locally. ! </p> ! ! <p> ! In order for downloaded code to work correctly, clients must ensure ! that their classes are exposed by an HTTP server accessible to bigdata ! servers and declared to the VM in which the client starts using: ! ! <code>-Djava.rmi.server.codebase=...</code> ! ! </p> ! ! <p> ! ! @todo consider this use case further. Are there other/better ways for ! executing remote code on the data server? At a minimum, we should ! supply a base class and ant script support for creating such remote ! services. ! </p> </body> ! </html> Index: MetadataService.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/MetadataService.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** MetadataService.java 17 Mar 2007 23:14:58 -0000 1.1 --- MetadataService.java 22 Mar 2007 15:04:15 -0000 1.2 *************** *** 64,72 **** /** - * The name of the index. - */ - protected final String name; - - /** * The name of the journal on which the metadata index is stored. * --- 64,67 ---- *************** *** 76,81 **** protected final Journal journal; - protected MetadataIndex mdi; - public MetadataService(Properties properties) { --- 71,74 ---- *************** *** 93,107 **** } ! public InetSocketAddress getDataService(byte[] key) { // TODO Auto-generated method stub return null; } ! public int getEntryCount() { // TODO Auto-generated method stub return 0; } ! public int rangeCount(byte[] fromKey,byte[] toKey) { // TODO Auto-generated method stub return 0; --- 86,100 ---- } ! public InetSocketAddress getDataService(String name,byte[] key) { // TODO Auto-generated method stub return null; } ! public int getEntryCount(String name) { // TODO Auto-generated method stub return 0; } ! public int rangeCount(String name,byte[] fromKey,byte[] toKey) { // TODO Auto-generated method stub return 0; Index: MapReduceService.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/MapReduceService.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** MapReduceService.java 17 Mar 2007 23:14:58 -0000 1.1 --- MapReduceService.java 22 Mar 2007 15:04:15 -0000 1.2 *************** *** 220,227 **** /** ! * Resolve the metadata service for the named index. ! * ! * @param name ! * The index name. * * @return The metadata service for the named index. --- 220,224 ---- /** ! * Resolve the metadata service. * * @return The metadata service for the named index. *************** *** 229,233 **** * @todo change the return type. */ ! protected IMetadataService getMetadataService(String name) { throw new UnsupportedOperationException(); --- 226,230 ---- * @todo change the return type. */ ! protected IMetadataService getMetadataService() { throw new UnsupportedOperationException(); *************** *** 256,262 **** public Object call() throws Exception { ! IMetadataService mds = getMetadataService(name); ! final int nentries = mds.rangeCount(fromKey,toKey); return null; --- 253,259 ---- public Object call() throws Exception { ! IMetadataService mds = getMetadataService(); ! final int nentries = mds.rangeCount(name,fromKey,toKey); return null; Index: IMetadataService.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/IMetadataService.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** IMetadataService.java 17 Mar 2007 23:14:58 -0000 1.1 --- IMetadataService.java 22 Mar 2007 15:04:15 -0000 1.2 *************** *** 66,70 **** * The approximate number of entries in the index (non-transactional). */ ! public int getEntryCount(); /** --- 66,70 ---- * The approximate number of entries in the index (non-transactional). */ ! public int getEntryCount(String name); /** *************** *** 76,80 **** * @return */ ! public int rangeCount(byte[] fromKey,byte[] toKey); /** --- 76,80 ---- * @return */ ! public int rangeCount(String name,byte[] fromKey,byte[] toKey); /** *************** *** 95,99 **** * index partitions surrounding that partition. */ ! public InetSocketAddress getDataService(byte[] key); } --- 95,99 ---- * index partitions surrounding that partition. */ ! public InetSocketAddress getDataService(String name, byte[] key); } Index: AbstractService.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/AbstractService.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** AbstractService.java 18 Mar 2007 22:29:43 -0000 1.1 --- AbstractService.java 22 Mar 2007 15:04:15 -0000 1.2 *************** *** 50,55 **** --- 50,57 ---- import java.io.IOException; import java.io.Serializable; + import java.rmi.Remote; import java.rmi.RemoteException; + import net.jini.admin.JoinAdmin; import net.jini.core.entry.Entry; import net.jini.core.lease.Lease; *************** *** 61,66 **** --- 63,73 ---- import net.jini.discovery.DiscoveryListener; import net.jini.discovery.LookupDiscovery; + import net.jini.export.Exporter; + import net.jini.export.ProxyAccessor; import net.jini.id.Uuid; import net.jini.id.UuidFactory; + import net.jini.jeri.BasicILFactory; + import net.jini.jeri.BasicJeriExporter; + import net.jini.jeri.tcp.TcpServerEndpoint; import net.jini.lease.LeaseListener; import net.jini.lease.LeaseRenewalEvent; *************** *** 75,78 **** --- 82,90 ---- import net.jini.lookup.entry.StatusType; + import org.CognitiveWeb.bigdata.jini.ITestService; + import org.CognitiveWeb.bigdata.jini.TestServer; + import org.CognitiveWeb.bigdata.jini.TestServer.MyServiceType; + import org.CognitiveWeb.bigdata.jini.TestServer.MyStatus; + import org.CognitiveWeb.bigdata.jini.TestServer.TestServiceImpl; import org.apache.log4j.Logger; *************** *** 83,160 **** * @version $Id$ */ ! abstract public class AbstractService implements DiscoveryListener, LeaseListener, IServiceShutdown ! { public static Logger log = Logger.getLogger(AbstractService.class); ! private ServiceID serviceID; ! private ServiceItem item; ! private ServiceRegistration reg; ! final private LeaseRenewalManager leaseManager = new LeaseRenewalManager(); ! /** ! * Close down the service (no longer discoverable). ! * ! * @todo revoke lease, etc. ! */ ! private void _close() { ! ! } ! /** ! * Waits for existing leases to expire before shutting down, but does not ! * grant any new leases. ! */ ! public void shutdown() { ! ! /* ! * @todo wait for leases to expire and then shutdown. do not renew any ! * leases. ! */ ! ! _close(); ! ! } ! ! /** ! * Shutdown immediately, violating any existing leases. ! */ ! public void shutdownNow() { ! ! _close(); ! ! } ! ! /** ! * Return the {@link ServiceID}. Using a consistent {@link ServiceID} makes ! * it easier to register the same service against multiple lookup services. ! * <p> ! * This implementation generates a new {@link ServiceID} each time. ! * ! * @todo If you want to restart (or re-register) the same service, then you ! * need to read the serviceID from some persistent location. If you ! * are using activation, then the service can be remotely started ! * using its serviceID which takes that responsibility out of your ! * hands. When using activation, you will only create a serviceID once ! * when you install the service onto some component and activition ! * takes responsiblity for starting the service on demand. ! */ ! public ServiceID getServiceID() { ! Uuid uuid = UuidFactory.generate(); ! ! return new ServiceID(uuid.getMostSignificantBits(), uuid ! .getLeastSignificantBits()); ! } /** * Server startup performs asynchronous multicast lookup discovery. The * {@link #discovered(DiscoveryEvent)} method is invoked asynchronously to ! * register {@link TestServerImpl} instances. */ public AbstractService() { ! serviceID = getServiceID(); try { --- 95,135 ---- * @version $Id$ */ ! abstract public class AbstractService implements DiscoveryListener, ! LeaseListener, IServiceShutdown { public static Logger log = Logger.getLogger(AbstractService.class); ! private ServiceID serviceID; ! private ServiceItem item; ! private ServiceRegistration reg; ! final private LeaseRenewalManager leaseManager = new LeaseRenewalManager(); ! private TestServerImpl impl; /** * Server startup performs asynchronous multicast lookup discovery. The * {@link #discovered(DiscoveryEvent)} method is invoked asynchronously to ! * register {@link TestServiceImpl} instances. */ public AbstractService() { ! /* ! * Generate a ServiceID ourselves. This makes it easier to register the ! * same service against multiple lookup services. ! * ! * @todo If you want to restart (or re-register) the same service, then ! * you need to read the serviceID from some persistent location. If you ! * are using activation, then the service can be remotely started using ! * its serviceID which takes that responsibility out of your hands. When ! * using activation, you will only create a serviceID once when you ! * install the service onto some component and activition takes ! * responsiblity for starting the service on demand. ! */ ! Uuid uuid = UuidFactory.generate(); ! serviceID = new ServiceID(uuid.getMostSignificantBits(), uuid ! .getLeastSignificantBits()); try { *************** *** 162,172 **** LookupDiscovery discover = new LookupDiscovery( LookupDiscovery.ALL_GROUPS); ! discover.addDiscoveryListener(this); ! } catch (IOException ex) { ! throw new RuntimeException(ex); ! } --- 137,147 ---- LookupDiscovery discover = new LookupDiscovery( LookupDiscovery.ALL_GROUPS); ! discover.addDiscoveryListener(this); ! } catch (IOException ex) { ! throw new RuntimeException(ex); ! } *************** *** 174,178 **** /** ! * Log a message and register the {@link TestServerImpl}. Events are * aggregated but we can still receive multiple events depending on the * latency between discovery of various service registrars. Since the --- 149,153 ---- /** ! * Log a message and register the {@link TestServiceImpl}. Events are * aggregated but we can still receive multiple events depending on the * latency between discovery of various service registrars. Since the *************** *** 185,190 **** * indicator of whether or not it has been registered. * - * @todo Modify service proxy to use RMI. - * * @todo This should be a fast operation and should not make remote calls. * Service registration therefore needs to happen in another thread so --- 160,163 ---- *************** *** 197,206 **** */ ! registerService( evt.getRegistrars() ); ! } /** ! * Registers a service proxy with reach identified registrar. The * registration happens in another thread to keep the latency down for the * {@link DiscoveryListener#discovered(net.jini.discovery.DiscoveryEvent)} --- 170,179 ---- */ ! registerService(evt.getRegistrars()); ! } /** ! * Registers a service proxy with each identified registrar. The * registration happens in another thread to keep the latency down for the * {@link DiscoveryListener#discovered(net.jini.discovery.DiscoveryEvent)} *************** *** 210,222 **** * One or more service registrars. */ ! private void registerService( final ServiceRegistrar[] registrars ) { ! ! AbstractService.log.info("Discovered "+registrars.length+" service registrars"); new Thread("Register Service") { public void run() { ! // Create an information item about a service ! item = new ServiceItem(serviceID, new TestServerImpl(), new Entry[] { new Comment("Test service(comment)"), // human facing comment. new Name("Test service(name)"), // human facing name. --- 183,199 ---- * One or more service registrars. */ + private void registerService(final ServiceRegistrar[] registrars) { ! log.info("Discovered " + registrars.length + " service registrars"); new Thread("Register Service") { public void run() { ! // the service ! impl = new TestServerImpl(); ! /* Create an information item about a service. ! * ! * @todo use Configuration? ServiceStarter? ! */ ! item = new ServiceItem(serviceID, impl.getProxy(), new Entry[] { new Comment("Test service(comment)"), // human facing comment. new Name("Test service(name)"), // human facing name. *************** *** 224,231 **** "Test Service (short description)"), // service type new MyStatus(StatusType.NORMAL), ! new Location("floor","room","building"), ! new Address("street", "organization", "organizationalUnit", ! "locality", "stateOrProvince", "postalCode", ! "country"), new ServiceInfo("bigdata", // product or package name "SYSTAP,LLC", // manufacturer --- 201,208 ---- "Test Service (short description)"), // service type new MyStatus(StatusType.NORMAL), ! new Location("floor", "room", "building"), ! new Address("street", "organization", ! "organizationalUnit", "locality", ! "stateOrProvince", "postalCode", "country"), new ServiceInfo("bigdata", // product or package name "SYSTAP,LLC", // manufacturer *************** *** 247,250 **** --- 224,247 ---- // Register the service. reg = registrar.register(item, Lease.FOREVER); + /* + * Setup automatic lease renewal. + * + * Note: A single lease manager can handle multiple services + * and the lease of a given service on multiple service + * registrars. It knows which lease is about to expire and + * preemptively extends the lease on the behalf of the + * registered service. It will notify the LeaseListener iff + * it is unable to renew a lease. + */ + log.info("lease will expire in " + + (reg.getLease().getExpiration() - System + .currentTimeMillis()) + "ms"); + leaseManager.renewUntil(reg.getLease(), + Lease.FOREVER, AbstractService.this); + /* + * Service has been registered and lease renewal is + * operating. + */ + break; } catch (RemoteException ex) { // retry until successful. *************** *** 254,286 **** } } - /* - * Setup automatic lease renewal. - * - * Note: A single lease manager can handle multiple services - * and the lease of a given service on multiple service - * registrars. It knows which lease is about to expire and - * preemptively extends the lease on the behalf of the - * registered service. It will notify the LeaseListener iff - * it is unable to renew a lease. - */ - AbstractService.log.info("lease will expire in " - + (reg.getLease().getExpiration() - System - .currentTimeMillis()) + "ms"); - leaseManager - .renewUntil(reg.getLease(), Lease.FOREVER, AbstractService.this); - /* - * Service has been registered and lease renewal is - * operating. - */ - break; } } ! } ! }.start() ! ; ! ! } ! /** * Log a message. --- 251,261 ---- } } } } ! } ! }.start(); ! } ! /** * Log a message. *************** *** 288,293 **** public void discarded(DiscoveryEvent arg0) { ! AbstractService.log.info(""); ! } --- 263,268 ---- public void discarded(DiscoveryEvent arg0) { ! log.info(""); ! } *************** *** 299,306 **** public void notify(LeaseRenewalEvent event) { ! AbstractService.log.error("Lease could not be renewed: " + event); ! } ! /** * Launch the server in a separate thread. --- 274,281 ---- public void notify(LeaseRenewalEvent event) { ! log.error("Lease could not be renewed: " + event); ! } ! /** * Launch the server in a separate thread. *************** *** 309,344 **** new Thread("launchServer") { public void run() { ! AbstractService.main(new String[] {}); } }.start(); } ! /** ! * Run the server. It will die after a timeout. ! * ! * @param args ! * Ignored. ! */ ! public static void main(String[] args) { ! final long lifespan = 3 * 60 * 1000; // life span in seconds. ! AbstractService.log.info("Will start test server."); ! AbstractService testServer = new AbstractService(){ ! /* @todo this is an anonymous class - each service must provide its ! * own main() and registration information. ! */ ! }; ! AbstractService.log.info("Started test server."); ! try { ! Thread.sleep(lifespan); ! } ! catch( InterruptedException ex ) { ! AbstractService.log.warn(ex); ! } ! /* ! * @todo This forces a hard reference to remain for the test server. ! */ ! AbstractService.log.info("Server will die: "+testServer); ! } ! /** * {@link Status} is abstract so a service needs to provide their own --- 284,333 ---- new Thread("launchServer") { public void run() { ! TestServer.main(new String[] {"org.CognitiveWeb.bigdata.jini.TestServer.config"}); } }.start(); + log.info("Service started."); } ! // /** ! // * Run the server. It will die after a timeout. ! // * ! // * @param args ! // * Ignored. ! // */ ! // public static void main(String[] args) { ! // final long lifespan = 5 * 1000; // life span in seconds. ! // log.info("Will start test server."); ! // AbstractService testServer = new AbstractService(); ! // log.info("Started test server."); ! // try { ! // Thread.sleep(lifespan); ! // } catch (InterruptedException ex) { ! // log.warn(ex); ! // } ! // /* ! // * Cancel the lease. ! // */ ! // try { ! // log.info("Canceling service lease."); ! // testServer.leaseManager.cancel(testServer.reg.getLease()); ! // } catch (Exception ex) { ! // log.error(ex); ! // } ! // /* ! // * Unexport the proxy, making the service no longer available. ! // */ ! // log.info("Unexporting the service proxy."); ! // testServer.impl.unexport(true); ! // ! // // /* ! // // * Note: The reference to the service instance here forces a hard ! // // * reference to remain for the test server. If you comment out this log ! // // * statement, then you need to do something else to hold onto the hard ! // // * reference. ! // // */ ! // // log.info("Server will die: "+testServer); ! // } ! /** * {@link Status} is abstract so a service needs to provide their own *************** *** 354,363 **** */ private static final long serialVersionUID = 3431522046169284463L; ! /** * Deserialization constructor (required). */ ! public MyStatus(){} ! public MyStatus(StatusType statusType) { --- 343,353 ---- */ private static final long serialVersionUID = 3431522046169284463L; ! /** * Deserialization constructor (required). */ ! public MyStatus() { ! } ! public MyStatus(StatusType statusType) { *************** *** 367,375 **** */ super(statusType); ! } ! } ! /** * {@link ServiceType} is abstract so a service basically needs to provide --- 357,365 ---- */ super(statusType); ! } ! } ! /** * {@link ServiceType} is abstract so a service basically needs to provide *************** *** 383,388 **** * </a> */ ! public static class MyServiceType extends ServiceType ! { /** --- 373,377 ---- * </a> */ ! public static class MyServiceType extends ServiceType { /** *************** *** 390,401 **** */ private static final long serialVersionUID = -2088608425852657477L; ! public String displayName; public String shortDescription; ! /** * Deserialization constructor (required). */ ! public MyServiceType() {} public MyServiceType(String displayName, String shortDescription) { --- 379,392 ---- */ private static final long serialVersionUID = -2088608425852657477L; ! public String displayName; + public String shortDescription; ! /** * Deserialization constructor (required). */ ! public MyServiceType() { ! } public MyServiceType(String displayName, String shortDescription) { *************** *** 403,443 **** this.shortDescription = shortDescription; } ! public String getDisplayName() { return displayName; } ! public String getShortDescription() { return shortDescription; } - - } - - /** - * The interfaces implemented by the service should be made locally - * available to the client so that it can execute methods on those - * interfaces without using reflection. - * - * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ - */ - public static interface ITestService - { - /** - * Method for testing remote invocation. - */ - public void invoke(); - } /** ! * The proxy object that gets passed around. ! * ! * @todo It appears that multiple instances of this class are getting ! * created. This is consistent with the notion that the instance is ! * being "passed" around by state and not by reference. This implies ! * that instances are not consumed when they are discovered but merely ! * cloned using Java serialization. * * @version $Id$ --- 394,417 ---- this.shortDescription = shortDescription; } ! public String getDisplayName() { return displayName; } ! public String getShortDescription() { return shortDescription; } } /** ! * The remote service implementation object. This implements the ! * {@link Remote} interface and uses JERI to create a proxy for the remote ! * object and configure and manage the protocol for communications between ! * the client (service proxy) and the remote object (the service ! * implementation). ! * <p> ! * Note: You have to implement {@link JoinAdmin} in order to show up as an ! * administerable service (blue folder) in the jini Service Browser. * * @version $Id$ *************** *** 445,449 **** * </a> */ ! public static class TestServerImpl implements ITestService, Serializable { --- 419,423 ---- * </a> */ ! public static class TestServerImpl implements ProxyAccessor, ITestService/*, Serializable*/ { *************** *** 451,473 **** * Note: Mark the {@link Logger} as transient since we do NOT need to * serialize its state. */ ! public static final transient Logger log = Logger.getLogger(TestServerImpl.class); /** * */ ! private static final long serialVersionUID = -920558820563934297L; /** ! * De-serialization constructor (required). */ ! public TestServerImpl() { ! // System.err.println("Created: "+this); ! log.info("Created: "+this); } public void invoke() { ! // System.err.println("invoked: "+this); ! log.info("invoked: "+this); } --- 425,504 ---- * Note: Mark the {@link Logger} as transient since we do NOT need to * serialize its state. + * <p> + * + * @todo When the service uses a proxy and a remote communications + * protocol, the service instance is remote and this object is not + * instantiated on the client (test this hypothesis by removing + * log4j from the codebase). */ ! public static final transient Logger log = Logger ! .getLogger(TestServerImpl.class); ! ! private ITestService proxy; ! ! private Exporter exporter; /** + * Service constructor. * + * @todo modify to use ServiceStarter */ ! public TestServerImpl() { ! ! try { ! ! // @todo hardwired jeri exporter using TCP. ! exporter = new BasicJeriExporter(TcpServerEndpoint ! .getInstance(0), new BasicILFactory()); ! ! // export an object of this class ! proxy = (ITestService) exporter.export(this); ! log.info("Proxy is " + proxy + "(" + proxy.getClass() + ")"); ! ! } catch (Exception ex) { ! // @todo should we retry the operation? ! log.error(ex); ! throw new RuntimeException(ex); ! } ! ! log.info("Created: " + this); ! ! } ! ! public Object getProxy() { ! ! return proxy; ! ! } /** ! * Unexports the proxy. ! * ! * @param force ! * When true, the object is unexported even if there are ! * pending or in progress service requests. ! * ! * @return true iff the object is (or was) unexported. ! * ! * @see Exporter#unexport(boolean) */ ! public boolean unexport(boolean force) { ! ! if (exporter.unexport(true)) { ! ! proxy = null; ! ! return true; ! ! } ! ! return false; ! } public void invoke() { ! ! log.info("invoked: " + this); ! } |