103
1 Distributed Objects

Chapter4 RMI 2011

Embed Size (px)

Citation preview

Page 1: Chapter4 RMI 2011

1

Distributed Objects

Page 2: Chapter4 RMI 2011

2

In the Good Old Days...

Only local objects existedOnly local objects existed

My MachineMy Machine

My ObjectMy Object

Page 3: Chapter4 RMI 2011

3

Today’s World...

Network and Distributed ObjectsNetwork and Distributed Objects

My MachineMy Machine Remote Remote MachineMachine

Local Local ObjectsObjects Remote Remote

ObjectsObjects

Page 4: Chapter4 RMI 2011

4

Overview

• What options do I have for distributed application development?

• Developers who program using the Java programming language can choose several solutions for creating distributed applications programs.

1) Java RMI technology

2) Java IDL technology (for CORBA programmers)

3) Enterprise JavaBeans technology

In this section we shall be talking about Java RMI and IDL (Corba) technologies

Page 5: Chapter4 RMI 2011

5

JAVA RMI

Remote Method Invocation

Page 6: Chapter4 RMI 2011

6

Outline

1) RMI Concepts

2) RMI architecture

3) Implementing and running RMI system

4) Implementing activatable RMI server

5) Summary

Page 7: Chapter4 RMI 2011

7

Introduction

• Remote Method Invocation (RMI) technology was first introduced in JDK1.1.

• RMI allows programmers to develop distributed Java programs with the same syntax and semantics used for non-distributed programs.

• RMI is based on a similar, earlier technology for procedural programming called remote procedure call (RPC)

Page 8: Chapter4 RMI 2011

8

Introduction

Disadvantages of RPC

a) RPC supports a limited set of data types. Therefore it is not suitable for passing and returning Java Objects

b) RPC requires the programmer to learn a special interface definition language (IDL) to describe the functions that can be invoked remotely

Page 9: Chapter4 RMI 2011

9

Introduction

The RMI architecture defines

a) How objects behave.

b) How and when exceptions can occur.

c) How memory is managed.

d) How parameters are passed to, and returned from, remote methods.

The remote object model for Enterprise JavaBeans (EJB) is RMI- based.

Page 10: Chapter4 RMI 2011

10

Introduction

• RMI is designed for Java-to-Java distributed applications. RMI is simpler and easier to maintain than using socket.

• Other options for creating Java-to-non-Java distributed applications are:

a) Java Interface Definition Language (IDL)

b) Remote Method Invocation (RMI) over Internet Inter-ORB Protocol (IIOP) -- RMI-IIOP.

Page 11: Chapter4 RMI 2011

11

RMI architecture

• RMI allows the code that defines the behavior and the code that implements the behavior to remain separate and to run on separate JVMs.

• At client side, RMI uses interfaces to define behavior.• At server side, RMI uses classes to define

implementation.

Page 12: Chapter4 RMI 2011

12

RMI Layer

TCPRemote Reference Layer

Transport Layer

Java Virtual Machine

Client Object

Remote Reference Layer

Transport Layer

Java Virtual Machine

Stub

Remote Object

Skeleton

Page 13: Chapter4 RMI 2011

13

Remote Objects

• Remote Objects– Live on server– Accessed as if they were local

Page 14: Chapter4 RMI 2011

14

Remote Objects

Page 15: Chapter4 RMI 2011

16

Stubs and Skeletons

• Stub – lives on client– marshals argument data (serialization)– unmarshals results data (deserialization)

• Skeleton– lives on server– unmarshals argument data– marshals results data– receives requests from stub– delivers response to stub

Page 16: Chapter4 RMI 2011

17

Remote Reference Layer

• This layer provides a RemoteRef object that represents the link to the remote service implementation object.

• Encodes and decodes the on-wire protocol.

• Implements the remote object protocols (Unicast Remote Object/ activatable remote objects ).

Page 17: Chapter4 RMI 2011

18

Transport Layer

• The Transport Layer makes the connection between JVMs. All connections are stream-based network connections that use TCP/IP.

• Dispatching messages between stub and skeleton.

Page 18: Chapter4 RMI 2011

19

RMI Flow

Client Virtual Machine

Client

Server Virtual Machine

Stub

Remote Object

Skeleton

Registry Virtual Machine

“Fred”

Server

1

2

1. Server Creates Remote Object2. Server Registers Remote Object

Page 19: Chapter4 RMI 2011

20

RMI Flow

Client Virtual Machine

Client

Server Virtual Machine

Stub

Remote Object

Skeleton

Registry Virtual Machine

“Fred”

Server

4

3. Client requests object from Registry4. Registry returns remote reference(and stub gets created)

3

Page 20: Chapter4 RMI 2011

21

RMI Flow

Client Virtual Machine

Client

Server Virtual Machine

Stub

Remote Object

Skeleton

Registry Virtual Machine

“Fred”

Server

6

5. Client invokes stub method6. Stub talks to skeleton7. Skeleton invokes remote object method

5 7

Page 21: Chapter4 RMI 2011

22

The steps...

• Create the Interface to the server

• Create the Server

• Create the Client

• Compile the Interface (javac)

• Compile the Server (javac)

• Compile the Client (javac)

• Generate Stubs and Skeletons (rmic)

Page 22: Chapter4 RMI 2011

23

Part II: RMI Usage

Page 23: Chapter4 RMI 2011

24

Creating Remote Objects

• Define a Remote Interface– extends java.rmi.Remote

• Define a class that implements the Remote Interface– extends java.rmi.RemoteObject– or java.rmi.UnicastRemoteObject

Page 24: Chapter4 RMI 2011

25

Remote Interface Example

import java.rmi.*;

public interface Adder extends Remote

{

public int add(int x, int y)

throws RemoteException;

}

Page 25: Chapter4 RMI 2011

26

Remote Interface Example

• Remark:

• All the interface has to extend the java.rmi.Remote interface

• and all the methods has to declare that it may throw a RemoteException object.

Page 26: Chapter4 RMI 2011

27

Remote Class Example

• The implementation class may extend from the

java.rmi.server.UnicastRemoteObject to link into the RMI system.

• It must also provide an explicit default constructor throwing RemoteException. When this constructor calls super(), it activates code in UnicastRemoteObject that performs the RMI linking and remote object initialization.

Page 27: Chapter4 RMI 2011

28

Remote Class Example

import java.rmi.*;

import java.rmi.server.*;

public class AdderImpl extends UnicastRemoteObject implements Adder

{

public AdderImpl() throws RemoteException

{

super();

}

public int add(int x, int y)

throws RemoteException

{

return x + y;

}

}

Extend UnicastRemoteObjectand implemet Adder InterfactExtend UnicastRemoteObjectand implemet Adder Interfact

Implement all methodsfrom interface Hello.javaImplement all methods

from interface Hello.java

Page 28: Chapter4 RMI 2011

29

Compiling Remote Classes

• Compile the Java class– javac

• reads .java file• produces .class file

• Compile the Stub and Skeleton– rmic

• reads .class file• produces _Skel.class and _Stub.class

Page 29: Chapter4 RMI 2011

30

Compiling Remote Classes (Diagram)

Adder.java(interface)

Adder.class(interface classfile)

javac

AdderImpl.java(remote class)

AdderImpl.class(classfile)

javacrmic

AdderImpl_Skel.class(skeleton classfile)

AdderImpl_Stub.class(stub classfile)

rmic –v1.1 –classpath “…..\RMI” –d “….\RMI” AdderImpl

Page 30: Chapter4 RMI 2011

31

Registering Remote Classes

• start the registry– running process

• Windows: start rmiregistry

You can also bind rmiregistry to a different port by indicating the new port number as :

start rmiregistry <new port>

(uses port 1099 by default)

Page 31: Chapter4 RMI 2011

32

Create the server

• Creates a new instance of the remote object

• Registers it in the registry with a unique name

Page 32: Chapter4 RMI 2011

33

RMI Server Example

public class RMIServer {

public static void main(String []args) throws RemoteException, MalformedURLException, AlreadyBoundException

{

try{

// LocateRegistry.createRegistry(1099);

AdderImpl adder = new AdderImpl();

System.out.println("Server has started");

Naming.bind (“rmi://localhost/adder", adder);

System.out.println("Adder bound");

}catch (Exception e)

{

System.out.println ("Trouble: " + e);

}

}

}

import java.rmi.AlreadyBoundException;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.Naming;import java.net.MalformedURLException;

Instantiate a new object and register (bind it) in the ”rmiregistry”

Instantiate a new object and register (bind it) in the ”rmiregistry”

Registering Remote ClassesRegistering Remote Classes

Start rmicregistry.exe

Page 33: Chapter4 RMI 2011

34

RMI URLs

rmi://host[:port]/name• default port is 1099

• Specifies hostname of registry

• can also use relative URLs – name only– assumes registry is on local host

Page 34: Chapter4 RMI 2011

35

Creating an RMI Client

1) In the client’s code, all you need to do is to lookup the object and use, it’s methods as local methods.

2) The client’s code may look like the following:

Page 35: Chapter4 RMI 2011

36

RMI Client Example

import java.rmi.Naming;

import java.rmi.NotBoundException;

import java.util.Scanner;

import java.io.*;

public class RMIClient {

public static void main(String[] args) throws NotBoundException, IOException {

Adder a = (Adder) Naming.lookup("rmi://localhost/adder");

int sum = a.add(2,2);

System.out.println("2+2=" + sum);

}

}

”lookup” the RMIServer – and call Method adder() on Stub

”lookup” the RMIServer – and call Method adder() on Stub

Page 36: Chapter4 RMI 2011

37

RMI URLs

rmi://host[:port]/name• default port is 1099

• Specifies hostname of registry

• can also use relative URLs – name only– assumes registry is on local host

Remember – that the stuband skeleton classes get generated

by the ”rmic” compiler

Remember – that the stuband skeleton classes get generated

by the ”rmic” compiler

Page 37: Chapter4 RMI 2011

38

Steps for Developing an RMI System

1. Define the remote interface

2. Develop the remote object by implementing the remote interface.

3. Develop the client program.

4. Compile the Java source files.

5. Generate the client stubs and server skeletons.

6. Start the RMI registry.

7. Start the remote server objects.

8. Run the client

Page 38: Chapter4 RMI 2011

39

Lab Work: RMI System

1) Please follow what we have discussed to develop a RMI server which hosts a service for calculating the square root of a number.

2) Compile your RMI server and generate the corresponding stub class.

3) Create a client to test the RMI service.

Page 39: Chapter4 RMI 2011

40

Passing Parameters

• All parameters passed from an RMI client to an RMI server must either be serializable or be a remote object.

• For serializable: a) Data is extracted from the local object and

sent across the network to the remote server. b) Object is then reconstructed in the remote

server. c) Any changes to the object in the

RMIServer will not be reflected in the object held in the RMI client and vice versa.

Page 40: Chapter4 RMI 2011

41

Passing Parameters

• For a remote object:

a)Stub information, not a copy of data, is actually sent over RMI.

b)Any call made to the parameter object become a remote calls back to the actual object.

c)Changes made in one JVM are reflected in the original JVM.

Page 41: Chapter4 RMI 2011

42

Conditions for serializability

If an object is to be serialized:

a) The class must be declared as public

b) The class must implement java.io.Serializable interface are marked as serializable

c) The class must have a default (no-argument) constructor

d) All fields of the class must be serializable: either primitive types or serializable objects.

Page 42: Chapter4 RMI 2011

43

Remote interfaces and class

Page 43: Chapter4 RMI 2011

44

Security

• Your program should guarantee that the classes that get loaded do not perform operations that they are not allowed to perform.

• A more conservative security manager than the default should be installed. The following code should be added to the main method of the server and client program:

Page 44: Chapter4 RMI 2011

45

RMI Server Example

import java.rmi.RMISecurityManager;public class RMIServer {

public static void main(String []args) throws RemoteException, MalformedURLException, AlreadyBoundException

{

// Create and install a security manager

if (System.getSecurityManager() == null) {

System.setSecurityManager(new RMISecurityManager()); }

}

}

Page 45: Chapter4 RMI 2011

46

RMISecurityManager

• Easiest way to do this is to use java.rmi.RMISecurityManager as:

System.setSecurityManager(new RMISecurityManager());

• This by default restricts all code from making socket connections.

• Obviously this is too strict. Need a policy file to allow client to make network connection to rmi port. It would look something like:grant{ permission java.net.SocketPermission “*:1024-65535”, “connect”}

java Client –Djava.security.policy=“file_policy”

Page 46: Chapter4 RMI 2011

47

Activatable Server

• Before Java 2, the UnicastRemoteObject could be accessed only from a server program that created instances of the object and ran all the time.

• With Java 2 we got the Activatable and the rmid daemon.

• An activatable class needs only to be registered with the rmid.

• This is an advantage for systems that have many remote object classes but only a few of them are active at any one time. They save memory (and so gain performance).

Page 47: Chapter4 RMI 2011

48

Activatable Server

• Enable server programs to wake up and start to run when they are needed.

• Java RMI Activation System Deamon (RMID) is introduced to handle this task.

• When a client requests a reference to the server from the rmiregistry, the rmid program, which holds the servers details, will be requested to start up the server and return the reference to the client. After that, the rmiregistry will be able to provide the reference of the server directly.

Page 48: Chapter4 RMI 2011

49

MyRemoteInterface.java

import java.rmi.*;

public interface MyRemoteInterface extends Remote {

public Object callMeRemotely() throws RemoteException;

}

Page 49: Chapter4 RMI 2011

50

Creating the implementation class

• Step 1: Make the appropriate imports in the implementation class import java.rmi.*;

import java.rmi.activation.*; • Step 2:

Extend your class from java.rmi.activation.Activatable

public class ActivatableImplementation extends Activatable implements MyRemoteInterface {

Page 50: Chapter4 RMI 2011

51

Creating the implementation class

• Step 3: Declare a two-argument constructor in the implementation class

public ActivatableImplementation(ActivationID id, MarshalledObject data) throws RemoteException {

// Register the object with the activation system

// then export it on an anonymous port

super(id, 0);

}

The super(id, 0) method calls Activatable constructor to pass an activation ID and a port number. In this case, the port number is default 1099.

Page 51: Chapter4 RMI 2011

52

Creating the implementation class

• Step 4: Implement the remote interface method(s)

public Object callMeRemotely() throws RemoteException {

return "Success";

}

Page 52: Chapter4 RMI 2011

53

ActivatableImplementation.java

Page 53: Chapter4 RMI 2011

Activatable Server: Setup

Page 54: Chapter4 RMI 2011

Activatable Server: Setup

Page 55: Chapter4 RMI 2011

Activatable Server: Setup

Page 56: Chapter4 RMI 2011

Activatable Server: Setup

Page 57: Chapter4 RMI 2011

58

Compile and Run

1. Compile all the classes use javac.

2. Run rmic on the implementation class

3. Start rmi registry use rmiregistry.

Note that if you use jdk version below 1.5.0, you may need to regenerate stub class first by using command

below before start the rmiregistry.

rmic -v1.2 <implement of Interface>

rmic –v1.2 ActivatableImplementation

Page 58: Chapter4 RMI 2011

Compile and Run

Page 59: Chapter4 RMI 2011

Compile and Run

Page 60: Chapter4 RMI 2011

Compile and Run

Page 61: Chapter4 RMI 2011

Compile and Run

Page 62: Chapter4 RMI 2011

63

Example

http://www.javacamp.org/moreclasses/rmi/rmi23.html

Page 63: Chapter4 RMI 2011
Page 64: Chapter4 RMI 2011

65

java.rmi.activation.Activatable 1.2

protected Activatable(ActivationID id, int port)• Constructs the activatable object and establishes a listener on

the given port. Use 0 for the port to have a port assigned automatically.

static Remote exportObject(Remote obj, ActivationID id, int port)

• Makes a remote object activatable. Returns the activation receiver that should be made available to remote callers. Use 0 for the port to have a port assigned automatically.

static Remote register(ActivationDescriptor desc)• registers the descriptor for an activatable object and prepares it

for receiving remote calls. Returns the activation receiver that should be made available to remote callers.

Page 65: Chapter4 RMI 2011

66

java.rmi.MarshalledObject 1.2

MarshalledObject(Object obj)

• constructs an object containing the serialized data of a given object.

Object get()

• deserializes the stored object data and returns the object.

Page 66: Chapter4 RMI 2011

67

java.rmi.activation.ActivationGroupDesc 1.2

ActivationGroupDesc(Properties props, ActivationGroupDesc.CommandEnvironment env)

• constructs an activation group descriptor that specifies virtual machine properties for a virtual machine that hosts activated objects. The env parameter contains the path to the virtual machine executable and command-line options, or it is null if no special settings are required.

Page 67: Chapter4 RMI 2011

68

java.rmi.activation.ActivationGroup 1.2

static ActivationSystem getSystem()

• returns a reference to the activation system.

Page 68: Chapter4 RMI 2011

69

java.rmi.activation.ActivationSystem 1.2

ActivationGroupID registerGroup ( ActivationGroupDesc group)

• registers an activation group and returns the group ID.

Page 69: Chapter4 RMI 2011

70

java.rmi.activation.ActivationDesc 1.2

ActivationDesc(ActivationGroupID id, String className, String classFileURL, MarshalledObject data)

• constructs an activation descriptor.

Page 70: Chapter4 RMI 2011

Converting UnicastRemoteObject to Activatable

If you already have a UnicastRemoteObject and want to make it Activatable you just have to make some small changes to the implementation class.

1. Make the appropriate imports. 2. Make the class extend Activatable. 3. Remove the no-argument constructor. 4. Declare a two argument constructor.

You then need to create a setup program just like before.

Page 71: Chapter4 RMI 2011

• Using Remote Method Invocation to ImplementCallbacks

Page 72: Chapter4 RMI 2011

73

Polling vs. Callback

In the absence of callback, a client will have to poll a passive server repeatedly if it needs to be notified that an event has occurred at the server end.

S e rv e r

C lie n t

...

P o lling

S e rv e r

C lie n t

C a llba c k

A clie n t is s u e s a re qu e s t to th es e rv e r re pe a te dly u n t il th ede s ire d re s po n s e is o bta in e d.

A clie n t re g is te rs it s e lf with th es e rv e r, a n d wa it u n t il th e s e rv e rca lls ba ck .

a re m o te m e th o d ca ll

Page 73: Chapter4 RMI 2011

74

RMI Callbacks

• A callback client registers itself with an RMI server.• The server makes a callback to each registered client upon

the occurrence of a certain event.

T h e c a llb ac k lis t

C 1

C 2

C 3

C 4

C 5

c allb ac k

S e rv e rC lie n ts

R M I c a lls

Page 74: Chapter4 RMI 2011

75

Callback Client-Server InteractionsC lie n t h o s t

S e rv e r h o s t

R M I r eg is tr y

S o m eS er v er . c las s

S o m eI n ter f ac e_ s tu b .c las s

S o m eI n ter f ac e_ s k el. c las s

C lien t. c las s12

1 . C lie n t lo o k s u p th e in te rfa ce o bje ct in th e R M I re g is try o n th e s e rv e r h o s t .2 . Th e R M I R e g is try re tu rn s a re m o te re fe re n ce to th e in te rfa ce o bje ct .3 . V ia th e s e rv e r s tu b, th e c lie n t pro ce s s in v o k e s a re m o te m e th o d to re g is te r it s e lf fo r ca llba ck , pa s s in g a re m o te re fe re n ce to it s e lf to th e s e rv e r. Th e s e rv e r s a v e s th e re fe re n ce in it s ca llba ck lis t .4 . V ia th e s e rv e r s tu b, th e c lie n t pro ce s s in te ra ct s with th e s k e le to n o f th e in te rfa ce o bje ct to a cce s s th e m e th o ds in th e in te rfa ce o bje ct .5 . W h e n th e a n t ic ipa te d e v e n t ta k e s pla ce , th e s e rv e r m a k e s a ca llba ck to e a ch re g is te re d c lie n t v ia th e ca llba ck in te rfa ce s tu b o n th e s e rv e r s ide a n d th e ca llba ck in te rfa ce s k e le to n o n th e c lie n t s ide .

X

C allb ac k I n ter f ac e_ s k el. c las s

C allb ac k I n ter f ac e_ s tu b .c las s5

3 ,4

Page 75: Chapter4 RMI 2011

76

Callback application files

C lie n t .c la s s

C l i e n tIn te rface .cl as s

S e rve rIn te rface .cl as s

C lie n t I m pl.cla s s

S e rve rIm pl _S tu b.cl as s

C l i e n tIm pl _s k e l .cl as s

O bje ct c lie n t h o s t

o bje ct c lie n t dire cto ry

S e rv e r.cla s s

S e rve rIn te rface .cl as s

C l i e n tIn te rface .cl as s

S e rv e rI m pl.c la s s

C l i e n tIm pl _S tu b.cl as s

S e rve rIm pl _s k e l .cl as s

O bje ct s e rv e r h o s t

o bje ct s e rv e r dire cto ry

Page 76: Chapter4 RMI 2011

Implementation

Page 77: Chapter4 RMI 2011

Defining the Listener Interface

• defines a remote object with methods

• method should be invoked by an event source whenever an event occurs, so as to act as notification that the event occurred.

Page 78: Chapter4 RMI 2011

Object-Oriented Callbacks

Page 79: Chapter4 RMI 2011

Callback notification of event, for every registered listener

Page 80: Chapter4 RMI 2011

Callback implemented by invoking a method on a listening object

Page 81: Chapter4 RMI 2011

RMI Callbacks

• Listener interface and the event source must be implemented as an RMI service.

• For the listener – to register itself with the remote event source, it

must invoke a remote method and pass an object reference to the remote listener interface it defines.

Page 82: Chapter4 RMI 2011

Defining the Listener Interface

Page 83: Chapter4 RMI 2011

Defining the Event Source Interface

• event source must allow a listener to be registered and unregistered, and may optionally provide additional methods

Page 84: Chapter4 RMI 2011

Defining the Event Source Interface

Page 85: Chapter4 RMI 2011

Implementing Event Source Interface

• implement TemperatureSensorServer class– RMI server.

• server must – extend UnicastRemoteObject, to offer a– implement Temperature Sensor interface

Page 86: Chapter4 RMI 2011

Implementing Event Source Interface

Page 87: Chapter4 RMI 2011

Implementing Event Source Interface

Page 88: Chapter4 RMI 2011

Implementing Event Source Interface

Page 89: Chapter4 RMI 2011

Implementing Event Source Interface

Page 90: Chapter4 RMI 2011

Implementing Event Source Interface

Page 91: Chapter4 RMI 2011

Implementing Event Source Interface

Page 92: Chapter4 RMI 2011

Implementing Event Source Interface

Page 93: Chapter4 RMI 2011

Implementing the Listener Interface

• implement the TemperatureListener interface,

• register itself with the remote temperature sensor service,

• client will be notified of changes as they occur, using a remote callback

Page 94: Chapter4 RMI 2011

Implementing the Listener Interface

Page 95: Chapter4 RMI 2011

Implementing the Listener Interface

Page 96: Chapter4 RMI 2011

Implementing the Listener Interface

Page 97: Chapter4 RMI 2011

Implementing the Listener Interface

Page 98: Chapter4 RMI 2011

Running the Callback Example

Page 99: Chapter4 RMI 2011

100

RMI Components

• java.rmi: client-side RMI classes, interfaces, and exceptions

• java.rmi.server: server-side RMI classes, interfaces, and exceptions

• java.rmi.registry: Classes for naming services

• java.rmi.dgc: distribute garbage collection

Page 100: Chapter4 RMI 2011

101

• java.rmi.activation: Implements activate on demand RMI services. Objects instantiated on-demand by client-requests. References persistent over server crashes.

• rmic: compiler to generate stubs and skeletons

• rmiregistry: Utility server that provides naming service for RMI. Associates names with objects

• rmid: utility server to RMI activation framework

RMI Server Properties

Page 101: Chapter4 RMI 2011

102

RMI Server Properties

• java.rmi.server.codebase: a url indicating code base from which classes should be loaded to network clients

• java.rmi.server.disableHttp: if true, RMI will not use Http to try to tunnel through firewalls. Default is false, meaning that Http wraps RMI calls

Page 102: Chapter4 RMI 2011

103

• java.rmi.server.hostname: sets servers fully qualified host name, if name unavailable via DNS

• java.rmi.server.logCalls: if true, RMI will log information about calls. Default is false.

• java.rmi.dgc.leaseValue: The time in milliseconds until server notices client is no longer connected. Default is 10 minutes.

RMI Server Properties

Page 103: Chapter4 RMI 2011

104

RMI Naming Methods• Remote lookup(String name): Look up remote object

by URL and return it• bind(String name, Remote obj): bind an object to a

specific URL• unbind(String name): unbind an object at a URL• rebind(String name, Remote obj): Replace the object

currently bound with a new one• String[] list(String name): list of URL’s from specified

Registry