Archived
This forum has been archived. Please start a new discussion on GitHub.
IceGrid sessions, Glacier2 and factory objects?
in Help Center
Working with Glacier2 is still puzzling me. Any help is greatly appreciated.
As a variation on the IceGrid/"sayHello()" example, I extended the Demo module with a "HelloFactory":
Here comes my problem:
Without using the Glacier2 router, both ways work as expected. However, with the Glacier2 router in place, the sayHello() call directly on the allocated Hello object still works, but the alternative via the factory yields an exception:
Below follow some details
On the client, a session is obtained via
Also on the client, I select between the direct approach and the factory using a boolean "withFactory":
Finally,
The server side implementation looks like:
The descriptor file reads:
As a variation on the IceGrid/"sayHello()" example, I extended the Demo module with a "HelloFactory":
On the server side, I created a Hello object and a HelloFactory object, which I both made available as allocatable to the icegrid session. So there are two ways to say hello: either via a call "sayHello()" directly on the allocated "Hello" object, or via a call to a freshly created Hello object from the allocated factory.module Demo
{
interface Hello {
["cpp:const"] idempotent string sayHello();
void shutdown();
};
interface HelloFactory {
["cpp:const"] Hello* createHello( string name );
};
};
Here comes my problem:
Without using the Glacier2 router, both ways work as expected. However, with the Glacier2 router in place, the sayHello() call directly on the allocated Hello object still works, but the alternative via the factory yields an exception:
What am I doing wrong?Outgoing.cpp:388: Ice::ObjectNotExistException:
object does not exist:
identity: `CCBF3961-B714-47D1-88AA-808A2DD75BFC'
facet:
operation: sayHello
Below follow some details
On the client, a session is obtained via
where the branch is selected by setting eitherif(communicator()->getDefaultRouter())
{
Ice::RouterPrx defaultRouter = communicator()->getDefaultRouter();
_router = Glacier2::RouterPrx::checkedCast(defaultRouter);
_session = IceGrid::SessionPrx::checkedCast(_router->createSession( "foo", "bar" ));
}
else
{
IceGrid::RegistryPrx registry = IceGrid::RegistryPrx::checkedCast(
communicator()->stringToProxy("DemoIceGrid/Registry"));
_session = registry->createSession( "foo", "bar" );
}
(use glacier2: only works partially) orIce.Default.Router=Allocate.Glacier2/router:tcp -p 12001
(no glacier2: ok!) in the client configuration file.Ice.Default.Locator=DemoIceGrid/Locator:default -p 12000
Also on the client, I select between the direct approach and the factory using a boolean "withFactory":
HelloPrx hello;
if (withFactory)
{
HelloFactoryPrx hf = HelloFactoryPrx::checkedCast(_session->allocateObjectByType("::Demo::HelloFactory"));
hello = hf->createHello( "<foo>" );
}
else
{
hello = HelloPrx::checkedCast(_session->allocateObjectByType("::Demo::Hello"));
}
hello->sayHello();
Finally,
The server side implementation looks like:
int Server::run(int, char* [])
{
Ice::PropertiesPtr properties = communicator()->getProperties();
Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Hello");
std::string srvId = properties->getProperty("Ice.ServerId");
Ice::Identity id = communicator()->stringToIdentity(properties->getProperty("Identity"));
adapter->add( new HelloI( srvId ), id );
id = communicator()->stringToIdentity(properties->getProperty("Identity2"));
adapter->add( new HelloFactoryI, id );
adapter->activate();
communicator()->waitForShutdown();
return EXIT_SUCCESS;
}
The descriptor file reads:
<icegrid>
<application name="Allocate">
<server-template id="AllocateServer">
<parameter name="index"/>
<server id="AllocateServer-${index}" exe="/home/bertwim/develop/gapps/Linux-2.6/benoitS" activation="on-demand">
<adapter name="Hello" endpoints="tcp" register-process="true">
<allocatable identity="hello-${index}" type="::Demo::Hello" property="Identity"/>
<allocatable identity="hf-${index}" type="::Demo::HelloFactory" property="Identity2"/>
</adapter>
</server>
</server-template>
<server-template id="Glacier2">
<parameter name="instance-name" default="${application}.Glacier2"/>
<parameter name="client-endpoints"/>
<parameter name="server-endpoints"/>
<parameter name="session-timeout" default="30"/>
<server id="${instance-name}" exe="glacier2router" activation="always">
<properties>
<property name="Glacier2.Client.Endpoints" value="${client-endpoints}"/>
<property name="Glacier2.Server.Endpoints" value="${server-endpoints}"/>
<property name="Glacier2.Admin.Endpoints" value="tcp -h 127.0.0.1"/>
<property name="Glacier2.Admin.RegisterProcess" value="1"/>
<property name="Glacier2.InstanceName" value="${instance-name}"/>
<property name="Glacier2.SessionTimeout" value="${session-timeout}"/>
<property name="Glacier2.PermissionsVerifier" value="${instance-name}/NullPermissionsVerifier"/>
<property name="Glacier2.SessionManager" value="DemoIceGrid/SessionManager"/>
</properties>
</server>
</server-template>
<node name="localhost">
<server-instance template="AllocateServer" index="1"/>
<server-instance template="AllocateServer" index="2"/>
<server-instance template="Glacier2" client-endpoints="tcp -p 12001" server-endpoints="tcp"/>
</node>
</application>
</icegrid>
0
Comments
-
I suspect what is going on is the Glacier2 filtering rules are kicking in and denying access to the factory created hello object. To fix this issue you need to add the identity of the allocated object to the Glacier2 identity filter. You can see the Ice manual for full details on this. I also recommend you read my article "Custom Sessions and IceGrid" in issue 19 of the Connections newsletter for an example.0
-
As Matthew pointed out, the problem is most likely that Glacier2 filtering only allows invocations on allocated objects (see 38.14.3 Allocating Servers and Objects).
To allow your client to access objects created by the factory, you can interpose a session like described by Matthew's article from the Connections newsletter issue #19. This interposed session will allow you to disable the default filtering or to add your own filtering.
Another option is to mark the server as allocatable by adding allocatable="true" to the XML server element. With this attribute set, the allocation of the factory object will cause the allocation of the server and will alter the Glacier2 filtering to allow invocations on the objects from the "Hello" object adapter of the allocated server.
Cheers,
Benoit.0 -
The allocatable="true" hint you gave worked.
Thanks.0