Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 71 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
71
Dung lượng
393,7 KB
Nội dung
The Client The Client is just a class for exercising these Calculator services. Its only real method is getAndDisplayResult(), which takes a Calculator along with the two operands. It then asks the Calculator for the operation name and will get "sum" if the Calculator is an Adder and "difference" if the Calculator is a Subtractor. It then gets the results of the calculation and displays them. You can already view Adder and Subtractor as services and see how you could easily extend the application to include other operations. package NonDistributedCalculator; public class Client { public void getAndDisplayResult(Calculator calculator, int firstOperand, int secondOperand){ String operationName = calculator.getOperationName(); int operationResult = calculator.getValueOfResult(firstOperand, secondOperand); System.out.println("The "+operationName + " of " + firstOperand + " and " + secondOperand + " is " + operationResult); } public static void main(String[] args){ Client client = new Client(); client.getAndDisplayResult(new Adder(), 5, 6); client.getAndDisplayResult(new Subtractor(), 24,7); } } In the next section, you'll download and install Jini and get it configured and running. You'll then return to this example and convert it to a set of Jini services and a client. Getting Jini Up and Running You may remember from Chapter 15 that getting all the RMI services running properly is difficult. For the most part, the Jini community has addressed that issue by creating a version that is easy to install and to run. Note As with RMI, it is a good idea to run these examples on at least two different machines, each of which is connected to a network (an internal network is fine). You may recall that when you ran RMI examples in which the client and server code were in the same file or even on the same machine, shortcuts were taken. If you aren't able to develop on two different machines, at least test in such a setup before deploying. Installing Jini Download the latest version of the Jini Technology Starter kit by following the links from http://java.sun.com/jini. (In this chapter, I use version 1.2 beta in all the examples.) Unzip the distribution. The code in this chapter was tested on a Windows box and on a UNIX box (actually a Mac running OS X). In each case, I unzipped the distribution into a directory named files. On the Windows machine, this directory is Chapter 20: Why Dream of Jini? 489 C:\files, and on the Mac, it is <home directory>/files. This isn't a huge point, but it will help you see how to adjust the configuration file to your own settings. The instructions for the rest of the chapter are given in terms of the Windows installation on a single machine. Jini actually runs more easily on a Mac. In particular, if you want to develop Jini applications on a Windows machine that isn't connected to the network, you'll have to look around the Jini FAQs for the latest information on how to configure your computer. Other books give the exact same directions twice, once for Windows users and once for UNIX users. The differences are mainly that Windows bat files are replaced by UNIX shell scripts and that the paths have to be altered in the usual ways. That is, the base of the path depends on where you install Jini and your other files, and the direction of the separators changes from \ on Windows to /on UNIX. Create two subfolders inside the C:\J2EEBible directory. Name one of them CalculatorClient and the other CalculatorService. Again, you may want to have CalculatorClient on one machine and CalculatorService on another. As a final step, you'll follow the directions in the next paragraph to place two files in your CalculatorClient directory that you'll need later on. (These instructions are included here and not later so that when you install Jini on another machine and something isn't quite working right, you'll find them and say, "Oh yeah, that's right.") Open up a command window and navigate into CalculatorService. You are going to pull a single file from each of two jar files in the Jini distribution. You'll use the jar utility and specify the path to the jar files and the actual class files you're looking for. Type in the following: jar xvf C:\files\jini1_2\lib\jini−ext.jar net\jini\lookup\ServiceDiscoveryManager$LookupCacheImpl$Lookup Listener_Stub.class There is a space between jar and net and not the line break that you see in the preceding code. You should type your command in all on a single line. You have specified that you are extracting a particular file and that you want verbose output. Of course, UNIX users should reverse the direction of the slashes and adjust the file location of jini−ext.jar to agree with their installation. You should see the following response: extracted net\jini\lookup\ServiceDiscoveryManager$LookupCacheImpl$Lookup Listener_Stub.class Extract the other class with this command: jar xvf C:\files\jini1_2\lib\jini−core.jar net\jini\core\event\RemoteEventListener.class. You will get feedback telling you that the class had been extracted. You're now ready to run the GUI tool. The GUI tool You can set up the various Jini components from the command line using multiple windows or you can just use the GUI tool that ships as a part of Jini. In this book, you'll use the GUI tool, but if you prefer the command line you can see the commands that result from pressing the start buttons on the tool and enter those by hand. The reason you may not want to use the command−line method is that you are constantly specifying the additions to the CLASSPATH. It is tedious to repeatedly type in these long unenlightening strings, and it is easy to make a mistake. Instead, you will probably want to open up the GUI tool and locate the appropriate Chapter 20: Why Dream of Jini? 490 properties file. You will modify the settings so that the various services run on your machine for your configuration. You will then save these settings into a modified properties file and open it up each time to avoid having to remember your customized settings. You should be warned (again) that getting Jini up and running is the most frustrating part of working with Jini. The situation has greatly improved since the early days. If you continue to have problems, check the installation docs to see if anything has changed since the 1.2 beta release. Make sure you have a network connection and that you have configured it as described in the following section. Yell loudly. Check out the Jini resources section for links to helpful hints. Many of them include troubleshooting techniques. Start up the GUI launcher To start up the GUI launcher, type in the following code, after making adjustments to the various paths: java −cp files/jini1_2/lib/jini−ext.jar;files/jini1_2/lib/ jini−examples.jar com.sun.jini.example.launcher.StartService Here you are, of course, running the StartService application and adding both the jar file that contains it and a jar file with other Jini utilities to the CLASSPATH. You will be running this launcher enough that you should save this command into a bat file or a shell script that you can easily run. The GUI launcher application starts up, and the window in Figure 20−1 appears. Figure 20−1: The Jini StartService launcher The cool thing about this application is that it is flexible enough that you can use it to start up any Java application. The template that you see in Figure 20−1 enables you to add the command−line parameters you need to pass in. Click the Run tab, and you will see a start button and a stop button for the application you just added. You can use them to run any of your own Java applications. In this chapter, you'll just use StartService to launch your Jini−related applications. Load the configuration file by selecting File → Open Property File, and then navigate to the example\launcher subdirectory in your Jini 1.2 distribution. There you'll see two property files, one for Windows and one for UNIX. Choose the one that is appropriate for your needs. Mac OS X users should choose UNIX. You should see many tabs added to your StartService launcher. Click the Run tab, and you should see something like what is shown in Figure 20−2. Chapter 20: Why Dream of Jini? 491 Figure 20−2: Applications you can run from the launcher In the following sections, you will customize the default settings and then save your new settings to your own properties file that you can use the next time you start up the launcher. Startup rmid You may remember from your experience with RMI that working with the RMI activation daemon introduced some complexity. In Jini this complexity is, for the most part, hidden from you. You start up rmid and a Jini lookup service (in our case Reggie). Usually, this is where the difficulties come in starting up Jini. After you start up Reggie, you may get one or more errors or exceptions until you get your configuration right. To configure rmid, use the default settings shown in Figure 20−3. Figure 20−3: The rmid settings Go ahead and return to the Run tab and click Start RMID. The console window should display the following: the command line is: rmid –J−Dsun.rmi.activation.execPolicy=none You could also have started rmid by typing that command yourself. The GUI tool is just a convenience to keep you from having to do that. As discussed in Chapter 15, you will want to change the security policy once you are ready to deploy your application. For general security improvements to the Jini architecture, you should watch for news of the Davis release at http://www.jini.org/. Chapter 20: Why Dream of Jini? 492 If you have to cycle rmid (in other words, shut it down and restart it), you should discard the log file before starting it up again. In other words, use the stop button labeled "Stop RMID" or the command rmid –stop to kill rmid. Then delete the log file generated by rmid. Then use the Start RMID button on the GUI launcher to start rmid again. If you start up rmid and get a screen filled with problems, look for the log file and delete it. Start up a Web server Really there is no reason why the Web server has to be started up next. You could have started it before rmid or after Reggie. The instructions are given in this order to match the order of the buttons on your GUI tool. In the course of this chapter, you will start up several Web servers. You will need to serve up files from the CalculatorService and CalculatorClient directories. For now you are setting up a Web server to serve up the jar files in the \lib subdirectory of the jini1_2 distribution. The \lib subdirectory includes, among others, the reggie.jar file. The port is set to 8081, and the Web server itself is in the tools.jar file in the lib directory. Your Web server configurations should look like what you see in Figure 20−4. Figure 20−4: The Web server configuration Start up your Web server from the Run tab. Here's the resulting command: java –jar C:\files\jini1_2\lib\tools.jar –port 8081 –dir C:\files\jini1_2\ lib –verbose You will use other ports for the Web servers being used for CalculatorService and CalculatorClient in our example application. As long as it's unused, it doesn't much matter which port you choose. You will need to make sure your other Jini applications know about and use whichever port you choose. The default is now 8081. In earlier Jini days, the default was 8080, and so some people change to that. In Chapters 3 and 4, however, you would have used 8080 to run Tomcat. If you are running Tomcat and Jini, then you need to make sure you are not using the same port for each. The long and the short of it is that it doesn't matter which port you choose, and so for this example we will stay with the default of 8081 in the default properties files shipped in the Jini distribution. Start up Reggie As I mentioned earlier, you'll find most of your initial problems in getting a Jini service up and running in this step. You should check the resources for troubleshooting, but the basic setup is this. Make sure you are connected to a network and that the RMI activation daemon is running. If you have tried to start up reggie before, make sure you have deleted the log that was created. If you are on a UNIX system, you will have to create the directory into which reggie will write its log. For example, if your log is to be written into the file Chapter 20: Why Dream of Jini? 493 /Users/yourName/files/reggie_log then reggie_log should not exist but the directory /Users/yourName/files must exist. You will need to specify where reggie.jar is. If you have expanded the jini1_2 somewhere other than in the default location, you will need to make the usual adjustments. You will also need to specify the codebase, as you did with RMI. As with RMI, you shouldn't use localhost because that means different machines to different users. You would be indicating localhost because the code is on your machine. Then a client from another machine contacts you and asks where the files are that it needs to download. It is told localhost. The client says, "Oh, I know where localhost is. It's on my machine." You want to use the URL for the machine running reggie. In this case, we are connected to a router, and the machine's address is 192.168.1.101. You will also need to specify the port. All that matters here is that the port matches the setting you chose for the Web server. The Web server will be used to access reggie, so these values must match. As before, you need to specify a policy file. (You will most likely want a more restrictive policy file than the policy.all that you're using in this example when it's time to deploy your application.) You can choose to keep the log file wherever you'd like. You'll be saving this property file so you'll be storing whatever settings you now enter. If reggie doesn't start up correctly and you want to cycle reggie without cycling rmid, you can just input another value for the log directory as a temporary measure. Figure 20−5 shows the reggie settings. Figure 20−5: The reggie settings Hold your breath and start up reggie using the start button in the Run tab. If all goes well, reggie should start pretty quietly. You'll have to wait a little while for things to settle down to see if it really started up correctly. You can wait 30 seconds or to see if any error messages appear. You usually find out in less than a minute. Now it's time to see what you've done. Start up a Lookup Browser You now have a running Jini service. It's hard to tell. There's no visual evidence that anything is happening. The Lookup Browser will find lookup services and enable you to find information about the various services that their providers have made available. In your first application, you'll write a fairly ordinary service, and later on you'll provide information so that clients can locate the services they want. The settings for the Lookup Browser are similar to the ones for reggie. You will again need to specify a security policy and codebase as well as the location of the jar file containing the Browser class file and the full name of the class being run. Make the adjustments to the values shown in Figure 20−6 to fit the location of the Jini distribution and your IP address and port number. Chapter 20: Why Dream of Jini? 494 Figure 20−6: The Lookup Browser settings After a few seconds, the Lookup Browser appears. It should find your running reggie service, and you should see the screen shown in Figure 20−7. Figure 20−7: The Lookup Browser Select the only host being displayed and you can find out more information about the reggie services by using the checkboxes for the items in the other menus. You'll see more on this later in this chapter, but have fun poking around for now. At this point, if you have another machine on the same network, go ahead and follow the steps for starting up rmid, a Web server, reggie, and a Lookup Browser. You should see each machine discover and register with the other. This is automatic discovery, and joining is just part of the magic of Jini. While you're at it, kill off reggie and the Web server in one of the machines. After a while the other machine realizes that the reggie service on the remote machine is no longer there. You will again see only a single host listed. Again, magic. Leasing means that you won't continue to believe you have access to resources that are no longer there. You'll learn more about these features as you move through the examples in this chapter. Save your properties file OK, this probably doesn't deserve a separate heading, but nothing is more frustrating than finally getting Jini working and quitting the tool, only to have to configure it again later. Before you quit, choose File → Save As and save your property file under some useful name, such as customJini.properties. For convenience, place the file in the directory that is first opened when the JFileChooser appears. That way you can quickly load your config files without searching around. A Simple Proxy Jini Calculator Service You'll modify the non−distributed calculator example to run as a Jini service. Imagine that an adding service could just make itself available, and you could use it whenever you needed to add two numbers together. Perhaps this example seems trivial, but you can imagine a spell−checking service, a printing service, or a Chapter 20: Why Dream of Jini? 495 service for ordering dinner. For simplicity, begin by creating a subdirectory called ProxyCalculator in both the CalculatorClient and the CalculatorService directories. In this version of the example, you will begin by modifying the Calculator interface. The classes that perform the actual addition and subtraction will be sent from the server to the lookup service as proxies. When clients request a calculator service from the lookup service, they will receive either proxy if one is available. What really changes in this version of the example is the delivery mechanism for the service and the request mechanism for the client. Those details are presented in this section. Remember that you can run this application with the CalculatorClient directory on one machine, the CalculatorService on another, and the actual lookup service on a third. For the purpose of this example, I will assume that you are running on a single machine with the directories set up as specified . Inside of the ProxyCalculator subdirectory of CalculatorService, you will create the Calculator interface as well as the AdderProxy, SubtractorProxy, AddingService, and SubtractingService classes described in the following sections. The ProxyCalculator subdirectory of CalculatorClient will contain the same Calculator interface as is found in CalculatorService. It will also contain the CalculatorClient class described in the following section. The Calculator interface As in all Java programming, the interface is like a contract between two classes. One class wants to use another class that, to it, looks like a calculator. Another class promises to behave like a calculator when it implements the Calculator interface. This means that the client class knows what messages it is allowed to send to the service that implements the interface, and the implementing class knows how it is expected to respond. You can see that both the client side and the service side must know what the interface is, so the following Calculator interface must be in both the CalculatorClient and the CalculatorService directories. package ProxyCalculator; import java.rmi.Remote; import java.rmi.RemoteException; public interface Calculator extends Remote{ public String getOperationName() throws RemoteException; public int getValueOfResult(int firstOperand, int secondOperand) throws RemoteException; } The chief additions here are that Calculator now extends java.rmi.Remote and that each of the two methods now throws a java.rmi.RemoteException. It is important to know when you could be making a remote method call and to be able to handle the problems that could arise. The proxies for the adding and subtracting services In the original application, the Adder and Subtractor classes performed the actual calculation. As you convert them to Jini services, you will need to divide up the responsibilities between the piece that actually travels to the client machine and the piece that remains on your server. Later in the chapter you'll create a thin client that calls back to the server for all the results. For now, the calculating abilities will be contained in the proxy objects, and the server will contain the logic for delivering the service. Inside the directory CalculatorService you will create the two files AdderProxy.java and SubtractorProxy.java. Because the AdderProxy will be delivered over the wire, it needs to be serializable. Other than that very few changes to Adder are necessary. Because the proxy does not need to communicate Chapter 20: Why Dream of Jini? 496 with the service to return results to the client, the proxy does not need to accomplish anything extra. Here's the code: package ProxyCalculator; import java.io.Serializable; public class AdderProxy implements Calculator, Serializable { public AdderProxy(){} public String getOperationName(){ return "sum"; } public int getValueOfResult(int firstOperand, int secondOperand){ return firstOperand + secondOperand; } } Similarly, Subtractor needs to be changed to the following: package ProxyCalculator; import java.io.Serializable; public class SubtractorProxy implements Calculator, Serializable{ public SubtractorProxy(){} public String getOperationName(){ return "difference"; } public int getValueOfResult(int firstOperand, int secondOperand){ return firstOperand − secondOperand; } } Create the services Once you have separated out the actual functionality that you are presenting to the client, you can take a clear look at the delivery mechanism. In this first example, you will use a very simple model. You will set up a security manager as follows: private void setUpSecurityManager(){ if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } } When you run the application, you will pass in a security policy as a command−line argument. If, however, a user forgets to do this, your application will create a java.rmi.RMISecurityManager for him or her. The next step is to set up the net.jini.lookup.JoinManager, as follows: private void setUpJoinManager(){ try{ JoinManager joinManager = Chapter 20: Why Dream of Jini? 497 new JoinManager(new AdderProxy(), null, (ServiceIDListener)null, null, null); } catch (IOException e) {} } Two signatures are possible for the JoinManager constructor. In the one you've used, the first parameter is a handle to the proxy service. In other words, an instance of AdderProxy will be communicating back to this instance of AddingService, so when setting up the JoinManager for AddingService you have to tie it to the object that is referring back to AddingService. The other parameters have been set to null and will be explained in later examples as you add their functionality. It may look odd to see a null cast to the type ServiceIDListener. This is because the signatures of the two constructors differ only in their type. You use the constructor that takes a ServiceIDListener if you are registering your service for the first time and haven't yet been assigned a ServiceID. Each service should have a unique ServiceID so that if you register your service with more than one lookup service, a client can tell that the two or more apparently different services it is finding are really the same. The first time you register a service you can find out the ServiceID it's been assigned and then subsequently use this ServiceID by using the other constructor for JoinManager when registering with other lookup services. In this chapter, you won't actually be coding in this storage of the ServiceID. Here's the entire code for AddingService: package ProxyCalculator; import net.jini.core.lookup.ServiceItem; import java.io.IOException; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; import net.jini.lookup.JoinManager; import net.jini.lookup.ServiceIDListener; public class AddingService { public AddingService() throws IOException { setUpSecurityManager(); setUpJoinManager(); } private void setUpSecurityManager(){ if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } } private void setUpJoinManager(){ try{ JoinManager joinManager = new JoinManager(new AdderProxy(), null, (ServiceIDListener)null, null, null); } catch (IOException e) {} } public static void main(String args[]) { try { new AddingService(); Thread.sleep(5000); } catch (IOException e) { e.printStackTrace(); Chapter 20: Why Dream of Jini? 498 [...]... classes You should see the services shown in Figure 20 −9 Figure 20 −9: Viewing your services in the lookup browser Start up the SubtractingService as follows: java –classpath C:\files\jini1 _2\ lib\jini− core.jar;C:\files\jini1 _2\ lib\jini−ext.jar;.; −DJava.security.policy=C:\files\jini1 _2\ policy\policy.all –Djava.rmi.server.codebase=http://1 92. 1 68. 1.101 :80 85/ ProxyCalculator/SubtractingService Almost magically,... command to run the AddingService leaving a space between the codebase and the classname: java –classpath C:\files\jini1 _2\ lib\jini− 503 Chapter 20 : Why Dream of Jini? core.jar;C:\files\jini1 _2\ lib\jini−ext.jar;.; −Djava.security.policy=C:\files\jini1 _2\ policy\policy.all –Djava.rmi.server.codebase=http://1 92. 1 68. 1.101 :80 85/ ProxyCalculator/AddingService Take a look at your Lookup browser You should see that... with the following command: java org.apache.axis.utils.tcpmon This brings up the TCPMonitor GUI, as shown in Figure 21 −1 Figure 21 −1: The TCPMonitor 522 Chapter 21 : Implementing Web Services You want to intercept calls between your client and your server Pick a port to listen on — port 80 88, for example The target host name in this case is localhost, and the target port is 80 80 because that's the host... command window and navigate to the CalculatorClient directory Enter the following command to run the client: java –classpath C:\files\jini1 _2\ lib\jini− core.jar;C:\files\jini1 _2\ lib\jini−ext.jar;.; −DJava.security.policy=C:\files\jini1 _2\ policy\policy.all –Djava.rmi.server.codebase=http://1 92. 1 68. 1.101 :80 86/ ProxyCalculator/CalculatorClient There will be a pause, and you will see one of the following two... Calculator .java and CalculatorClient .java at the same time: javac –classpath C:\files\jini1 _2\ lib\jini− core.jar;C:\files\jini1 _2\ lib\jini−ext.jar ProxyCalculator/* .java You should know a couple of things about this command First, if you have not added a pointer to in your CLASSPATH settings you may have to change the preceding command to the following: javac –classpath C:\files\jini1 _2\ lib\jini−... settings You can't use port 80 81 because that port is already being used by the running Web server In this chapter you'll use port 80 85, unless you have already assigned it for another purpose Whichever port you choose, make sure you remember it, because you will need it in the next step Configure the Web server as shown in Figure 20 8, and then start it from the Run tab Figure 20 8: Web−server settings... You'll have to go back and change HelloClient .java so that the target is port 80 88; otherwise you won't be able to view the conversation between HelloClient and HelloService You need only to change endpoint to this: String endpoint = "http://localhost :80 88/ axis/HelloService.jws"; Now recompile and rerun HelloClient with the command−line argument Sam, as follows: java LocalGreeting/HelloClient Sam The TCPMonitor... way you set up the CalculatorService Web server Use the Jini GUI tool to launch the Web server This time use port 80 86 and set up the codebase to point at C:\J2EEBible\CalculatorClient Your configuration should look like the one shown in Figure 20 −10 504 Chapter 20 : Why Dream of Jini? Figure 20 −10: Configuring the CalculatorClient Web server Now start the Web server from the Run tab Run the client The... xsi:type="xsd:string">Sam You'll see the following code as the response in the TCPMonitor: HTTP/1.1 20 0 OK Content−Type: text/xml; charset=utf 8 Content−Length: 444 Date: Tue, 02 Oct 20 01 18: 16: 58 GMT 524 ... in the files directory, then your command is as follows: javac –classpath /files/jini1 _2/ lib/jini− core.jar:/files/jini1 _2/ lib/jini−ext.jar:.: ProxyCalculator/* .java Navigate to the CalculatorService directory and compile all the source files inside the ProxyCalculator directory with the same command 5 02 Chapter 20 : Why Dream of Jini? Run the distributed application This process consists of several . client: java –classpath C:filesjini1 _2 libjini− core.jar;C:filesjini1 _2 libjini−ext.jar;.; −DJava.security.policy=C:filesjini1 _2 policypolicy.all –Djava.rmi.server.codebase=http://1 92. 1 68. 1.101 :80 86/. C:filesjini1 _2 libjini− core.jar;C:filesjini1 _2 libjini−ext.jar;.; −DJava.security.policy=C:filesjini1 _2 policypolicy.all –Djava.rmi.server.codebase=http://1 92. 1 68. 1.101 :80 85/ ProxyCalculator/SubtractingService Almost. port 80 86 and set up the codebase to point at C:J2EEBibleCalculatorClient. Your configuration should look like the one shown in Figure 20 −10. Chapter 20 : Why Dream of Jini? 504 Figure 20 −10: