Connector Service Bundle

The Connector Service Bundle provides ProSyst's implementation of the OSGi IO Connector Service, specified in the OSGi Service Platform Specification Release 4. It supplies a model through which bundles can communicate with external resources through different connection implementations. The OSGi communication API applies the advantages of the J2ME architecture to the OSGi Service Framework. It allows creating applications that occupy small amounts of resources. It is easy to use and provides many different connection implementations simultaneously.

Note: Using the Connector Service Bundle make sense only when the Standard Version of mBeddedServer framework is used (see "Framework Versions" chapter of the current documentation). In case running the Connector Version of the framework the functionality of the Connector Service Bundle is implemented by the System Bundle.

Contents:


Bundle Information

Bundle JAR

The JAR file of this bundle is connector.jar, located in the bundles folder.

Import

Package Exporter Description
javax.microedition.io System Bundle/
ProSyst Util Full Bundle
Generic connection API.
com.prosyst.util.hash Delivers hashtable utilities.
com.prosyst.util.ref ProSyst Util Bundle/
ProSyst Util Full Bundle
Allows the Connector Service Bundle to store log messages through the Log Service.

Export

Package Description
org.osgi.service.io The OSGi communication API.
org.mbs.services.io The ProSyst connection API. Provides means for creating connection listeners.

OSGi Communication API Overview

The communication API of OSGi is defined for all bundles that require connectivity to external computers or devices. It uses the J2ME Connection Framework, represented by the javax.microedition.io API. This model is based on a Connector class which manages many different connection implementors.

The OSGi Communication API replaces the javax.microedition.io.Connector class from J2ME with its own ConnectorService interface (org.osgi.service.io.ConnectorService) available as a service in the framework. This is necessary for the needs of the OSGi Service Framework model. The OSGi IO Connector Service manages the available connection implementations and creates connections requested by bundles. Services which need to create connections must use the IO Connector Service. They need NOT work directly with the connection implementors.

The communication implementations are registered as services called "connection factories". They are represented by the org.osgi.service.io.ConnectionFactory interface. Each connection factory declares the types of connections it implements by registering for a particular scheme. A scheme is the protocol or pattern of communication implemented. A bundle which demands a connection must pass to the IO Connector Service a valid Uniform Resource Identifier (URI) starting with the expected scheme. The scheme is the part of the URI before the first ":". When the IO Connector Service receives the URI, it parses it and then redirects the URI to the appropriate connection factory.

Each bundle that needs to communicate must invoke some of the open methods of the IO Connector Service. The connection factory found by the Connector Service will create a javax.microedition.io.Connection object.


Figure 1: The connection-requester bundle uses the IO Connector Service to make the appropriate connection factory create the desired connection

IO Connector Service

This service is implemented as described in the OSGi specification. In addition, it possesses capabilities to dynamically detect new connection factory services registered with the framework.

When this service is registered, it checks for connection factories registered before its activation and starts listening for the registration of new connection factories.

If a connection factory is found (or a notification for its registration is received), the IO Connector Service inspects its scheme. If there isn't a connection factory already registered for that scheme, the new connection factory is added to the list of known factories. If there is a connection factory already responsible for that scheme, then the newly found one replaces the old one only if it has higher ranking (a service's ranking is determined by the value of the org.osgi.framework.Constants.SERVICE_RANKING ( "service.ranking") property with which it is registered by the registerService method).

How the IO Connector Service Creates Connections

When the open method of the IO Connector Service is invoked by some bundle needing a connection, there are two possibilities:

This pattern is visualized in Figure 1.


Figure 2: How the IO Connector Service creates connections

The IO Connector Service creates each connection by invoking the connection factory's createConnection method. Before the connection is initiated, the Connector Service parses the requested URI and then places its components into a Dictionary, so that the ConnectionFactory will be able to get only the components it needs.

A connection has three modes: read, write and read&write. They are defined as constants in the ConnectorService interface and can be passed as a parameter to the open method. If no mode is passed, the read&write mode is implied.

Tip: You can obtain a normal java.io stream instead of a javax.microedition.io.Connection by using the openOutputStream / openDataOutputStream methods.

Note: If the connection factory or the Connector Service gets unregistered, the connection factory's close() method is invoked to withdraw all connections currently available in the connection factory.

Connection Types

The generic connection interface obtained through the IO Connector Service is javax.microedition.io.Connection. However, this interface is not convenient to use because it contains only one method: the close() method. The open method is not defined here because the opening of a connection is always handled by the IO Connector Service.

The javax.microedition.io package contains a set of much more convenient connections extending the generic interface. Figure 3 shows the connection hierarchy in the package.


Figure 3: Connection hierarchy in javax.microedition.io

Most connection factories created by ProSyst return not the generic connection itself but some of its inheritants. They contain useful methods allowing you to send and/or receive data through input/output streams or datagram packets. See each connection factory's description in the Connection Category chapter for details about the connection types supported by it.

Composing URIs

The format of the URI must be composed according to RFC 2396 (Uniform Resource Identifiers (URI): Generic Syntax). Usually, the form of a URI is: <scheme>:<target>[<params>], where parts enclosed in [..] are optional. For example:

socket://127.0.0.1:1449

sms://+46705950899

Using the Service

As already mentioned, each bundle that needs a connection must get the IO Connector Service and invoke some variant of its open method. The bundle requester does not need to work directly with connection factories. The IO Connector Service handles processing all registered connection factories and decides which particular connection factory to use.

Note: On finishing all your work or getting unregistered, close the opened connection.

We'll illustrate using the OSGi communication model through two example classes (listings 1.1 and 1.2) packed in two separate bundles which communicate over the socket scheme. This scheme is implemented by the Socket Connection Bundle. See its description for more details. The socket pattern requires there to be a server connection (i.e. a server-side TCP/IP socket to be listening) and a client connection opened. Hence, the first bundle will create a server connection waiting for client connections, and the second bundle will create a client connection passing some data to the server. The client and the server URIs are formed according to the syntax required by the Socket Connection Bundle.

import org.osgi.service.io.ConnectorService;
import javax.microedition.io.StreamConnection;

import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.io.StreamConnectionNotifier;
import java.io.DataInputStream;
import org.osgi.framework.*;
import java.io.IOException;

public class IOServer extends Thread implements BundleActivator {

  private ServiceReference         connRef;
  private ConnectorService         connService;
  private StreamConnection         connection;
  private StreamConnectionNotifier server;
  
  public void start(BundleContext bc) {

    connRef = bc.getServiceReference(ConnectorService.class.getName());
    
    if (connRef != null) {
      connService = (ConnectorService)bc.getService(connRef);
      
      try {
        //Creates a read-only server connection on port 3333
        server = (StreamConnectionNotifier)connService.open("socket://:3333", 
ConnectorService.READ); } catch(ConnectionNotFoundException ce) { ce.printStackTrace(); } catch(IOException ioe) { ioe.printStackTrace(); } } start(); } public void run() { try { //accepting the data input from clients connection = server.acceptAndOpen(); DataInputStream inputStream = connection.openDataInputStream(); while(true) { String input = inputStream.readUTF();//we expect String data while(input != null) { System.out.println(input); input = inputStream.readUTF(); } } } catch (Exception e) { e.printStackTrace(); } } public void stop(BundleContext bc) { try { connection.close();//finally, we close the connection } catch(IOException ioe) { ioe.printStackTrace(); } bc.ungetService(connRef); } }
Listing 1.1: Using the IO Connector Service to create a server socket connection

Note that the connection created by the above example is an instance of StreamConnectionNotifier. This is allowed by the implementation of the Socket Connection Bundle.

import org.osgi.service.io.ConnectorService;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.ConnectionNotFoundException;
import java.io.DataOutputStream;
import org.osgi.framework.*;
import java.io.IOException;

public class IOClient implements BundleActivator {

  private ServiceReference       connRef;
  private ConnectorService       connService;
  private StreamConnection       connection;
  
  public void start(BundleContext bc) {

    connRef = bc.getServiceReference(ConnectorService.class.getName());
    
    if (connRef != null) {
      connService = (ConnectorService)bc.getService(connRef);      
      try {
        //passing the client socket URI. Note that we create a StreamConnection
        connection = (StreamConnection)connService.open("socket://localhost:3333");
        DataOutputStream outputStream = connection.openDataOutputStream();
        //the simple String data sent to the server
        outputStream.writeUTF("Hello there from the client!");       
      } catch(ConnectionNotFoundException ce) {
        ce.printStackTrace();
      } catch(IOException ioe) {
        ioe.printStackTrace(); 
      }
    }       
  }
  
  public void stop(BundleContext bc) {
    try {
      connection.close();//not forgetting to close the connection
    } catch(IOException ioe) {
      ioe.printStackTrace();
    }
    bc.ungetService(connRef);    
  }
}
Listing 1.2: Using the IO Connector Service to create a client socket connection

The client bundle sends a greeting String to the server, which prints it in the system output. The created client connection is an instance of StreamConnection.

Note: If you start the two example bundles on different frameworks, you will need an IO Connector Service and a socket connection factory running on each of the frameworks. In this case, change the URIs passed to the Connector.

System Properties

The Connector Service Bundle owns the following user-configurable system properties:

System Property Description
mbs.connector.debug If set to true, the messages at DEBUG level created by the Connector Service Bundle will be stored through the Log Service. By default its value is false.
mbs.connector.console If set to true, the log messages created by the bundle will be printed in the server's console. By default its value is false.
mbs.io.connector.disable.notification If set to true, the notification when a connection is created/closed will be disabled. By default its value is false.

If you set/change these properties after the bundle has been activated, you must restart it so that it will accept the new values.

References


OSGi Bundles