Building Production Code


The previous two samples demonstrated how, in both .NET and Java, you can create a server component that can be called by the other platform by using the .NET Remoting protocol to communicate. In each of the samples, the server side had to listen for incoming requests in a second command-prompt window.

Although this procedure is adequate for showing the samples in action, it doesn't lend itself toward a production-worthy solution. For example, in a production system, you don't want to have to ensure that all servers sharing these components are logged in and running this pseudo “server application from a command prompt. What happens if a user logs off the machine? What if a reboot happens? How do you scale this solution to offer the component to potentially hundreds of calling clients , supporting life cycle, security, and transactions?

The remainder of this chapter covers three additional samples and shows how to host these types of server components by using more production-worthy techniques in conjunction with the .NET Remoting protocol. First, we'll look at hosting the .NET server component within Microsoft Internet Information Server (IIS). IIS provides a proven, HTTP-based framework that can be leveraged to host such components to the respective Java client. Second, we'll reverse the situation, hosting the Java server component code within two EJBs ”one Session-based and one Entity-based. You'll see how to use the Janetor tool to create an abstracted Web-based layer to allow these EJBs to be called from your .NET client.

Finally, we'll conclude by examining a late-breaking sample of a .NET component hosted through Component Services (using Microsoft Windows Server 2003) and called by a Java client. A new release of Component Services in Windows Server 2003 provides additional functionality for creating enterprise components and automatically generating a SOAP virtual root that can be consumed by the Ja.NET proxies.

Java Client to .NET Remoted Object, Hosted by IIS

Before we look at this particular sample, let's discuss some advantages of hosting the server component in IIS over using a sample standalone application. Figure 4.17 shows a server component hosted by IIS.

click to expand
Figure 4.17: Java client calling a .NET server component, hosted by IIS.

With a little work, we could have used the examples in the previous section to move the .NET Remoting server component into a Windows service, which could be a viable option to hosting the server component in IIS. Although this would increase the stability of the component, it wouldn't automatically provide for the following:

  • Security By hosting the server component within IIS, we can use the authentication mechanisms that are provided as part of the Web server. The process of locking down the server component with a username and password is the same as that of locking down an HTML page.

  • Isolation IIS provides a number of pooling options that allow pages (and this component) to be pooled based on load and priority. Objects that run can be either executed as part of the IIS process or isolated within a separate process, thus protecting the Web server in case of a fault with the component.

  • Logging Any logging mechanism (to a file or database) that's currently configured within IIS can now be applied to calls to the hosted server component.

The .NET Server Sample Code

The sample that demonstrates hosting the IIS server component is located in the C:\Interoperability\Samples\Point\Remoting\JavaToIIS directory. As with the Java-to-.NET example in the previous section, the Server subdirectory contains the classes for the server component. However, to host this component using IIS instead of the default .NET Remoting server method, you need to make a few changes. As the sample is also using IIS, you should ensure that you have followed the "Installing ASP.NET on Windows Server 2003" or "Installing ASP.NET on Windows XP Professional" and "Configuring ASP.NET Security" sections in Chapter 1.

First, there is no remoting.config file, and instead the settings are now present in web.config, which is the default configuration file for ASP.NET applications. In the web.config file, the reference to the port and channel have been removed. This is because HTTP is the only channel that IIS can host, and the port will be derived from the IIS settings.

 <configuration>     <system.runtime.remoting>         <application>             <service>                 <activated type="SimpleRemoting.SampleData,Server"/>                 <activated type="SimpleRemoting.StockServer,Server"/>             </service>         </application>     </system.runtime.remoting> </configuration> 

In addition, the sample now has a bin directory. This directory is used to store the .NET assembly for the IIS virtual directory.

This sample also makes a couple of changes in the RemotingServer.cs class file. A Main method no longer exists. This is because the assembly generated is a DLL, not an executable. Recall that the Main method was used only to set up the .NET Remoting server configuration in the previous Java-to-.NET example. This is no longer required.

In addition, the previous example wrote the incoming purchases and sales by calling the Console.WriteLine method. When the component is hosted via IIS, however, we no longer have access to the Console object. To record the purchase, the component now writes to the Windows Event Log by using the following code:

 EventLog ev = new EventLog("application",".",     "Ja.NET Interoperability Sample"); ev.WriteEntry("Incoming request to purchase "+quantity+     " common shares of "+stockToBuy.Name+" ("     +stockToBuy.Ticker+")"); 

Compile the server code within this directory using NAnt. This will generate the required DLL in the bin directory for IIS. Once this has completed, you need to set up the IIS Virtual Directory. To do so, launch IIS by selecting the Start/Programs/Administrative Tools/Internet Information Services (IIS) Manager program menu item.

Tip

You can also run IIS by going to the Start menu, selecting Run, and typing INETMGR .

Within the Internet Information Services (IIS) Manager tool, navigate to and right-click the Default Web Site entry. From the drop-down menu, select New and then select Virtual Directory. The Virtual Directory Creation wizard will be opened, as shown in Figure 4.18.

click to expand
Figure 4.18: Creating an IIS Virtual Directory.

The alias for this sample's virtual directory will be JavaToIIS . (Note that virtual directories in IIS are case sensitive.) For the directory containing the content, point to our sample Server directory, C:\Interoperability\Samples\Point\Remoting\JavaToIIS\Server , as shown in Figure 4.19.

click to expand
Figure 4.19: Setting the directory location for the virtual directory.

Complete the wizard by selecting the defaults for the remainder of the options. The .NET server component in IIS is now configured and ready to be called.

The Java Client Sample Code

With the server component now hosted through IIS, the configuration of the Java calling client is relatively straightforward. In the Client directory, run the GenJava tool. For the URI, enter tcp://localhost:8001/GenService . For the .NET Assembly, enter C:\Interoperability\Samples\Point\Remoting\JavaToIIS\Server\bin\server.dll , and for the Output Directory, enter C:\Interoperability\Samples\Point\Remoting\JavaToIIS\Client . (We've actually hardly changed the assembly, but we still need to generate the proxy files for the Java client.)

Navigate to the C:\Interoperability\Samples\Point\Remoting\JavaToIIS\Client directory. The client code for Client.java is the same as the code for the previous Java client connecting to a .NET server example.

In the client directory, run the Janetor tool, but this time, select the default option under the Remote Objects node in the tree, as shown in Figure 4.20.

click to expand
Figure 4.20: Setting the activation mode, URI, and channel format for the client.

With the activation mode set to Client, set the URI to the root of the IIS virtual directory. (In this sample, this is http://localhost/JavaToIIS .) Also, select either SOAP or Binary for the channel format ”both work with IIS.

Notice the Authentication tab on the remote object activation panel, shown in Figure 4.21. This is a useful option because it allows you to configure authentication on the IIS Web server if required. (For example, these authentication credentials could come from an Active Directory directory service store.) The Authentication tab then lets you apply this authentication to the component that you remotely host.

click to expand
Figure 4.21: Using the Authentication tab to set credentials for the exposed component.

The Authentication tab supports Basic and Digest authentication, which both can be selected in IIS. In addition, this authentication information can be set programmatically.

Save the configuration, compile the sample, and run the client side of the code. After the call is made, the client object will call the remote server object as in the previous sample and will display the results and confirmation of the purchase to the console.

To validate this sample, go to the Event Viewer. (If you're running this demo across multiple machines, use the Event Viewer on the machine that the IIS Server is running on.) You can run the Event Viewer by selecting either Start/Programs/Administrative Tools/Event Viewer or Start/Run and entering EVENTVWR at the command prompt.

Within the Event Viewer, navigate to the Application Log File. If the sample code ran successfully, the remote server component should have written an entry into the Event Log to confirm the purchase, as shown in Figure 4.22.

click to expand
Figure 4.22: An event written to the Windows Event Log.

If you open and look at this event, you'll see a similar message to the one that was written to the console in previous examples.

Analyzing the Samples with the SOAP Trace Utility

The skeptic in me always likes to validate the data sent for each of these samples, especially when running the demos on the same machine. When running the demos on the same machine, it's easy to lose your appreciation for the type of data that's sent between processes.

One way of analyzing this communication is with the SOAP Trace Utility that's packaged as part of the Microsoft SOAP Toolkit version 3.0. The toolkit, which is designed to support SOAP for existing Microsoft Windows DNA architectures, can be downloaded from http://msdn.microsoft.com . The easiest method to find the SOAP toolkit is to search the MSDN Web site for "SOAP Toolkit".

The SOAP Trace Utility works by listening on one designated IP port and forwarding the data to another. As this tool intercepts and forwards the requests and responses, it logs the output of the message headers, body, and content. This is a great way to see both the size and type of data as they are transmitted along the wire.

Rerunning the current IIS sample, you can use the SOAP Trace Utility to view the data that's being passed. Once installed, the Trace Utility is available from the Start/Programs/Microsoft SOAP Toolkit Version 3 Program menu. To try this, configure the SOAP Trace Utility to create a new formatted trace, by selecting New/Formatted Trace from the File menu and setting the Local port to 8080 , the Destination host to localhost , and the Destination port to 80 , as shown in Figure 4.23.


Figure 4.23: Setting the ports in the SOAP Trace Utility.

Now, return to the C:\Interoperability\Samples\Point\Remoting\JavaToIIS\Client directory and rerun the Janetor tool. In the default node of Remote Objects, set the port so that the URL is http://localhost:8080/JavaToIIS , as shown in Figure 4.24. This will configure the Java client to communicate with the server component on port 8080, sending the request through the SOAP Trace Utility.

Save the configuration, and rerun the sample. You don't need to regenerate the proxies or recompile the code because the Janet.xml file is read dynamically by the Ja.NET libraries.

Once the demo has run, switch back to the active SOAP Trace Utility. An entry for the previous message, shown in Figure 4.25, will have been recorded. Expand the entry to inspect the contents of the message.

click to expand
Figure 4.24: Setting the activation mode, URI, and channel format.
click to expand
Figure 4.25: Examining the output from the SOAP Trace Utility.

You should see two messages displayed in the utility: the call to the SampleData and the call to the StockServer (which calls the purchaseStock method). Click the first message to display the SOAP envelope, header, and body for the message. The top window shows the request from the client, and the bottom window displays the response from the server. From here, you can interrogate the types and content that make up the two messages. You can view the content of the SOAP message by clicking on the Binary node. By clicking the HTTPHeaders node in the tree, you can see that the size of the message (its content length) is 2553 bytes for the client request and 3038 bytes for the reply. These values might differ slightly based on your environment.

Now, clear the window in the SOAP Trace Utility and return to the client code (without closing the SOAP Trace Utility). Rerun the Janetor tool. This time, in the Remote Object defaults, select Binary for the channel format. Run the Client again, and return to the SOAP Trace Utility to view the generated output, as shown in Figure 4.26.

click to expand
Figure 4.26: Examining the output from the SOAP Trace Utility.

Using binary format changes the output in a number of ways. First, when you click the Message node, you can't see any output. The only way to view the binary output is to click the Binary node. Second, the content length for the two calls is significantly smaller than the SOAP output. The content length is 1395 bytes for the first request and 1298 bytes for the reply. Although this is only a simple example based on the sample code, using the SOAP Trace Utility in conjunction with the Janetor tool options illustrates how you can obtain valuable insight into the data passed with calls using .NET Remoting.

.NET Client to EJB, Hosted by J2EE Application Server

Now that we've spent some time looking at a Java client calling a .NET component hosted in IIS, let's look at a scenario in which the server component is hosted on the J2EE platform, using both Session and Entity EJBs. Figure 4.27 depicts such a scenario.

click to expand
Figure 4.27: .NET client to EJB, hosted by J2EE application server ” with simulated database access.

To show this example, we'll use the Stock object from earlier samples in this chapter to create a Stock Entity Bean. The bean, which uses Bean Managed Persistence (BMP), contains the same fields as the original Stock object and simulates calls to the database within the ejbLoad and ejbFindByPrimaryKey methods . You can easily extend this example to make the appropriate database calls if you want.

The StockServer code is now running in the context of a Session Bean. This bean exposes a method to accept only the ticker symbol for a particular stock and then does an internal Java Naming and Directory Interface (JNDI) lookup for the Stock Entity Bean. As with many J2EE architectures and best practices, the Entity Bean is never passed back to the calling application. (I share the view that Entity Bean data should always be hidden behind a Session Bean interface for both security and maintainability reasons.)

The Java EJB Sample Code

The EJB sample code for this example can be found in the C:\Interoperability\Samples\Point\Remoting\dotNETToEJB\Server directory. The package name for the samples is com.microsoft.samples.ejb . The SessionBean.java class contains the main methods for the Session Bean exposing the sellStocks method. This method is invoked by passing a ticker (of type java.lang.String , which is set to be the primary key type for the Stock Bean) and a quantity for the number of shares to sell.

The Session Bean first tries to get the home interface for the Stock Bean with a simple context lookup:

 StockHome newStockHome;      try {     InitialContext newContext = new InitialContext();     Object ref = newContext.lookup("StockBean");     newStockHome = (StockHome)PortableRemoteObject.narrow(ref,         StockHome.class); } catch (Exception e) {     throw new EJBException(e); } 

After this lookup is performed, the Stock object is created, and a findByPrimaryKey method is called to pass in the value of the ticker. If you look in the StockBean.java class, you'll see a simple if then statement used to return the values that simulate a lookup in the database. When the Stock Bean is returned, you write the sell stock request to STDOUT , which on most J2EE application servers gets translated to the EJB console window.

 Stock newStock; try {     newStock = newStockHome.findByPrimaryKey(ticker); } catch (Exception e2) {     throw new StockNotFoundException(); }      System.out.println("Incoming request to sell "+quantity     +" common shares of "+newStock.getName()+" ("     +newStock.getTicker()+")"); // do the real work here! // Assume that the trade was committed return true; 

Before building the EJB package, it is important to ensure that the relevant J2EE libraries are available to the GenNet tool, by being in the CLASSPATH . This varies from application server to application server. For using the sample code with JBoss, the jboss-j2ee.jar (found in the jboss\server\default\lib directory) should be used.

Once this is set, use the supplied Ant build script to compile the EJB package. Upon a successful compilation, a SampleEJB.jar file will be created in the Deploy subdirectory in C:\Interoperability\Samples\Point\Remoting\dotNETToEJB\Server.

You now have a JAR file that can be deployed to the application server. Before we actually deploy the server component, let's create the required proxy for the .NET client. To create the proxy from the classes for the EJB, navigate to the Classes directory, C:\Interoperability\Samples\Point\Remoting\dotNETToEJB\Server\Classes. This directory contains the compiled classes from the Session Bean and the Entity Bean and will be used to generate the proxy. Run the GenNet tool from within this directory.

Again, enter the URI for the GenService tool ( tcp://localhost:8001/GenService ), and enter the following two required classes, which the code will generate:

com.microsoft.samples.ejb.StockSessionBean

com.microsoft.samples.ejb.StockSessionHome

The GenNet wizard should show these classes, as Figure 4.28 depicts.

click to expand
Figure 4.28: Setting the Java classes for the exposed EJB.

Once you've completed this step, click Next to proceed. To generate the .NET proxy, name the assembly SampleEJB.dll , and this time, save all the classes into a References subdirectory for the client. Set the output directory to C:\Interoperability\Samples\Point\Remoting\dotNETToEJB\Client\References , as shown in Figure 4.29.

click to expand
Figure 4.29: Setting the assembly and output directory for the .NET client proxies.

You need to use a second subdirectory because generating the .NET proxy can require a lot of classes. Generating this proxy in a subdirectory allows for a cleaner client solution. A neat way of cleaning up this generation is to use the Filter button in the previous wizard step. (Use the Back button to see this.) From there, you can filter out classes that aren't required for the .NET assembly, such as the java.io classes the tool detects.

To complete the generation of the .NET proxy, click the Next button and then click the Finish button once all the required proxy classes have been generated.

The final step you'll perform with the Java server code is to run the Janetor tool again to configure the settings. This time, part of the configuration involves creating a WAR file that can be used to expose the EJBs to the .NET Remoting client.

To perform this step, run janetor from the C:\Interoperability\Samples\Point\Remoting\dotNETToEJB\Server directory. Click the default node in the Local Objects tree, as shown in Figure 4.30.

click to expand
Figure 4.30: Setting the activation mode, URI, and assembly name for the client.

Now set the activation mode to Client , the URI to http://localhost:8080/SampleEJB , and the assembly name to SampleEJB . This configures the endpoint for the server component. Now click the EJB Context tab in the wizard, shown in Figure 4.31.

click to expand
Figure 4.31: Setting the EJB context to expose the EJBs via a Ja.NET WAR file.

Now you need to enter the Initial Context Factory and Provider URL to enable EJB lookups in the server. This class and URL will be specific to the J2EE application vendor you choose, so you should check with the documentation that accompanies your server to see which class and URL to use.

For the sake of this example, you can use Table 4.1 as a guide to the defaults for a number of J2EE application servers. With the exception of JBoss 3.0.7, this information has not been tested with the sample code, and any settings in the documentation or notes that are supplied with your J2EE application server should always supersede this information.

Table 4.1: Context Factory Settings for J2EE Application Servers

J2EE Application Server

Initial Context Factory

Provider URL

JBoss 3.0.7

org.jnp.interfaces.NamingContextFactory

localhost:1099

BEA WebLogic

weblogic.jndi.WLInitialContextFactory

t3://localhost:7001

IBM WebSphere

Not required

Not required

Oracle 9i

Not required

Not required

Borland Enterprise Server

com.imprise.j2ee.jndi.CtxFactory

Not required

Once you've configured this information, save the configuration but do not close the Janetor wizard yet. Once the file is saved, select the Export Web Application Archive option from the File menu, shown in Figure 4.32.

click to expand
Figure 4.32: Configuring the Web application archive to be exported.

The Export Web Application Archive dialog box has a number of options that you need to configure. First, enter the location of the Ja.NET library. This is required for packaging in the WAR file that's created and is normally C:\Interoperability\Tools\Ja.NET\lib\janet.jar .

You then need to reference the user library, which is the JAR file that was created by the initial Ant build script (via C:\Interoperability\Samples\Point\Remoting\dotNETToEJB\Server\Deploy\SampleEJB.jar ) and then specify the output file, which is the name of the WAR file to be generated by the tool ( Deploy\SampleEJB.war ). After entering this information, click the OK button. A SampleEJB WAR file will now be created in the Deploy subdirectory. Close the Janetor wizard.

You've now completed all the steps required to share the EJBs with a .NET Remoting client. To complete the deployment, deploy the SampleEJB.jar file (in the Deploy directory), and deploy the SampleEJB.war file that was created by Janetor to the application server. The deploy target can be used with the provided Ant script to deploy both the JAR and WAR file to a JBoss J2EE server. As mentioned earlier, follow the deployment instructions that are specific to the J2EE application server that you're using. Once deployed, start the application server to allow the .NET sample client to call the exposed EJB component.

The .NET Client Sample Code

You configure the .NET client to call the deployed EJB in largely the same way as you did in the previous code. The remoting.config file (which can be found in the C:\Interoperability\Samples\Point\Remoting\dotNETToEJB\Client directory) references the URL, type, and assembly name configured in the previous steps:

 <client url="http://localhost:8080/SampleEJB">      <activated type=         "com.microsoft.samples.ejb.StockSessionBean, SampleEJB"/> </client> 

Build and run the client from this directory using NAnt. The .NET client will call the deployed Stock Session EJB via the Ja.NET Servlet that's been deployed to the application server as part of the WAR file that was generated. This Session Bean in turn calls the Stock Entity Bean to perform the simulated stock sale. With luck, the following message will be displayed in the console window of the J2EE application server:

 Incoming request to sell 200 common shares of Woodgrove Bank(WOOD) 

Notice also how in the J2EE application server console the EJB methods (for example, ejbLoad and ejbStore ) are displayed, showing activation of the bean.

Java Client to .NET Object, Hosted by Component Services

The final example in this section ”which rounds out the chapter by showing the many permutations of using .NET Remoting for interoperability ”depicts a component hosted within Component Services running on either Microsoft Windows XP Professional SP1 or Microsoft Windows Server 2003. This example will use Windows Server 2003.

Component Services has evolved somewhat during the past few years and through the past few generations of Microsoft server products. It began life as Microsoft Transaction Services (MTS) in Microsoft Windows NT 4.0 and expanded into COM+ Services with Microsoft Windows 2000. Component Services is now a highly integrated part of Windows Server 2003.

As Chapter 1 discussed, today Component Services allows a .NET assembly to be deployed and configured in a way that supports integrated security, transactions, pooling, and activation. All this configuration can be performed through the Component Services user interface, which can be accessed from the Administrative Tools program menu, or programmatically by applying attributes to the .NET component source code.

In this example, we'll look at a feature of Component Services known as SOAP activation . SOAP activation enables the developer to deploy a component within Component Services (known as a Serviced Component ) and then automatically create a SOAP endpoint for consumption by a client using .NET Remoting. This example will demonstrate how to deploy a component, configure the SOAP activation, and consume that component from a Java client (with the proxies generated by the Ja.NET tool), as shown in Figure 4.33.

All the sample code for this example is located in the C:\Interoperability\Samples\Point\Remoting\JavaToComponentServices directory.

click to expand
Figure 4.33: Java client to .NET object, hosted by Component Services on Windows Server 2003.

The .NET Serviced Component Sample Code

Let's first look at the code that makes up the component we'll deploy. To do this, open the RemotingServer.cs class, which is located in the Server directory. First, you can see that the class imports the System.EnterpriseServices namespace. This namespace contains all the interfaces, classes, and attributes used to deploy a component within Component Services. Also, the beginning of the class contains some assembly attributes:

 [assembly: ApplicationName("StockServer")] [assembly: AssemblyKeyFile("StockServer.snk")] [assembly: ApplicationAccessControl(     Value=false,Authentication=AuthenticationOption.None)] [assembly: ApplicationActivation(     ActivationOption.Server, SoapVRoot="StockServer")] 

The first attribute specifies the name of the application that will be deployed within Component Services. The second attribute references a key file that will be used to create a strongly named assembly.

Note

What is a strongly named assembly? .NET assemblies must be deployed into the global assembly cache (GAC) so that they can be accessed by many processes (including system processes such as Component Services). The GAC is a machine-based store that's responsible for centralizing and sharing these version-specific assemblies. To be installed into the GAC, an assembly must be strongly named. To strongly name an assembly, the assembly must be signed with a key. This key either can be specific to the developer or auto- generated by the system. Once the assembly is signed by this key, the assembly will remain unique within the GAC regardless of other assemblies that might have the same name or that might expose the same methods.

The ApplicationAccessControl attribute turns the security authorization level off and sets the authentication option to None . This negates the requirement to install a certificate or set up a Secure Sockets Layer (SSL) context to call our component. (Of course, this default option is still available if you want to investigate it further.) The ApplicationActivation attribute automatically configures the component to run as a server component ”meaning that the component is allocated a dedicated server process for activation ”and defines a SOAP virtual root called StockServer.

Also, notice how each class inherits from ServicedComponent :

 public class SampleData : ServicedComponent { } 

This signifies to Component Services that the component will be exposed as a hosted component. This inheritance of ServicedComponent replaces the MarshalByRefObject used in the previous samples and will be detected by the Ja.NET tools when generating the required proxies.

Build the code in the C:\Interoperability\Samples\Point\Remoting\JavaTodotNETServer\Server directory, using NAnt. The build creates two things: a StockServer.dll file that can be hosted through Component Services and an Invoker.exe file that's used to deploy the component. The Invoker.exe file is created within the Invoker subdirectory.

After the build has completed, use the invoke target with the provided NAnt script to launch the invoker. If you plan to run the component on a second machine, you'll need to copy the contents of this directory to that machine and run it there. The invoker batch file that is called deploys the assembly to Component Services so that you can configure it via the administration interface.

The invoke script also automatically runs a utility named GACUTIL, which is used to place a copy of the StockServer.dll into the GAC. If installation into the GAC is successful, the invoke script should report this final message:

 Assembly successfully added to the cache 

If the GACUTIL does not work, check that the directory holding gacutil.exe is in the System Path.

Note

In certain rare cases, you might get a System.Runtime.InteropServices.COMException exception when you run the NAnt script with the invoke target, indicating that the server process must be run under a different identity. In this case, the StockServer component will be deployed, but it needs to be configured to be able to run properly. Open the Properties window for the StockServer component within Component Services (the steps necessary to do this are detailed below), and select the Identity Tab. Change the settings to make the StockServer component run using the Local Service account, and click OK. Now rerun the invoke batch file to complete the StockServer component installation.

To check that all this completed successfully, go to Start/Programs/Administrative Tools/Component Services on the machine that the component was deployed on. Drill down through the Component Services, Computers, My Computer, and COM+ Applications folders until you reach the StockServer application folder, as shown in Figure 4.34.

click to expand
Figure 4.34: Using the Component Services administration tool to examine the deployed component.

To view properties on the application, simply right-click the StockServer node and select Properties to display a properties window. The properties that are available allow the component to be configured for services that are supported under Component Services.

Because we're interested in activating the component via SOAP, click the Activation tab, as shown in Figure 4.35. As you can see, the attributes used on the class define that the component will run as a server application. Furthermore, SOAP activation is enabled using a SOAP VRoot of StockServer.


Figure 4.35: Using the Component Services administration tool to examine the deployed component.

Close this properties window. Before building the client, you can test the component by browsing to http://localhost/StockServer . (Replace localhost with the name of the machine on which you're running the component.) Figure 4.36 shows the Web page that should appear.

click to expand
Figure 4.36: Using Microsoft Internet Explorer to test the SOAP VRoot.

One new feature of Windows Server 2003 provides a Web interface for the components that are exposed. Viewing this Web page means that the components have been successfully deployed.

The SOAP root ”and location of the files ”for the StockServer component is by default set to C:\WINDOWS\System32\Com\SoapVRoots\StockServer on the machine on which the component is deployed. Before running the Java client, one remaining configuration item is to make a security change to allow the stock type to be passed by value. A restricted security setting in the .NET Framework 1.1 prevents these types from being passed automatically.

To make this change, edit the web.config file in the newly created SOAP root (C:\WINDOWS\System32\Com\SoapVRoots\StockServer). Within the channels section of the file, replace < channel ref="http server" / > with the following text:

 <channel ref="http server">     <serverProviders>          <formatter ref="binary" typeFilterLevel="Full"/>     </serverProviders> </channel> 

This will set the filter level for the binary formatter such that the stock data type can be serialized without raising a security exception. Additional information about the workings of this security model can be found by searching for "Automatic Deserialization in .NET Remoting" on http://msdn.microsoft.com .

The Java Client Sample Code

Now that you have the .NET server component completed, it's time to configure the Java client. To do so, navigate to the C:\Interoperability\Samples\Point\Remoting\JavaTodotNETServer\Client directory. From there, you need to run the GenJava utility to create the Java proxies for the component deployed in Component Services.

Run the GenJava tool, enter the URL for the GenService tool ( tcp://localhost:8001/GenService ), and point the .NET assembly to the location of the StockServer DLL that's created in the server directory ( C:\Interoperability\Samples\Point\Remoting\JavaToComponentServices\Server\StockServer.dll ). For the Output Directory, enter . (a period) for the current directory. Figure 4.37 shows the dialog box used to make these settings.

click to expand
Figure 4.37: Setting the .NET assembly and output directory for the Java proxies.

Click Next and then Finish to generate the required proxies. From the client directory, the final step is to configure the URL and ports.

Run the Janetor tool, and select the default node under the Remote Object tree, as shown in Figure 4.38.

click to expand
Figure 4.38: Setting the activation mode, URI, and channel format.

To access the component hosted in Component Services, you need to set the activation mode to Web Services, which allows the Ja.NET tool to derive the configuration from a SOAP endpoint rather than from a direct URL. In addition, you must set the URI as required ( http://localhost/StockServer ). As mentioned earlier, you might need to change the server name for this URI setting based on your environment. Also, set the channel format to binary for this example.

Save the configuration, and exit the janitor tool. Compile and run the client code using Ant with the run target. As in the earlier examples in the chapter, the list of recommendations and the confirmation of a purchase should be displayed. On the server running the component in Component Services, you can again check the Windows Event Log to ensure that the request to purchase stock was logged.

Interoperability Performance Tests

As in Chapter 3, a set of performance tests for this chapter has been included in the C:\Interoperability\Samples\Point\Remoting\PerformanceTest directory. The sample takes the previous .NET Remoting client and the Java server from the dotNETToJava example directory and runs the test a specified number of times, reporting back the average time taken in milliseconds . To build and run the tests, follow the same directions used in the ".NET Client to Java Object Hosted by Ja.NET TCP Server" section. (Note that you will need to modify the earlier gennet tool directions to use the proper PerformanceTest directory.)

As with the performance tests in Chapter 3, the intention of this chapter's tests isn't to report the results and compare platform performance, but instead to act as a guide for selecting the correct interoperability technology for your own environment. For example, you might want to connect the EJB server to test how well the .NET Remoting protocol compares with accessing an EJB via some of the other methods outlined in this book.

In executing this performance test, my development machine took an average of 4.6 milliseconds (ms) to download the five stock recommendations and an average of 8.1 ms to call and commit the sale command.

Type Mappings

As with the type mappings among .NET, XML, and Electric XML shown in Chapter 1 and Chapter 3, Table 4.2 shows how the types map between .NET and Java by using the Ja.NET toolset. This comparison is useful when developing your own applications because it helps to determine how types will be passed between each platform.

Table 4.2: Ja.NET Type Mappings Between .NET and Java

.NET Data Type

Java Data Type

bool

java.lang.Boolean

char

java.lang.Character

System.String

java.lang.String

System.Single

java.lang.Float

System.Double

java.lang.Double

System.Int8

java.lang.Byte

System.Int16

java.lang.Short

System.Int32

java.lang.Integer

System.Int64

java.lang.Long

System.Byte

java.lang.Byte

System.UInt16

java.lang.Short

System.UInt32

java.lang.Integer

System.UInt64

java.lang.Long

System.Object

java.lang.Object

The collection class types are handled as shown in Tables 4-3 and 4-4.

Table 4.3: Ja.NET Collection Mappings Between Java and .NET

.NET Collection Class

Java Collection Class

System.Collections.Ilist

java.util.ArrayList

System.Collections.Ilist

Java.util.LinkedList

System.Collections.Ilist

Java.util.Vector

Table 4.4: Ja.NET Collection Mappings Between .NET and Java

.NET Collection Class

Java Collection Class

System.Collections.ArrayList

java.util.List

Events and Exceptions

Before ending this chapter on using .NET Remoting to achieve interoperability between the .NET and Java platforms, let's examine two additional points that relate to the other examples in the book.

Events

.NET Remoting and the Ja.NET tool support the notion of events ”something that our samples did not show but that can be easily demonstrated. The Ja.NET tool has the ability to map events that extend java.util.EventListener to system events in .NET. One advantage of using the .NET Remoting protocol this way is that the server component has the ability to "call back" to the client using this event model. This can be especially useful in situations where asynchronous operations or long-running transactions are required.

Exception Handling

In a couple of samples in this chapter, an exception was thrown and reported back (hopefully, on purpose). Be aware that exceptions are handled using the Ja.NET tool but that specific exceptions do get mapped accordingly . The rules of exception handling are generally as follows :

  • Any exception that occurs in a Java server gets mapped to System.Runtime.Remoting.RemotingException in .NET.

  • Any exception that occurs in a .NET server gets mapped to com.intrinsyc.janet.RemoteException in Java.

In the majority of cases, the original exception message is embedded in the text produced from these exceptions. Therefore, when handling exceptions, you can trap this single exception and then search through the text of the inner exception if additional information is required.




Microsoft. NET and J2EE Interoperability Toolkit
Microsoft .NET and J2EE Interoperability Toolkit (Pro-Developer)
ISBN: 0735619220
EAN: 2147483647
Year: 2003
Pages: 132
Authors: Simon Guest

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net