Nokia M2M Platform Server Application: Programming Guide
Nokia M2M Platform Server Application: Programming Guide
PROGRAMMING GUIDE
Copyright © 2002-2003 Nokia. All rights reserved. Issue 7.0 9355793
Contents
Acronym/term Description
AM Application Module
ANC Active Naming Context
ASCII American Standard Code for Information
Interchange
CHAP Challenge Handshake Authentication Protocol
CORBA Common Object Request Broker Architecture
GIOP General Inter-ORB Protocol
GSM Global System for Mobile Communications
IDL Interface Definition Language
IMP Information Module Profile
IOR Interoperable Object Reference
IP Internet Protocol
™
J2ME Java™ 2 Micro Edition
J2SE™ Java 2 Standard Edition
M2M Machine-to-Machine
ORB Object Request Broker
POA Portable Object Adapter
SDK Software Development Kit
TCP Transmission Control Protocol
VM Virtual Machine
WAP Wireless Application Protocol
WTP Wireless Transport Protocol
1/28
1. INTRODUCTION
This document is intended to guide application developers who want to develop
customer server applications for the Nokia Machine-to-Machine (M2M)
Platform.
In the Nokia M2M system architecture, the term customer server application
refers to applications that are typically located in the customer intranet and
connected to the Nokia M2M Gateway (hereon Gateway). At the opposite end
of the Nokia M2M Platform, the counterpart of the customer server application
can be executed either in the Application Module (AM) software or an IMlet
located in the Nokia 12 GSM module (hereon Nokia 12 module).
Note: The customer server application does not necessarily function as a server
in terms of the client-server architecture, although this is often the case. See the
Nokia M2M Platform Software Developer’s Guide for a more detailed description
on the Nokia M2M system architecture.
This document focuses on those customer server applications that utilise the
Nokia M2M Platform. Thus M2M applications that do not require any
programming specific to the Nokia M2M Platform are not in the scope of this
document.
All code examples included in this document are written in the Java™
programming language. This language was chosen because it is widely used in
server side programming. Readers are expected to have a basic knowledge of
Java programming and therefore this document does not describe the basics of
Java programming in detail. The programming focus is on the M2M application
specific parts of the source code instead.
The Nokia M2M Platform utilises the Common Object Request Broker
Architecture (CORBA) as middleware and therefore the M2M applications used
in the Platform are language-independent. However, all applications must be
implemented with a programming language that enables CORBA language
mapping.
2/28
In this document it is assumed that the Nokia M2M Platform has been
successfully installed and applications can be run on top of it. For more
information on how to install and configure the components of the Nokia M2M
Platform, see the Nokia M2M Platform Software Development Kit and Nokia
M2M Gateway Trial Version Installation Guide and the Nokia M2M Platform
Configuration Manual.
3/28
2. DEFINING A CORBA INTERFACE
In the interface definition phase, the application developer must know what kind
of data one end of the application needs to receive from the other end.
Naturally the interface can be modified as the application implementation
proceeds, but each time the interface is modified, both ends of the application
must be updated to conform to the new interface definition.
module tutorial1 {
interface Hello {
exception EmptyGreetingsStringException { };
};
};
The first row defines the module where the interface belongs. When the
interface definition is compiled to Java code, the module is mapped to a
package called tutorial1.
On the second row, the Hello interface maps to an interface in Java code. A
servant object (CORBA implementation) then implements that interface.
The third row defines a user exception that can be thrown by the sayHello
method.
4/28
The last entry in the interface definition is the actual method call (sayHello). It
gets a string as an input parameter and returns a response string.
The interface definition described above contains all the necessary information
for both ends of the application. However, both the client and the
implementation utilise the code generated from the interface definition
differently. As the name implies, the implementation implements the interface.
That is, a class that implements the Hello interface must have a method
named sayHello, and its input parameter and return value must conform to
the interface definition. The client does not implement the sayHello method; it
simply calls that method from another object that implements the interface.
The Java SDK 1.4 includes an executable called idlj that generates Java
source code from an interface definition. The idlj compiler can be given
different parameters and it can be used to generate, for example, only the stub
code. In the Tutorial1 application the idlj has been set to compile the interface
definitions with a –fall parameter that causes the compiler to generate all
bindings (stub and skeleton code).
Note: You may want to optimise the use of the idlj in your applications to
decrease the number of generated classes.
Note: If you compile your applications with other prefixes (or without prefixes),
make sure that you implement the corresponding changes also to your application
5/28
source code.
This command generates the Java source code (both stub and skeleton codes)
to an idl_generated directory. It gives a
com.nokia.m2m.sdk.examples.tutorial1.idl package prefix for the
Tutorial1 interface by using the tutorial1.idl file as an input for the IDL
compiler.
6/28
3. CREATING A CORBA CLIENT
This chapter describes the communication parts of the Tutorial1 customer
server application CORBA client, that is, how to invoke a remote method.
Note: Although this chapter deals with the Tutorial1 application, similar actions
must be taken in all applications that are used to make remote method
invocations over the Nokia M2M Platform.
The client part of the Tutorial1 customer server application makes a request to
the implementation (servant) part of the same application as described in
Chapter 2.1. The client communicates wirelessly with the servant over the
Nokia M2M Platform. The complete source code of the Tutorial1 application
CORBA client can be found from the Nokia M2M SDK.
To execute a remote method, the server side CORBA client application must
carry out the following steps:
4. Narrow (cast) the retrieved CORBA object to a specific object type (type
‘hello’ in this case).
The above five steps of the Tutorial1 application source code are described in
more detail in the following chapters.
7/28
This is a standard procedure for Java applications to initialize an ORB and
obtain a reference for it.
org.omg.CosNaming.NamingContextExt nc =
org.omg.CosNaming.NamingContextExtHelper.narrow(
orb.resolve_initial_references("NameService"));
8/28
the best suited object reference retrieval method may vary from application to
application. The different object reference retrieval and publishing methods are
discussed in more detail in the Nokia M2M Platform Software Developer’s
Guide.
The Nokia M2M Platform includes a Nokia Active Naming Context (ANC)
implementation (see the Nokia M2M Platform Active Naming Context
Programming Guide for details) called M2MDevices. This implementation is
registered to the CORBA Naming Service with the name
’NokiaANC/M2MDevices’ during the Gateway start-up.
org.omg.CORBA.Object helloReference =
nc.resolve(
new NameComponent[] {
new NameComponent("NokiaANC", ""),
new NameComponent("M2MDevices", ""),
new NameComponent(
terminalID
+ ";HelloServant"
,"")});
9/28
The port number is retrieved either from the class information database or
bearer information database depending on the addressing type of the bearer.
Note: The port number that the NokiaANC/M2MDevices inserts to the object
reference depends on the used bearer. TCP port numbering is used for sms.tcp,
csd.tcp, and gprs.tcp bearers, and the port number is fetched from the class
information database. Wireless Transport Protocol (WTP) port numbering is used
for sms.wap, csd.wap, and gprs.wap bearers, and the port number is fetched from
the bearer information database.
Note: The iorgen implementation does not utilise the bearer information database
or the class information database. Therefore, all the parameters that the
M2MDevices implementation retrieves from these databases must be given
separately when using the iorgen implementation.
org.omg.CORBA.Object helloReference =
nc.resolve(
new NameComponent[] {
new NameComponent("NokiaANC", ""),
new NameComponent("iorgen", ""),
new NameComponent(
bearer
+ ";"
+ terminalID
+ ";"
+ port
+ ";ORB/OA/IDL:tutorial1/hello:1.0;"
+ tutorial1.helloHelper.id(),
"")});
The iorgen implementation constructs the object reference from the parameters
that it receives. The syntax is
<bearer>;<terminal-id>;<port>;<object-key>;<type-id> ,where:
10/28
• <terminal-id> is the identifier for the target Nokia terminal or Nokia 12
module found from the user information database of the Gateway
(user_information.txt file if the reference implementation is used).
• <port> identifies the port number where the object is located at the remote
end. If the selected bearer uses WTP port numbering (sms.wap, csd.wap
and gprs.wap bearers), the port number indicates the WTP port at the
remote end. If the selected bearer uses TCP port numbering (sms.tcp,
csd.tcp and gprs.tcp bearers), the port number indicates the TCP port at the
remote end.
• <object-key> identifies the object key of the remote object in American
Standard Code for Information Interchange (ASCII) mode. Object keys of
objects in devices compatible with the Nokia M2M Platform can be found
from the reference implementation of the class information database (the
class_information.txt file).
• <type-id> is the type ID of the target object interface. It can be requested
from the helper class of the interface via an id() method, for example
tutorial1.helloHelper.id(), as described in the above code example.
interface ObjectFactory {
Object createObject();
};
the customer server application can request for a reference to a new object
(provided that the customer server application already has a reference to the
object that implements the ObjectFactory interface) simply by executing the
following method call:
org.omg.Object o = factory.createObject();
11/28
In the case of the Tutorial1 application, the Hello object has its own helper
method. A CORBA object is narrowed to a Hello object with the following
command:
Hello helloInstance =
HelloHelper.narrow(helloReference);
The Tutorial1 application executes the sayHello() method of the Hello object
in the remote Nokia terminal or Nokia 12 module:
String reply =
helloInstance.sayHello(“Greetings from the server side
application”);
The following takes place during the processing of the previous command:
3. The ORB establishes a connection to the ORB of the remote Nokia terminal
or Nokia 12 module with the help of the Gateway.
4. The ORB of the remote Nokia terminal or Nokia 12 module first receives the
GIOP message. It then finds an object (in this case Hello) that implements
the sayHello() method of the Tutorial1 interface definition.
At this point the Tutorial1 application has executed the remote method if the try-
block has not caught any exceptions.
12/28
4. CREATING A CORBA IMPLEMENTATION
This chapter describes the CORBA implementation part of the Tutorial1
customer server application, that is, how to make a servant.
Note: Although this chapter deals with the Tutorial1 application, similar actions
must be taken in all applications where CORBA implementations, compatible with
the Nokia M2M Platform, are made.
1. Initialize an ORB.
13/28
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(new String[0],
null);
Every ORB has at least one POA called the RootPOA. The Tutorial1 application
uses the RootPOA, and a reference to it is retrieved with the following
command:
org.omg.PortableServer.POA poa =
org.omg.PortableServer.POAHelper.narrow(
orb.resolve_initial_references("RootPOA"));
Tip: You can create your own POA if you want to define a different POA policy
(such as Lifespan policy or ID Assignment policy) than what is defined for the
RootPOA. Using a POA with different policies may have an effect on the source
code of the customer server application. For example, the RootPOA always uses
the Implicit Activation Policy, which means that a servant object is not explicitly
activated to a POA. Instead, it is implicitly activated during object reference
retrieval from the POA. If the POA that you use does not utilise the Implicit
14/28
Activation Policy, you need to activate the servant object explicitly with the
activate_object() or the activate_object_with_id() method.
By default, a newly created POAManager is in the ‘hold’ state meaning that all
calls to those servant objects that are associated with the newly created
POAManager via their POAs hang in queue. When a POAManager is activated,
the POAs associated with it start processing requests for their servant objects.
poa.the_POAManager().activate();
Tip: If it seems that the servant application does nothing and the client application
keeps waiting for a reply from the servant, it may be that the POAManager has
not been activated. In this case, activate the POAManager in your application.
The Tutorial1 application publishes the object reference of the servant object
(helloServant) by binding the reference to the Naming Service. This requires
two parameters: a name with which the object reference can be resolved from
the Naming Service and the object reference (IOR) that is returned as a reply to
the Naming Service request.
The object reference of the servant object is requested from the POA where the
servant object is registered. In the Tutorial1 application, the servant object has
not been registered with the POA at this point. However, since the Tutorial1
application uses the RootPOA and the RootPOA uses the Implicit Activation
Policy, the servant object is implicitly activated while requesting the object
reference from the POA. Therefore, the following command returns a reference
to the servant object and registers the servant object (helloServant) with the
RootPOA:
org.omg.CORBA.Object o = poa.servant_to_reference(helloServant);
15/28
After retrieving the object reference of the servant object, it must be narrowed
(cast) to a right type with the help of the class-specific helper that, in this case,
is the helloHelper class. After the narrowing operation, reference to the
servant object is ready to be bound to the Naming Service.
helloServantReference =
tutorial1.helloHelper.narrow(o);
nc.rebind(nc.to_name("Hello"), helloServantReference);
orb.run();
Note: It is not mandatory to call the orb.run() method, but in that case the
application should use some other means to keep the ORB thread running and
the servant object available for clients.
16/28
5. COMPILING AND RUNNING AN M2M APPLICATION
To compile the Tutorial1 application, the Java compiler needs to locate the
application source code and the stub and skeleton codes that were generated
from the interface definition.
The Tutorial1 application is deployed with the pre-compiled stub and skeleton
source codes that have been generated to the idl_generated directory. Thus,
the Tutorial1 application can be compiled by executing the following command
in the server directory of the Tutorial1 application:
This command generates the Java byte code to the classes directory (that
directory must exist) from the Tutorial1 application’s source code. The
command uses the stub and skeleton codes that were previously generated to
the idl_generated directory.
Before running the Tutorial1 customer server application, you must start the
Nokia M2M Gateway Trial Version as described in the Nokia M2M Platform
Software Development Kit and Nokia M2M Gateway Trial Version Installation
Guide. Once it is running, you can run the application by executing the following
command in the server directory of the Tutoria1 application:
This command starts the CORBA client of the Tutorial1 application. The servant
is started with a similar command except that the Client class is replaced with
the Servant class.
The ORBInitialPort parameter is given to the ORB of the Java SDK to define
the port where the CORBA Naming Service is located. If some other ORB than
that of the Java SDK is used, the application must be told how to locate the
used ORB and Naming Service.
Note: The Tutorial1 application uses the default values for terminal ID, bearer,
and port as described in the Nokia M2M Platform Configuration Manual. If you
want to use other than the default values, you need to modify the source code
accordingly and recompile the application as instructed above.
17/28
6. ADVANCED CORBA PROGRAMMING
This chapter describes the Tutorial2 application that is also included in the
Nokia M2M SDK. In the Tutorial2 application, the CORBA implementation is in
the Java 2 Standard Edition (J2SE™) code and the CORBA client is in the Java
2 Micro Edition (J2ME™) code that conforms to the Information Module Profile
(IMP).
The application logic of the Tutorial2 application is similar to that of the Tutorial1
application: the client sends a greeting string to the servant and the servant
sends a reply string back. The difference between the Tutorial1 and Tutorial2
applications is that in the Tutorial2 application the J2SE code uses the CORBA
object factory technique to generate unique object references for the calling
clients.
The core functionality of the CORBA object factory is thus in the Connection
interface. Implementation of the Connection interface is responsible for
generating unique object references to the Hello servant for each calling client.
18/28
The complete source code and the interface definition file for the Tutorial2
application can be found from the Nokia M2M SDK.
module tutorial2{
interface Hello {
exception EmptyGreetingsStringException { };
void logout();
};
interface Connection {
};
};
The servant side also contains one additional class that has its source code in
the tutorial2.java file. This class is merely a launcher for the ConnectionImpl
servant.
• CORBA initialization
• POA creation
• Instantiation and reference publishing of the Hello interface implementation
• Shutting down CORBA services
19/28
communicating with the servant, it must call a logout method of the Hello
interface implementation that deactivates the client-specific, unique CORBA
object referencing to the Hello servant.
6.1.2.1 Initialization
The Tutorial2 application is launched from the Tutorial2 class that instantiates
the ConnectionImpl class. The beginning of the ConnectionImpl code follows
the implementation of the Tutorial1 application: execution of ORB initialization,
POA reference retrieval, and POAManager activation for the RootPOA (see
Chapter 4).
The rest of the steps are done differently as described in the following chapters.
With these policy settings, the new POA is configured so that it is suitable for
the CORBA object factory.
Note: The new POA needs not to be activated because it shares the same
POAManager with the RootPOA that was activated earlier.
connectionsPOA = rootPOA.create_POA(
// Name for this POA.
"Connections-POA",
// POA manager; use the same POA manager as the root POA.
rootPOA.the_POAManager(),
// Policies:
new Policy[] {
20/28
rootPOA.create_id_uniqueness_policy(
IdUniquenessPolicyValue.MULTIPLE_ID),
rootPOA.create_id_assignment_policy(
IdAssignmentPolicyValue.USER_ID),
rootPOA.create_servant_retention_policy(
ServantRetentionPolicyValue.NON_RETAIN),
rootPOA.create_request_processing_policy(
RequestProcessingPolicyValue.USE_DEFAULT_SERVANT),
});
21/28
poa.deactivate_object(objectID);
} catch (org.omg.CORBA.UserException ignored) {
}
6.1.2.4 Setting the default servant for the Portable Object Adapter
Since the POA used in the Tutorial2 application uses the
USE_DEFAULT_SERVANT policy, the POA must be instructed of what is the
default servant. The default servant is defined with the set_servant() method.
All invocations that come to the POA used in the Tutorial2 application are
dispatched to the servant defined here:
connectionsPOA.set_servant(helloServant);
The Tutorial2 application binds the Connection servant to the CORBA Naming
Service. The binding is done as in the Tutorial1 application:
try { nc.unbind(nc.to_name(connectionName));
} catch (Exception ignore) { }
try { orb.shutdown(true);
} catch (Exception ignore) { }
}
22/28
6.1.2.7 Login method
The login() method of the Connection interface implementation is the core of
the object factory. It creates a unique object reference (IOR) that refers to the
HelloImpl servant (created earlier by the ConnectionImpl servant).
The object reference to be created obtains its object ID from the input
parameter of the login() method. In the Tutorial2 application, the client (IMlet
running in a Nokia 12 module) uses its terminal ID as the parameter and this is
why each calling client receives a different object reference.
org.omg.CORBA.Object ref =
connectionsPOA.create_reference_with_id(oid,
HelloHelper.id());
6.1.3.1 Initialization
The client application first creates an ORB instance and casts it to the type
com.nokia.m2m.orb.ORB. The casting is done to get access to an extra
method that the application uses later to create a named reference type
CORBA object reference. For more information on named reference and other
object referencing options available in the Nokia M2M Platform, see the Nokia
M2M Platform Software Developer’s Guide.
23/28
6.1.3.2 Retrieving a reference to the Connection interface implementation
The next step is to retrieve a reference to the servant that implements the
Connection interface. The reference is retrieved by creating a name
component array, passing that array (together with a Connection type ID) as
an argument to the createNamedReference() method of the nokiaorb, and
narrowing the object reference resulting from the createNamedReference()
method to be of the Connection type.
NameComponent[] nca =
new NameComponent[] {
new NameComponent("Tutorial2ConnectionServant", ""), };
org.omg.CORBA.Object namedRef =
nokiaorb.createNamedReference(nca, ConnectionHelper.id());
Note: When using the named reference mechanism, the reference retrieval does
not create any traffic over the air interface.
When the Hello servant knows the identity of the calling client, it can use that
information for client-specific processing. The incoming CHAP username can
be queried from the Device object located in the Nokia 12 module ORB, but
before the application can do that, it needs a reference to the Device object.
The reference is retrieved using the corbaloc mechanism, and it is then
narrowed (cast) to the type Device:
Object devObj =
orb.string_to_object("corbaloc::127.0.0.1:19740/Device");
The Device object has a getParam() method that can be used to query
Device object parameters described in the Nokia GSM Connectivity Terminal
and Nokia 12 GSM Module Properties Reference Guide.
24/28
The getParam() method must be given the name of the parameter to be
queried and a holder for the CORBA type any that holds the queried parameter
after the method call returns. The contents of the any type can be read from the
any holder using parameter-specific helpers.
At this point the client application has an ID string it can use as a parameter for
the login() method of the Connection interface implementation:
25/28
7. TROUBLESHOOTING
If the application cannot run successfully and receives a CORBA
COMM_FAILURE exception, it can use a convenience class called
GIOPMinorCodeParser (included in the Nokia M2M SDK) to print out the error
description.
You may find, for example, the following error notification in the command
prompt:
Nokia M2M Gateway - Authentication Error: The Device Information
Storage (DIS) does not have the user information for a terminal.
In this case the failure occurred because the authentication information was
missing from the user information database ( user_information.txt file if the
reference implementation is used).
The Nokia M2M Platform specific minor exception codes are described in the
Nokia M2M Platform GIOP Minor Exception Code Descriptions. If the
GIOPMinorCodeParser class is not used, you can check the exception code
descriptions from that document.
26/28
8. REFERENCES
Nokia M2M solution
CORBA
http://developer.java.sun.com/developer/technicalArticles/releases/corba/ - an
article about J2SE specific CORBA programming
http://developer.java.sun.com/developer/onlineTraining/corba/corba.html - short
course that teaches how to use CORBA as found in the Java 2 platform
27/28
APPENDIX A: GIOP MESSAGE FRAGMENTATION
This appendix explains how to configure the customer server application to
support fragmentation. For more information on how to configure the AM ORB
to support GIOP message fragmentation, please refer to the Nokia M2M
Platform Remote Application Programming Guide.
If you use a wireless bearer that utilises TCP as its transport protocol [csd.tcp |
gprs.tcp], the transport protocol takes care of fragmenting long messages and
there is no need for additional configurations.
-Dcom.sun.CORBA.giop.ORBFragmentSize=512
28/28