Remoting

POCO Remoting User Guide

Introduction

POCO Remoting is a framework for implementing distributed objects and web services in C++. It is

Requirements

Packages

The following packages (which are not part of the free POCO distribution) are required:

Code Quality

The remoting package parses only the C++ header files to detect for which classes code needs to be generated. The parser depends heavily on developers following the POCO coding guidelines:

//@ remote
class NetConf_API ConfigurationService
/// ConfigurationService...

//@ serialize
class NetConf_API ComplexType: public SomeOtherComplexType
/// some ComplexType
{
public:
    ComplexType();
    ~ComplexType();
    void setSomeInteger(int i);
    void setAString(const std::string& aString);
    int getSomeInteger() const;
    int getAString() const;

private:
    int _someInteger;
    int _aString;
};

Note that class members

In the above example SomeOtherComplexType must also have the attribute serialize set.

In the latest version, the Code Generator also supports public data members. This elimates the need for getter/setter methods and simplifies the above code to:

//@ serialize
struct NetConf_API ComplexType: public SomeOtherComplexType
/// some ComplexType
{
    int someInteger;
    int aString;
};

Properties

Properties are defined either at class or method level. The string //@ identifies a properties section. Properties are defined as name = value pair. If the value is missing, true is assumed. For the beginning, the following properties are probably enough:

See the Attribute Reference for a complete list of properties, especially if you plan to use caching, one-way remote invocation or if you require your classes to follow a given XML schema.

How To Generate

Now assume you have written your C++ class, you have set all properties, only the generation itself is missing. Generation will require you to provide a configuration file for the RemoteGen application.

Configuration

This chapter shows the minimum configuration needed for RemoteGen. We assume that POCO is installed in p:\poco.

<AppConfig>
    <RemoteGen>
        <files>
            <include>
                p:/poco/Remoting/include/*/*/RemoteObject.h,
                p:/poco/Remoting/include/*/*/Proxy.h,
                p:/poco/Remoting/include/*/*/Skeleton.h,
                << add your own list of files here >>
            </include>
            <exclude>
            </exclude>
        </files>
        <output>
            <include>p:/poco/Remoting/samples/TestProject/include/</include>
            <flatincludes>false</flatincludes>
            <src>p:/poco/Remoting/samples/TestProject/src</src>
            <schema>p:/poco/Remoting/samples/TestProject/wsdl</schema>
            <bundle>false|true</bundle>
            <namespace>Remoting::Sample</namespace>
            <libraryname>RemotingSample</libraryname>
            <namespacedeclfile>GenProject/RemotingSample.h</namespacedeclfile>
            <copyright>
            All your code are
            belong to us!
            </copyright>
            <mode>[both|client|server]</mode>
            <remoteServices>false|true</remoteServices>
        </output>
        <schema>
            <MyClass>
                <serviceLocations>http://thinkpad:9999/xmlrpc/MyClass/class1</serviceLocations>
            </MyClass>
        </schema>
        <compiler>
            <exec>...</exec>
            <options>...</options>
            <path>...</path>
        </compiler>
    </RemoteGen>
</AppConfig>

Note that expansion of environment variables is supported. Use {ENVAR} on Linux and %ENVAR% on Windows. Depending on your compiler you must set compiler specific settings.

Visual Studio

If you are using Visual Studio 2003 or newer set the compiler block to the following:

<compiler>
    <exec>cl</exec>
    <options>
    /I "C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE",
    /I "C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include",
    /I "p:\poco\Foundation\include",
    /I "p:\poco\Remoting\include",
    /I "p:\poco\XML\include",
    /I "p:\poco\Util\include",
    /I "p:\poco\Net\include",
    << add your own include directories here >>
    /D "WIN32",
    /D "_DEBUG",
    /D "_WINDOWS",
    /D "_MBCS",
    /C,
    /P,
    /TP
    </options>
    <path>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE;
    C:\Program Files\Microsoft Visual Studio 8\VC\BIN;
    C:\Program Files\Microsoft Visual Studio 8\Common7\Tools;
    C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\bin</path>
</compiler>

Update the path setting and the include paths if necessary.

GCC

Configuring GCC is a bit simpler. We assume that poco is installed in /ws/poco.

<compiler>
    <exec>g++</exec>
    <options>
    -I/ws/poco/Foundation/include,
    -I/ws/poco/XML/include,
    -I/ws/poco/Net/include,
    -I/ws/poco/Remoting/include,
    -I/ws/poco/Util/include,
    << add your own include directories here >>
    -E,
    -C,
    -o%.i
    </options>
    <path></path>
</compiler>

Execution

Start RemoteGen.exe /c=MyConfig.xml

Command Line Options

RemoteGen supports the following command line arguments

Generated Files

The RemoteGenerator produces for each object several files. If the remote property is set, an Interface, a RemoteObject, a Proxy, a ProxyFactory, a Skeleton and helper classes are generated. If a class has the serialize property set, a Serializer and a Deserializer class is generated.

Interface

The Interface class will have the same name as the original class but prepended with an upper-case I character, i.e. for a class MyClass, an interface IMyClass will be generated. This class has the same method signature as the original class but acts — as the name suggests — as a pure interface. The interface will be always generated independent of the mode value in the configuration.

RemoteObject

The RemoteObject class implements the Interface and acts as a wrapper around the local object. All method calls are simply delegated to the local object. Generated in server|both mode.

Proxy

The Proxy class implements the Interface and is responsible for serializing requests and deserializing responses. Generated in client|both mode.

ProxyFactory

A factory class for generating proxies of the given type. Generated in client|both mode.

Skeleton

The Skeleton class runs on the server-side and is responsible for deserializing requests and serializing responses back to the caller. Generated in server|both mode.

ClientHelper

The client helper class offers helper functions for the client to easily find objects, i.e. to create Proxy/RemoteObject objects. Generated in client|both mode.

ServerHelper

The server helper class offers helper functions for the server side. It is used to register objects at the server. Generated in server|both mode.

Serializer

Contains code to serialize the given data type. Always generated.

Deserializer

Contains code to deserialize the given data type. Always generated.

Writing an Application

Having generated all the code, the last step is to finally write a server/client application. We assume that we have generated for a class TestProject::MyClass all the code and that we use the binary transport to access it. See Remoting/samples for the full code.

Server

#include "Poco/Remoting/ORB.h"

#include "Poco/Remoting/Binary/TransportFactory.h"
#include "Poco/Remoting/Binary/Listener.h"
#include "Poco/Remoting/Binary/Transport.h"

#include "TestProject/MyClassServerHelper.h"

[...]

// initialize the transport
Poco::Remoting::Binary::TransportFactory::registerFactory();
// register a listener
Poco::Remoting::ORB::instance().registerListener(new Poco::Remoting::Binary::Listener(10003));
// register a single object
Poco::SharedPtr<TestProject::MyClass> ptrObj(new TestProject::MyClass());
TestProject::MyClassServerHelper::registerObject(
ptrObj, "class1", 10003, Poco::Remoting::Binary::Transport::ID, false);

// wait for CTRL-C or kill
waitForTerminationRequest();
// Stop the ORB
Poco::Remoting::ORB::instance().shutdown();

Client

#include "Poco/Remoting/Binary/TransportFactory.h"
#include "Poco/Remoting/Binary/Transport.h"
#include "TestProject/MyClassClientHelper.h"

[...]

// initialize the transport
Poco::Remoting::Binary::TransportFactory::registerFactory();
Poco::AutoPtr<TestProject::IMyClass> ptrObj3 =
TestProject::MyClassClientHelper::findObject(serverName, "class1", 10003, 
    Poco::Remoting::Binary::Transport::ID, false);

Note that the Helper object actually returns an IMyClass. If the client asked for a local object, it would actually receive the RemoteObject, i.e. one would communicate locally!

Supported Transports

Currently three transport implementations exist:

Poco::SharedPtr<TestProject::MyClass> ptrObj(new TestProject::MyClass());
TestProject::MyClassHelper::registerObject(
ptrObj, "class1", 10003, Poco::Remoting::Binary::Transport::ID, false);
TestProject::MyClassHelper::registerObject(
ptrObj, "class1", 10005, Poco::Remoting::SoapLite::Transport::ID, false);