`
`23
`
`ServiceRegistrar[] regs= ev.getRegistrars();
`for (inti= 0; i < regs.length; i++)
`registrars.remove(regs[i]) ;
`notifyAll(); II notify waiters that the list has changed
`
`}
`
`Each invocation of discovered represents one or more newly discovered lookup
`services. Our implementation gets the array of Servi ceRegi strar objects (the
`lookup service's primary interface) and adds each to the list of known registrars.
`When it is complete, it invokes noti fyA 11 in case searchDi scove red is blocked
`waiting for the list to have some elements. Our discarded irnple:mentation
`removes elements from the list.
`The searchDi scovered method invoked by execute loops checking out
`members of that list until it finds a matching service or until MAX_WAIT millisec(cid:173)
`onds have passed:
`private List regist rars= new LinkedList();
`
`private final static int MAX_WAIT = 5000;
`
`II five seconds
`
`private synchronized void searchDiscovered()
`throws Exception
`
`{
`
`ServiceTemplate serviceTmpl = bui l dTmpl(typeArgs);
`
`II Loop searching in discovered lookup services
`long end= System.currentTimeMillis() + MAX_WAIT ;;
`for(::){
`II wait until a lookup is discovered or time expires
`long timeleft = end - System . currentTimeMillis();
`while (timeleft > 0 && registrars.isEmpty()) {
`wait(timeleft);
`timeLeft = end - System.currentTimeMillis():
`
`}
`if (timeleft <= 0)
`break ;
`
`II Check out the next lookup service
`ServiceRegistrar reg=
`(ServiceRegistrar)registrars . remove(0);
`try {
`MessageStream stream=
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 41
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`THE CLIENT
`
`THE JlNl ARC,
`
`(MessageStream)reg.lookup(serviceTmpl );
`if (stream!= null) {
`readSt r eam(stream);
`return;
`
`}
`} catch (RemoteException e) {
`II skip on to next
`continue;
`
`}
`
`}
`System .err .printl n("No service found");
`II nothing happened in time
`System . exit(l);
`
`}
`
`First the method uses the command line arguments to build up a template. It then
`starts looping. Each time through the loop the list of registrars is checked. If it is
`empty, we wait until either the remaining time expires or the list ceases to be
`empty. During the invocation of wait the dis cove red method can be invoked by
`LookupDiscovery in its thread, adding registrars to the list. When registrars are
`added, the noti fyA 11 in the discovered method will allow the wa i t in
`searchDi scovered to return. The code in searchDi scovered then takes the
`first element from the list and asks it to look up a service that matches our tem(cid:173)
`plate. If it finds one, it asks read Stream to try and read messages from the stream
`(you will see readStream shortly).
`If readStream executes successfully, searchDi scovered will return, which
`signals successful execution. If searchDi scovered does not find a readable
`stream within the allotted time, it prints out an error message and exits with a non(cid:173)
`zero status, indicating failure of the command.
`The buildTmpl method creates the net.jini. lookup . Servi ceTemp,late
`object that is passed to the lookup service's lookup method. Let's look at how the
`template is built:
`
`private ServiceTemplate buildTmpl(String[J typeNames)
`throws ClassNotFoundException, IllegalAccessException,
`InstantiationException, NoSuchMethodException,
`InvocationTargetException
`
`{
`
`Set typeSet
`Set attrSet
`
`new HashSet();
`new HashSet();
`
`// service types
`// attribute objects
`
`II MessageStream class is always required
`typeSet.add(MessageStream.class);
`
`}
`
`}
`
`The bui l
`line. The
`name fol
`t ype(ar
`has an op
`the argur
`has been
`Cl ass ol
`so an ot
`method,
`must be
`port. W t
`and att
`priate a
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 42
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`THE JTNI ARCHITECTURE: AN INTRODUCTION
`
`25
`
`for (inti= 0; i < typeNames.length; i++) {
`// break the type name up into name and argument
`StringTokenizer tokens=
`// breaks up string
`new StringTokenizer(typeNames[i], ":");
`String typeName = tokens.nextToken();
`String arg = null;
`// string argument
`if (tokens. hasMoreTokens ())
`arg = tokens .nextToken();
`Class cl = Cl ass . forName(typeName);
`
`// test if it is a type of Entry (an attribute)
`if (Ent ry.class . isAssignableFrom(cl))
`attrSet . add(attribute(cl, arg));
`else
`typeSet.add(cl);
`
`}
`
`// create the arrays from the sets
`Entry [] attrs = (Entry[])
`attrSet .toArray(new Entry[attrSet.size()]);
`Class[] types= (Class[])
`typeSet.toArray(new Class[typeSet.size()]);
`
`return new ServiceTemplate(null, types, attrs);
`
`}
`
`The bui l dTmp l method loops through the type arguments given on the command
`line. The argUJm:nts can be either a type name or, in the case of attributes, a type
`name followed by a String argument to pass to the constructor, of the form
`type(arg). The first part of the loop takes the name and checks to see whether it
`has an open parenthesis. If it does, it strips any closing parenthesis and remembers
`the argument in the variable arg, which is otherwise null. Once any argument
`has been stripped off from the class name in cName, we translate the narm: inlo a
`Cl ass object for the type. If the type is assignable to Entry it is an attribute, and
`so an object is created of that attribute type, using arg if it was present-the
`method attribute (not shown) does this work. If it is not assignable to Entry, it
`must be a service type, and so we add its type to the types the service must sup(cid:173)
`port. When the loop is finished, typeset contains all the required service types
`and attrSet contains all the required attribute templates. We then create appro(cid:173)
`priate arrays from the contents of these sets and pass the arrays to the
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 43
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`26
`
`THE CLIENT
`
`Servi ceTempl ate constructor (the first null argument would be the service ID if
`we needed to match on a specific one).
`As you have seen, when searchDi scovered finds a matching service, it tries
`to read the stream by invoking the readStream method:
`private final static int MAX_RETRIES = 5;
`
`public void readStream(MessageStream stream)
`throws RemoteException
`
`{
`
`int errorCount = 0;
`II# of errors seen this message
`int msgNum = 0;
`II# of messages
`while (msgNum < count) {
`try {
`Object msg = stream.nextMessage();
`printMessage(msgNum, msg);
`II successful read
`msgNum++;
`errorCount = 0;
`II clear error count
`} catch (EOFException e) {
`System . out.println("-- -EOF---") ;
`break;
`} catch (RemoteException e) {
`e .pri ntStackTrace();
`if (++errorCount > MAX_RETRIES) {
`if (msgNum == 0)
`II got no messages
`throw e;
`else {
`System.err .println("too many error·s");
`System .exit(l);
`
`}
`
`}
`try {
`Thread . sleep(l000); II wait 1 second, retry
`} catch (InterruptedExcepti on ie) {
`System.err.println("---Interrupted.:.--");
`System.exit (1);
`
`}
`
`}
`
`}
`
`}
`
`THE J!Nl
`
`pul
`
`}
`
`The r E
`reads·
`ing on(
`gle me
`contint
`its fail1
`and a J
`ber of
`
`2.3
`
`Let us
`that cc
`(an int
`fortu
`condu,
`are fo1
`our di
`searc
`ing str
`it out.
`match
`A
`user s:
`attribl
`works
`will r
`proxy
`servic
`next ~
`Stre,
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 44
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`WE JIN! ARCHFFECTURE: AN llffRODUCf!ON
`
`27
`
`public void printMessage(int msgNum , Object msg) {
`if (msgNum > 0) // print separator
`System.out .println("---");
`System.out.printl n(msg);
`
`}
`The read St ream method will try to read the number of messages desired. If
`readStream gets a RemoteException, it retries up to MAX_RETRIES times,. wait(cid:173)
`ing one second (1,000 milliseconds) between each try. If it fai ls to read even a sin(cid:173)
`gle message it throws RemoteExcepti on, letting the loop in searchDi scovered
`continue looking for a usable stream. Jf it reads at least one message, it prints out
`its failure and exits, so that the user will not see some messages from one stream
`and a few more from the next one should a failure occur before the desired num(cid:173)
`ber of messages are read.
`
`2.3
`
`In Conclusion
`
`Let us revisit the example execution of StreamReader from page 2 1. If y,ou use
`that command line, the client will look for a fortune. FortuneStream service
`(an interface that we will define in the next section) with an attribute that is of type
`fortune. Fortune Theme created with the string "General". This search will be
`conducted in lookup services that manage the public group. If any such lookups
`are found, the LookupDi scovery utility object we created in execute will invoke
`our discovered method, which adds it to the list of known lookup services. The
`searchDi scovered method looks in each discovered lookup service for a m atch(cid:173)
`ing stream, and invokes readStream to read one message from a stream and print
`it out. When all this is complete, you should (assuming there is an avaiJable
`matching fortune cookie service) have a fortune cookie message on your screen.
`Again, notice that this client can work with any MessageStream service. The
`user specifies which particular service to use by the service's type and any desired
`attributes. Each message stream service implementation provides a proxy that
`works properly for the service's needs. The StreamReader client you have seen
`will print messages from any implementation of a message stream, using the
`proxy as an adaptor from the service definition (MessageStream) to the partic ular
`service that was matched (FortuneStream, ChatStream, or whatever). Y.ou will
`next see bow to write two different message stream services that can be used by
`StreamReader or any other MessageStream client.
`
`I
`
`I
`
`I
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 45
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`THE JIN! ARCHITECTURE: AN INTRODUCTION
`
`29
`
`3 Writing a Service
`
`Dare to be nai've.
`- R. Buckminster Fuller
`
`THE MessageStream interface is designed to work for many purposes. We will
`
`now show you two example implementations of a message stream service. The
`first will be a FortuneStream subinterface that returns randomly sekcted "for(cid:173)
`tune cookie" messages. The second will provide a chat stream that records a his(cid:173)
`tory of a conversation among several speakers. First, though, we must talk about
`what it means to be a Jini service.
`A service differs from a client in that a service registers a proxy object with a
`lookup service, thereby advertising its services-the interfaces and classes that
`make up its type. A client finds one or more services in a lookup service that it
`wants to use. Of course, a service might rely on other services and therefore be
`both a service and a client of those other services.
`
`3.1 Good Lookup Citizenship
`
`To be a usable service, the service implementation must register with appropriate
`lookup services. In other words, it must be a good lookup citizen, which means:
`
`• When starting, discovering lookup services of appropriate groups and regis(cid:173)
`tering with any that reply
`+ When running, listening for lookup service "here I am" message::s and, after
`filtering by group, registering with any new ones
`+ Remembering its join configuration-
`the list of groups it should join and the
`lookup locators for specific lookup services
`+ Remembering all attributes stamped on it and informing all lookups of
`changes in those attributes
`+ Maintaining all leases in lookup services for as long as the service is avail(cid:173)
`able
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 46
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`30
`
`THE FortuneSt,·eamSERVTCE
`
`+ Remembering the service ID assigned to the service by the first lookup ser(cid:173)
`vice, so that all registrations of the same service, no matter when made, will
`be under the same service ID
`
`3.1.1 The Joi nManager Utility
`
`Although the work for these tasks is not a vast amount of labor, it is also more
`than trivial. Services may provide these behaviors in a number of ways. The utility
`class com.sun.jini. lookup.JoinManage r (part of the first release ,of the Jini
`Technology Software Kit) handles most of these tasks on a service's behalf,
`except for the management of storage for attributes and service IDs whi,:::h the ser(cid:173)
`vice implementation must provide.
`Our example service implementations use Joi nManage r to manage lookup
`membership. You are not required to do so--you might find other mechanisms
`more to your liking, or you might want or need to invent your own.
`
`3.2 The FortuneStream Service
`
`Our first example service will extend MessageStream to provide a "fortune
`cookie" service, which returns a randomly selected message from a se:t of mes(cid:173)
`sages. Typically, such messages are intended to be amusing, informative, or
`inspiring. The collections are often broken up into various themes. The m ost gen(cid:173)
`eral theme is to be amusing, but collections drawn from particular television
`shows, movie types, comic strips, or inspirational speakers also exist. Our
`FortuneStream interface looks like this:
`
`package fortune;
`
`interface FortuneStream extends MessageStream, Remote {
`String getTheme() throws RemoteException;
`
`}
`
`As with all the classes defined in this example, this interface is in the fortune
`package. The FortuneStream interface extends the MessageStream interface
`because it is a particular kind of message stream. FortuneStream extends the
`interface Remote, which indicates to RMI
`that objects implementing the
`FortuneStream interface are accessible remotely using RMI.
`The getTheme method returns the theme of the particular stream. As you will
`see, the theme is primarily reflected as an attribute on the service so that a user can
`
`THE JIN/ 1
`
`select a
`added h
`Eac
`getThe
`stream 1
`
`put
`
`{
`
`}
`
`The F1
`of our
`of For
`Tl
`objecl
`conve
`Forti
`getTI
`strear
`it WO
`obtai
`F
`ment
`ing
`Abst
`impl
`troll1
`istra
`Se r 1
`cont
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 47
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`select a FortuneStream with a theme to their liking. The getThem1:? method is
`added here to allow queries after a stream has been selected.
`Each fortune stream's theme is represented both in the interface via the
`getTheme method and as an attribute in the lookup service to help users find a
`stream that gives the types of fortunes they want:
`public class FortuneTheme extends AbstractEnt ry
`implements ServiceControlled
`public String theme;
`
`{
`
`31
`
`public FortuneTheme() {}
`public FortuneTheme(String theme) {
`this.theme = t heme;
`}
`
`}
`
`The FortuneTheme attribute is part of the service definition, and is independent
`of our particular implementation of FortuneStream-a different implementation
`of FortuneStream would use the same attribute type.
`The Fortune Theme attribute fits the requirements for all entries: It has public
`object-typed fields and a public no-arg constructor. It adds another constructor for
`convenience. Each FortuneStream service expresses its theme . as both a
`FortuneTheme attribute and a value returned by the FortuneStream class's
`getTheme method. This redundancy has a purpose--it allows a client of .a fortune
`stream to be written independently of the code that finds the service. For example,
`it would be possible for a fortune stream client to display the theme of a stream it
`obtained without using a Fortune Theme attribute.
`FortuneTheme extends net.jini .entry.AbstractEntry, which imple(cid:173)
`ments Entry and provides useful semantics for entry classes, specifically in defin(cid:173)
`ing semantics for the equals, hashCode, and toStri ng methods. Using
`AbstractEntry is optional-we use it for convenience. FortuneTheme also
`implements Servi ceControlled, which marks the attribute as one that is con(cid:173)
`trolled by the service itself, as opposed to one placed on the service by an admin(cid:173)
`istrator. Any tools that let administrators modify attributes should not Jet
`Servi ceContro 11 ed attributes be changed. Only attributes that are exclusively
`controlled by the service itself should be marked with this interface.
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 48
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`32
`
`THE FortuneStreamSERVlCE
`
`3.2.1 The bnplementation Design
`
`The overall fortune service implementation looks like this:
`
`Lookup Service
`
`FortuneStreamimpl Stub
`
`FortuneStream
`Interface
`
`Client
`
`nextMessage
`
`fortunes
`
`TH
`
`str
`se
`
`ra
`d a
`d;:
`ye
`
`T
`d
`S(
`
`The running service is composed of three parts:
`
`• A database of fortunes, consisting of the collection of fortunes and position
`offsets for the start of each fortune. The position information is built by read(cid:173)
`ing the fortune collection.
`• ·A server that runs on the same system that contains the database. This server
`reads the database, choosing a fortune at random each time it needs to return
`the next message.
`
`• A proxy for the service. This proxy is the object installed in the lookup ser(cid:173)
`vice to represent the fortune stream service in the Jini system. In this pattic(cid:173)
`ular case, the proxy is simply a Java RMI stub that passes method invocations
`directly to the remote server.
`
`3.2.2 Creating the Service
`
`Our FortuneStream implementation is provided by the FortuneStreamimpl
`class, which is a Java Rl\fl remote object. Requests for the next message in the
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 49
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`. -----------------------------
`
`THE JIN/ ARCHITECTURE: AN INTRODUCTION
`
`33
`
`stream will be sent directly to this remote object that will return a random fortune
`selected from its database.
`The fortune database lives in a particular directory, which is set up by a sepa(cid:173)
`rate FortuneAdmi n program that creates the database of fortunes from the raw
`data. The FortuneAdmi n program is run before the service is created to set up the
`database a running FortuneStream service will use. When the database is ready,
`you will run FortuneStreamimpl to get the service going.
`The FortuneStreamAdmin command line looks like this:
`
`java [java-options] fortune.FortuneAdmin database-dir
`
`The database-di r parameter is the directory in which the database hves. This
`directory must initially contain a file named fortunes, which contains fortunes
`separated by lines that start with %%, as in:
`
`"As an adolescent I aspired to lasting fame, I craved
`factual certainty, and I thirsted for a meaningful vision
`of human life -- so I became a scientist. This is like
`becoming an archbishop so you can meet girls."
`Matt Cartmi 11
`
`%%
`As far as the laws of mathematics refer to reality, they
`are not certain, and as far as they are certain, they do
`not refer to reality.
`Albert Einstein
`
`%%
`As far as we know , our computer has never had an unde1cected
`error.
`
`The FortuneAdmi n program creates the position database in that directory if it
`does not already exist or if it is older than the fortune database file. The position
`database is stored in a file named pos. A typical invocation might look like this:
`
`java fortune.FortuneAdmin /files/fortunes/general
`
`FortuneAdmi n will look in the directory /fi les/fortunes/general for a
`fortunes file and will read it to create a/fi les/fort unes/general / pos file. 1
`The source to FortuneAdmi n just manipulates files, so we will not describe it
`here.
`
`1 On a Windows system it would be something like C: \files\ fortunes\gene ra·1; on a
`MacOS system it would be more like Hard Disk:fortunes:general. We use POSJX(cid:173)
`style paths in this book.
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 50
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`34
`
`THE FortuneStream SERVICE
`
`3.2.3 The Running Service
`
`The fortune service is started by the main method of FortuneStrea1mimpl. The
`command Jine looks like this:
`
`java [java-options] fortune.FortuneStreamimpl database-dir
`groups! 1ookup-ur1 theme
`
`The java-options must include a security policy file and the RMI server code(cid:173)
`base URL. The database-di r should be the directory given to For·tuneAdmi n.
`The running service will join lookup services with the given groups or the speci(cid:173)
`fied lookup service, with a FortuneTheme attribute with the given name. A typi(cid:173)
`cal invocation might look like this:
`
`java -Djava.security.policy=/file/policies/policy
`-Djava.rmi.server.codebase=http : //server/fortune-dl.jar
`fortune . FortuneStreamimpl /files/fortunes/general ""
`General
`
`Our implementation of the fortune stream service executes in the virtual
`machine this command creates, and therefore lives onJy as long as that virtual
`machine is running. Later you will see how to write services that live longer than
`the life of a single virtual machine.
`Here is the code that starts the service running:
`
`public class FortuneStreamimpl implements FortuneStream {
`private String [] groups = new String[0];
`private String lookupURL;
`private String dir;
`private String theme;
`private Random random = new Random();
`private long[] positions;
`private RandomAccessFile fortunes;
`private JoinManager joinMgr;
`
`public static void main(String[] args) throws Exception
`{
`
`FortuneStreamimpl f = new FortuneStreamimpl(args);
`f. execute() ;
`
`}
`
`II
`
`}
`
`r THEJI~
`
`Them
`tialize
`comrr
`methc
`
`p
`
`Firs1
`exp<
`the ,
`mac
`dies
`acfr
`vice
`st:n
`
`bas,
`ple:
`imI
`
`ide
`Jo-
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 51
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`THE J/Nl ARCHITECTURE: AN INTRODUCTION
`
`35
`
`The main method creates a FortuneStreamimpl object, whose constructor ini(cid:173)
`tializes the groups, l ookupURL, di r, theme, and i ni ti alAttrs fields from the
`command line arguments. The rest of the work is done in the object's execute
`method:
`
`private void execute() throws IOException {
`System.setSecurityManager(new RMISecurityManager());
`UnicastRemoteObject.exportObject(this);
`
`II Set up the fortune database
`setupFortunes ();
`
`II set our FortuneTheme attribute
`FortuneTheme themeAttr = new FortuneTheme(theme);
`Entry[] initialAttrs = new Entry[] { themeAttr };
`
`Lookuplocator[] locators = null;
`if (lookupURL != null) {
`Lookuplocator loc = new Lookuplocator(lookupURL);
`locators= new Lookuplocator [] { loc };
`
`}
`joinMgr = new JoinManager(this, initialAttrs,
`groups, locators, null, null);
`
`}
`
`First execute sets a security manager, as you saw done in the client. Next we
`export the FortuneStreamimpl object as an RMI object. Specifically, we export
`the object as a UnicastRemoteObject, which means that as long as this virtual
`machine is running, the object will be usable remotely. When the virtual machine
`dies, the remote object that it represents dies too. RMI provides a mechanism for
`activatable servers that will be restarted when necessary; most Jini software ser(cid:173)
`vices are actually best written as activatable services. You will see an activatable
`service in the next example.
`We then call setupFortunes to initialize this server's use of its fortune data(cid:173)
`base. We do not show the code for that here because it is not relevant to the exam(cid:173)
`ple; setupFortunes sets the positions and fortunes fields that are used by the
`implementation of nextMessage.
`The next two lines create the service-owned Fortune Theme attribute that will
`identify the theme of this fortune stream in the lookup service. Then we create the
`Joi nManager, which manages all the interactions with lookup services in the net-
`
`I
`I
`I
`I
`
`i'
`'
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 52
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`work. To do so, you must te11 the Joi nManager several things. The construct,or
`used by execute (there are others) talces the following parameters:
`
`THE FortuneStream SERVICE
`
`♦ The proxy object for the service. We use this because RMI will convert
`this to the remote stub for the FortuneStreamimpl object, which is what
`we want in this case. (FortuneStreamimpl implements a Remote inter(cid:173)
`face-FortuneStream extends Remote-so when a FortuneStreamimpl
`object is marshalled, it gets replaced by its stub.)
`♦ An Entry array that is the initial set of attributes to be associated with the
`service. Here we provide an array that contains only our Fortune Theme.
`♦ A String array that is the initial set of lookup groups. In our case this will
`be talcen from the command line and be either an array of the groups speci(cid:173)
`fied or an empty array if a URL was specified instead.
`
`♦ A net . ji ni. discovery. Lookuplocator array. Lookuplocator is a
`class that locates lookup services by URL. The array has a Lookuplocatc,r
`for the URL specified, or null if groups were specified instead.
`♦ A com. sun . j i ni . lookup . Servi ceIDLi stener object. The interface
`Servi ceIDL i stener provides a method to be caUed when the service's ID
`is assigned. This is a hook that lets the service store its ID persistently if it
`needs to. Since our particular service does not outlive its virtual machine
`there is no need to store the ID. We therefore pass null , meaning the service
`will not be notified. (The next example will show this feature in action.)
`• A com . sun. j i ni . lease . LeaseRenewa l Manager object
`to manage
`renewing the leases returned by lookup services. We use nul 1, which tells
`the Joi nManager to create and use its own LeaseRenewalManager. In
`another situation (for example, exporting multiple services in the same vir(cid:173)
`tual machine) you might want to specify this parameter (in our example, by
`using the same object in each service's Joi nManager to reduce the numbeir
`of lease manager objects).
`
`When execute is finished we have a service ready to receive messages and,
`)Y virtue of its Joi nManage r, the service registers with all appropriate lookup ser(cid:173)
`,ices and will continue to register appropriately so as long as the service is run(cid:173)
`ling. In other words, at this point we have a running Jini service. When execute
`·eturns, so does main. RMI will keep the virtual machine running in another
`bread, waiting to receive requests.
`The rest of the code implements nextMessage by picking a random fortune
`md getTheme by returning the theme field. Again, since these parts show no Jini
`:ervice code, we leave them to Appendix B.
`
`THE JIN! ARCH/TE•
`
`3.3 The Cl
`
`For a more inv,
`the utterances ,
`there must be a
`at random, so ,
`will want the n
`Consider \11
`occurs. Either c
`
`♦ Thenetv
`
`Client [
`
`♦ Thereq1
`respons1
`
`Client [
`
`These are ver
`guish betweer
`was stored at
`either messag
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 53
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`THE JIN/ ARCHITECfURE: AN INTRODUCTION
`
`3.3 The ChatStream Service
`
`37
`
`For a more involved example, we provide a message stream whose messages are
`the utterances of people in a conversation, such as in a chat room. In this case
`there must be an order to the messages. The fortune stream was picking a message
`at random, so any message was as good as any other. For a conversation clients
`will want the messages in the order in which they were spoken.
`Consider what happens when nextMessage is invoked and a network failure
`occurs. Either of two interesting situations may have occurred:
`
`• The network failure prevented the request from getting to the remove server:
`
`Network Failure
`
`Client
`
`Server
`
`• The request made it to the remote server, but the network failure blocked the
`response:
`
`Client
`
`Server
`
`Network Failure
`
`These are very different situations, but the client has no possible way to distin(cid:173)
`guish between the two cases. If the current position in the stream for each client
`was stored at the server, the next call to nextMessage by the client could return
`either message 29 (in the first case, in which the server never got the ,::iriginal,
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 54
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`THE ChatStreamSERVICE
`
`failed request) or message 30 (in the second case, in which the server thought it
`had returned message 29 but it didn't get to the client).
`The nextMessage method of MessageStream is documented to be idempo(cid:173)
`tent, that is, it can be re-invoked after an error to get the same result that would
`have come had there been no error. For FortuneStream idempotency was easy(cid:173)
`the fortune was picked at random, so the next message will be equally random, no
`matter which of the failure situations actually happened.
`But for ChatStream, this is not good enough. If the proxy was designed
`nai:Vely, an utterance might be skipped, and the utterance skipped could be the
`most important one of the discussion. If a call to nextMessage throws an excep(cid:173)
`tion because of a communication failure, the next time the client invokes
`nextMessage it should get the same message from the list that it would have got(cid:173)
`ten on the previous call had there been no failure. Suppose, for example, that we
`used the same strategy for a ChatStream proxy that we did for the
`FortuneStreamimpl proxy-an RMI stub. Then, after getting message number
`28 from the server, a network exception is thrown when trying to get message
`number 29 .
`So the proxy object registered with lookup services for a ChatStream cannot
`be a simple RMI stub. It must contain enough state to help the service return the
`right message even in the face of a network failure. To accomplish this, the proxy
`object will implement the ChatStream interface for the client to use, but the
`server will have an implementation-specific interface that the proxy uses to tell. the
`server which message should be next. It will look like this:
`
`Lookup Service
`
`Chat Proxy
`
`ChatStream
`Interface
`
`ChatServer
`'----~-Interface
`
`ChatServerimpl
`
`Client
`
`nextMessage
`
`j
`
`Chat
`History
`
`r THE JIN/ ARCTilTE(
`
`The proxy will
`cessfully retrie\
`interface. That i
`the ChatStrea1
`maintain the id1
`The Chats
`inherits nextM1
`ods of its own:
`
`package c
`
`public ir
`publ ·
`
`publ ·
`publ ·
`
`}
`
`Like all the cc
`method lets p(
`is the name of
`what the subje
`These last twc
`used to look u
`When arr
`
`public <
`pri,
`pri,
`
`pub·
`
`}
`
`pub
`
`pub
`
`pub
`
`Smart Mobile Technologies LLC, Exhibit 2002
`Page 2002 - 55
`IPR2022-00807, Apple Inc. et al. v. Smart Mobile Technologies LLC
`
`
`
`THE JINI ARCHITECTURE: AN INTRODUCTION
`
`39
`
`The proxy will use its internal stored state (the number of the last message suc(cid:173)
`cessfully retrieved) as an argument to the nextinL i ne method of the ChatServer
`interface. That method is hidden from the client, and different implementations of
`the ChatStream service are welcome to use a different mechanism so long as they
`maintain the idempotency of nextMessage.
`The ChatStream interface-the public service interface that the clients use(cid:173)
`inherits nextMessage from the MessageStream interfaces, and adds· a few meth(cid:173)
`ods of its own:
`
`package chat;
`
`public interface ChatStream extends MessageStream {
`public void add(Stri ng speaker , String[] message)
`throws Remote Exception;
`public String getSubject() throws RemoteException;
`public Stri ng[] getSpeakers() throws RemoteException;
`
`}
`
`Like all the code in this example this class is part of the chat package. The add
`method lets people add new messages to the discussion. The speaker parameter
`is the name of the speaker; message is what they say. You can ask a ChatStream
`what the subject of the chat is, and for the names of the people who have spoken.
`These last two things are also stored as attributes of the service so they can be
`used to look up streams.
`When a message is read, it will be a ChatMessage object:
`
`public class ChatMessage implements Serializable {
`private Stri ng speaker;
`private St ring[] content;
`
`public ChatMessage(String speaker, String[] content) {
`this . speaker
`speaker;
`this.content= content;
`
`}
`
`public String getSpeaker() { return speaker; }
`
`public String[] getContent() { return content; }
`
`public String toString() {
`StringBuffer buf = new Str