Mobile 2 Java
Mobile 2 Java
Introduction
If the task at hand is to connect a Pocket PC running the .Net Compact Framework to a Java back-end, and if Web Services are ruled
out as an interoperability solution, there are not many viable options available. The one presented in this article may well be the only
one.
This solution requires Middsols MinCor.NET. The product is an object request broker for the Compact Framework written in C#. It
supports Windows Mobile, Windows XP Embedded and Windows CE .NET.
Requirements
A chat application is a good example for an interoperability scenario, because it does not require much business logic, while it still
allows for some interesting features at the communication level. In this example, an existing Java server implements and exposes a
basic chat service through RMI. A mobile client, to be written in .Net managed code, will consume the chat service. Chat subscribers
must specify a user id and their favorite hobby. With the Naming Services IP address, a subscriber can get a connection to the chat
host and send messages that all subscribers will see on their displays. The example will demonstrate how a .Net developer who is
unfamiliar with Java distributed object technology can
-
generate an IDL file from a JAR (Java Archive) file that describes the interfaces in platform-independent terms
generate .Net remote object stub code from the IDL (Interface Definition Language) file
write a .Net application that consumes services provided by remote Java objects
expose methods in .Net code that will subsequently be invoked by Java objects
In order to compile and run the example files, the following software is necessary:
-
Chat Subscriber
Network/
Internet
For the screen shot above, the tool was pointed to the ChatHost.jar of the example. The Host and Subscriber interfaces were
selected. MCjava2cs further lists serializable Classes (passed by value) for selection:
The example contains two classes of this type that were both selected above. The last step is to run the generation process which
creates C# code for the selected interfaces:
The tool actually performs two distinct tasks. First, it extracts the IDL definition from the Java code. Second, it generates C# code
based on the IDL generated during step 1. The IDL file is transient because it is not needed once the C# code has been generated. The
tool created a file named host.cs, based on the name space of the Java interface. It contains the host class skeleton code and some
helper methods. If this sounds like something you dont want know, you can relax. MCjava2cs.exe allows you to write CORBA code
without any knowledge of IDL syntax and IDL types.
When I used the tool, I experienced problems with JVM version 1.4.2_04-b04, but it worked with JVM 1.4.2_05-b04. Also, make sure
that there are no spaces in the path to the JAR file and the C# output path. These issues will likely be fixed by the time you download
the trial software.
To better understand the purpose of the methods that the Java host makes available, it is beneficial to take a detailed look at the
communication between the host and a subscriber.
In the sequence diagram above, the host interface exposes three methods that will be called by subscribers: signOn(), signOff()
and sendMessage(). The method signOn()accepts one parameter (subscriberAccount) and returns a HashTable with all
subscriber names. sendMessage() is called by the subscriber to send a message and requires the senders name and the message as
parameters. signOff() is called by the subscriber to end the chat session. Since the subscriber name is used as a key, it must be
unique.
The subscriber, on the other hand, must allow the host to update the display, by exposing its interface to the host for a method call:
displayMessage() requires two parameters the name of the sender and the message itself.
The class subscriberAccount is known to both the host and the subscriber and is passed by value. It holds information about a
subscribers name, hobby and Subscriber interface. The latter must be exposed to the host so that the host can call the subscribers
displayMessage() method. The Java implementation looks as follows:
public class SubscriberAccount implements Serializable
{
private String
name;
private String
hobby;
private Subscriber
subscriber;
Subscriber _subscriber)
The rest of the presentation code should be straight-forward to read and understand and will not be discussed here.
Instead, the article will walk through the Subscriber interface and the Connection class that provides a wrapper for the remote objects
and manages the connection.
The folder /Serializables in the Visual Studio project helps to organize the solution. It contains the implementations of all serializable
CORBA classes, or CORBA valuetypes. In this case, they are SubscriberAccountImpl and SubscriberInfoImpl. They
are derived from Chat.SubscriberAccount (SubscriberInfo, respectively),which are generated classes in Chat.cs. These
classes are used to pass subscriber information between the client and the server. SubscriberInfo does not expose the subscribers
interface, which is only needed by the host, and can therefore be safely passed to other clients. The suffix Impl is a naming
convention that serves as a reminder of this fact.
The generated parent class already defines the properties and has abstract getter- and setter-method declarations. Therefore, the
implementation is rather simple:
namespace Chat
{
public class SubscriberAccountImpl: Chat.SubscriberAccount
{
public SubscriberAccountImpl()
{
}
public SubscriberAccountImpl( string _name, string _hobby,
Subscriber _subscriber)
{
name = _name;
hobby = _hobby;
subscriber = _subscriber;
}
The implementation of the subscriber interface exposes one method, displayMessage(), that the host can call.
namespace DotNetClient
{
public class SubscriberImpl: Chat.SubscriberPOA
{
private AsyncUIAccess m_oUserInterface;
public SubscriberImpl( AsyncUIAccess a_oUserInterface)
{
m_oUserInterface = a_oUserInterface;
}
AsyncUIAccess is the implementation of the display queue for the timer that was mentioned earlier.
SubscriberPOA, the parent of the SubscriberImpl, is also a generated class. POA stands for Portable Object Adapter. When a
client invokes a server object, the POA helps the request broker to activate the appropriate object and to deliver requests to it.
The last module on the client side that deserves attention is Connection.cs. This class contains the methods that manage the
communication between subscriber and host. It maintains a reference to the host and to its own interface. It also instantiates an object
request broker instance (ORB).
public class Connection
{
private string[] m_strORBInit =
{"-ORBInitRef NameService=corbaloc:iiop:1.2@<ServerAdress>:1050/NameService",
"-ORBDebug",
"-AddAssembly DotNetClient.exe, JavaBuiltinTypesCF.dll, MinCorCF.dll"
};
private
private
private
Chat.Host
Chat.SubscriberAccount
Middsol.CORBA.ORB
m_oChatHost;
m_oAccount;
m_oOrb;
signOn() is called by the user interface when the client wants to connect to a server.
public void signOn( AsyncUIAccess a_oAsyncUIAccess, string a_strIpAddr,
string a_strName, string a_strHobby)
{
// Instantiate local ORB, find remote ORB and connect
initializeConnection( a_oAsyncUIAccess, a_strIpAddr);
// Instantiate local Subscriber interface
Chat.Subscriber oSubscriber = new SubscriberImpl( a_oAsyncUIAccess)._this();
// create local subscribers account object
m_oAccount = new Chat.SubscriberAccountImpl( a_strName, a_strHobby, oSubscriber);
try
{
// sign on and display returned list of participants
displayListOfSubscribers( a_oAsyncUIAccess, m_oChatHost.signOn( m_oAccount));
}
catch( Middsol.java.lang.Ex ex)
{
a_oAsyncUIAccess.writeLog("+++ Sign-on failed. +++");
a_oAsyncUIAccess.writeLog("+++ Please try another name.+++");
deinitializeConnection();
}
}
signOff() calls this very method on the host in order to remove this instance from the list of subscribers.
public void signOff( )
{
if( m_oOrb != null)
{
m_oChatHost.signOff( m_oAccount.queryName());
deinitializeConnection();
}
}
connectToHost( a_oAsyncUIAccess);
}
catch(Middsol.CosNaming.NamingContextPackage.NotFound ex)
{
//Name service not running or not accessible
a_oAsyncUIAccess.writeLog( "NS Manager Error:" + ex.why);
throw new System.Exception();
}
catch( Middsol.CORBA.SystemException exSys)
{
a_oAsyncUIAccess.writeLog( "Server exception caught (Middsol.CORBA.SystemException).");
a_oAsyncUIAccess.writeLog( "ID:" + exSys.ID);
deinitializeConnection();
}
initCORBA() contains standard CORBA initialization code. It uses the .Net DNS API to get the local devices IP address,
instantiates a new ORB, retrieves a reference to the newly created root portable object adapter (POA) and narrows it to the correct
type (Middsol.PortableServer.POA). Finally, it activates the POA that has been in a holding state.
private void initCORBA( AsyncUIAccess a_oAsyncUIAccess, string a_strIpAddr)
{
m_strORBInit[0] = m_strORBInit[0].Replace("<ServerAdress>", a_strIpAddr);
m_oOrb = Middsol.CORBA._ORB.init( m_strORBInit, null);
Middsol.PortableServer.POA oRootPOA =
Middsol.PortableServer.POAHelper.narrow( m_oOrb.resolve_initial_references( "RootPOA" ));
oRootPOA.the_POAManager.activate();
connectToHost() uses the Java Naming Services to locate the host. It requires an IP address, connects to the name server on this
host and requests the location of a server called ChatHost. AsyncUIAccess, while not needed by some of the method, is passed
anyways to enable future improvements.
private void connectToHost( AsyncUIAccess a_oAsyncUIAccess)
{
Middsol.CosNaming.NamingContextExt oNsCtx =
Middsol.CosNaming.NamingContextExtHelper.narrow(
m_oOrb.resolve_initial_references("NameService"));
m_oChatHost = Chat.HostHelper.narrow( oNsCtx.resolve_str("ChatHost"));
a_oAsyncUIAccess.writeLog( "Chat host connected");
}
displayListOfSubscribers() iterates through the list of subscribers that the host returned and writes each entry to the list
box on the screen.
}
a_oAsyncUIAccess.writeLog("-----------------");
}
The client executable runs as a Windows application, too, which makes it very easy to test.
With these restrictions in mind, use the following steps to build and test the applications:
-
Please feel free to improve the code and direct all questions or comments to the author at ([email protected]).
Conclusion
This article demonstrated that it is possible to integrate with a Java back-end from a .Net application, specifically from the Compact
Framework, with very little knowledge of the technical details of the middleware. Middsols MinCor.NET, although a young product
and still a little rough around the edges, is a powerful tool that connects your .Net application to a vast selection of CORBA-enabled
targets, including J2EE Enterprise beans and RMI objects, without any further tools.
About the Author
Christian Donner is a Senior Consultant and Application Architect with Molecular Inc., a premier technology consulting firm based in
Watertown, Massachusetts. When he does not tinker with mobile technology, he designs and develops enterprise-level web solutions
for Fortune 1000 clients.
Resources
Introduction to Development Tools for Windows Mobile-based Pocket PCs and Smartphones (recommended!)
http://msdn.microsoft.com/mobility/windowsmobile/default.aspx?pull=/library/en-us/dnppcgen/html/devtoolsmobileapps.asp
Fundamentals of Microsoft .NET Compact Framework Development for the Microsoft .NET Framework Developer
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/net_vs_netcf.asp
Download the MinCor.Net evaluation copy
www.middsol.com