D-Bus method not found at object path despite the fact that method exist - dbus

I implement an app with this com.example.appname.desktop file as follows:
$ cat /usr/local/share/applications/com.example.appname.desktop
[Desktop Entry]
Version=1.0
Terminal=false
Type=Application
Name=appname
Exec=/opt/app/appname %u
DBusActivatable=true
Categories=Network;
MimeType=x-scheme-handler/itmm;
NoDisplay=false
$ cat /usr/share/dbus-1/services/com.example.appname.service
[D-BUS Service]
Name=com.example.appname
Exec=/opt/app/appname
Introspection XML looks like this:
$ qdbus com.example.appname /com/example/appname org.freedesktop.DBus.Introspectable.Introspect
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.Application">
<method name="ActivateAction">
<arg name="action_name" type="s" direction="in"/>
<arg name="parameter" type="av" direction="in"/>
<arg name="platform_data" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
</method>
<method name="Activate">
<arg name="platform_data" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
</method>
<method name="Open">
<arg name="uris" type="as" direction="in"/>
<arg name="platform_data" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface_name" type="s" direction="in"/>
<arg name="property_name" type="s" direction="in"/>
<arg name="value" type="v" direction="out"/>
</method>
----<snipped>-----
But when i try to launch the method it gives me an error:
$ gapplication launch com.example.appname
error sending Activate message to application: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method 'Activate' in interface 'org.freedesktop.Application' at object path '/com/example/appname' (signature 'a{sv}')
Is "annotation name=.." XML tag (see introspection XML) the reason this method is not found?
Browsing to itmm://192.168.1.1/query?version=1.0 via browser launches the application with command line parameter, but it is not launched via D-Bus service and thats what my requirement is. Is there a way to debug this via firefox or google chrome browsers?

I use QT's D-Bus binding to implement D-Bus service. My issue were
My class that implemented D-Bus interface was not inheriting QDBusAbstractAdaptor .
Methods to be exported were not marked as public slots
My original class looked like this below:
class DBusService : public Application
{
QOBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Application")
public:
void Activate(QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
}
void Open(QStringList uris, QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
if( ! uris.size() ) {
return;
}
QUrl url(uris[0]);
//use url
}
}
Following one works:
class DBusService : public QDBusAbstractAdaptor //<----- Inherit from this class
{
QOBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Application")
public slots: // <------ mark public slots
void Activate(QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
}
void Open(QStringList uris, QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
if( ! uris.size() ) {
return;
}
QUrl url(uris[0]);
qApp->MyCustomMethod(url);
}
}
D-Bus debugging tools
These tools helped me debugging D-Bus issues.
dbus-monitor - sniffs traffic on the bus
gapplication - lets you debug DBusActivatable services.

Related

Implenting Get and GetAll with libdbus-1

Given libdbus-1 which is non-negotiable, I'd like to implement Get and GetAll for DBus properties.
I don't really see any examples for this.
Do I just have to match the method with dbus_message_is_method_call() and respond accordingly?
Or is there a built in way of doing this where I have some code to do the heavy lifting.
Once again, switching libraries is not an option so please don't say use Qt, glib, libnih, libsystemd, or anything else. Please be specific to libdbus-1 or don't answer.
Look at the libdbus-1 source code: git://anongit.freedesktop.org/dbus/dbus
There's an example here in bus/driver.c called bus_driver_handle_get_all(). This function implements a reply to "GetAll".
Of course, we need to have GetAll implemented in our xml file for introspection as well.
<interface name='org.freedesktop.DBus.Properties'>
<method name='Get'>
<arg name='interface' type='s' direction='in' />
<arg name='property' type='s' direction='in' />
<arg name='value' type='s' direction='out' />
</method>
<method name='GetAll'>
<arg name='interface' type='s' direction='in'/>
<arg name='properties' type='a{sv}' direction='out'/>
</method>
</interface>
So to reply to this, we need to iterate through all of our properties and load them up in a DBusMessageIter then send this reply to the sender.
Clearly the "Get" response is much easier, we merely have to return a string in this case which is obviously matched for our property. Again, this is in the same file, bus/driver.c in the function: bus_driver_handle_get().

set/get property using dbus-send

I have made below sample xml and need some help in forming dbus-send command to set/get propoerty "Status". I know how to call methods, but not able to read/write property using dbus-send.
xml:
<node>
<interface name="com.pgaur.GDBUS">
<method name="HelloWorld">
<arg name="greeting" direction="in" type="s"/>
<arg name="response" direction="out" type="s"/>
</method>
<signal name="Notification">
<arg name="roll_number" type="i"/>
<arg name="name" type="s"/>
</signal>
<property name="Status" type="u" access="readwrite"/>
</interface>
</node>
You can Get/Set DBus properties for your DBus interface using below dbus-send commands. Replace $BUS_NAME and $OBJECT_PATH with respective names.
Get Property:
dbus-send --system --dest=$BUS_NAME --print-reply $OBJECT_PATH \
org.freedesktop.DBus.Properties.Get string:com.pgaur.GDBUS string:Status
Set Property:
dbus-send --system --dest=$BUS_NAME --print-reply $OBJECT_PATH \
org.freedesktop.DBus.Properties.Set string:com.pgaur.GDBUS string:Status variant:uint32:10
You can read DBus specification to know more about DBus Properties.
dbus-send --system --print-reply --type=method_call --dest=org.ofono /gemalto_0 org.ofono.Modem.SetProperty string:"Powered" variant:boolean:false

Camel exposing CXF Web service

I'm trying to expose a JAX-WS Webservice (an annotated Java class) using Camel. When using a single parameter the Web service replies correctly. On the other hand when using as parameter an Object or multiple parameter it does not work.
Here is the blueprint I have deployed on JBoss Fuse:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf" xmlns:cxf="http://cxf.apache.org/blueprint/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<camelcxf:cxfEndpoint id="demo-target-cxf" address="http://localhost:9000/SourceExample/hello" serviceClass="com.sample.SourceExampleWSImpl" endpointName="SourceExamplePort" serviceName="SourceExampleService" />
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="fuse-demo-route-exmple-cxf">
<route id="demo-target-cxf">
<from uri="cxf:bean:demo-target-cxf" />
<transform>
<simple>${in.body}</simple>
</transform>
<log message="Message input: ${in.body}" />
<removeHeaders pattern="CamelHttp*" />
</route>
</camelContext>
</blueprint>
Here is the Web Service implementation class:
#WebService
public class SourceExampleWSImpl {
#WebMethod
public int getTotal(int x, int y) {
return x+y;
}
}
The bundle ic correctly deployed on JBoss Fuse. When invoking the Web service, only the first parameter is evaluated. So for example, invoking with arguments 1 and 4:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sam="http://sample.com/">
<soapenv:Header/>
<soapenv:Body>
<sam:getTotal>
<arg0>1</arg0>
<arg1>4</arg1>
</sam:getTotal>
</soapenv:Body>
</soapenv:Envelope>
returns:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getTotalResponse xmlns:ns2="http://sample.com/">
<return>1</return>
</ns2:getTotalResponse>
</soap:Body>
</soap:Envelope>
Any idea how to fix it ?
Thanks
Do you mean the expected output should be
1 + 4 = 5 because the following code should be called?
public int getTotal(int x, int y) {
return x+y;
}
If so that does not happen, when you use camel-cxf as a bean then the bean only defines the contract, the code in the implementation is not in use.
If you just want a standard SOAP-WS and write java code that builds and process the SOAP requests/response then just use plain CXF.

Configuring WSS4J with CXF

I was doing pretty well with setting up a contract first set of web services using CXF until I started adding in the WSS4J piece.
I'm trying to debug sending a password and login in the soap header. I am getting null when I call getPassword() in the WSPasswordCallback class. I can see from the soap envelope that a password was sent.
This post, http://old.nabble.com/PasswordDigest-and-PasswordText-difference-td24475866.html, from 2009, made me wonder if I am missing (need to create) a UsernameTokenHandler.
And if that is true, can someone point me to how I would configure it in the spring/cxf bean xml file?
Any advice or suggestions would be appreciated.
Here's the Java file in question:
package com.netcentric.security.handlers;
import java.io.IOException;
import javax.annotation.Resource;
import javax.com.urity.auth.callback.Callback;
import javax.com.urity.auth.callback.CallbackHandler;
import javax.com.urity.auth.callback.UnsupportedCallbackException;
import org.apache.ws.com.urity.WSPasswordCallback;
public class ServicePWCallback implements CallbackHandler
{
#Override
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
try {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
sString login = pc.getIdentifier();
String password = pc.getPassword();
// password is null, not the expected myPASSWORD**1234
int n = pc.getUsage();
// this is 2 == WSPasswordCallback.USERNAME_TOKEN
//...
The CXF/Spring configuration file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
default-dependency-check="none" default-lazy-init="false">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="serverPasswordCallback" class="com.netcentric.security.handlers.ServicePWCallback"/>
<bean id="wss4jInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken"/>
<entry key="passwordType" value="PasswordText"/>
<entry key="passwordCallbackRef">
<ref bean="serverPasswordCallback"/>
</entry>
</map>
</constructor-arg>
</bean>
<jaxws:endpoint id="FederationImpl"
implementor="com.netcentric.services.federation.FederationImpl"
endpointName="e:federation"
serviceName="e:federation"
address="federation"
xmlns:e="urn:federation.services.netcentric.sec">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
<ref bean="wss4jInInterceptor"/>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans
The soap message:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:comurity xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wscomurity-comext-1.0.xsd" soapenv:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wscomurity-utility-1.0.xsd" wsu:Id="Timestamp-16757598">
<wsu:Created>2011-09-22T18:21:23.345Z</wsu:Created>
<wsu:Expires>2011-09-22T18:26:23.345Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wscomurity-utility-1.0.xsd" wsu:Id="UsernameToken-16649441">
<wsse:Username>pam</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">myPASSWORD**1234</wsse:Password>
</wsse:UsernameToken>
</wsse:comurity>
</soapenv:Header>
<soapenv:Body>
<getVersion xmlns="urn:federation.services.netcentric.com">
<getVersionRequest/>
</getVersion>
</soapenv:Body>
</soapenv:Envelope>
If using CXF 2.4.x, I would recommend reading:
http://coheigea.blogspot.com/2011/02/usernametoken-processing-changes-in.html
and seeing if that helps provide some extra information. Colm's blog is a treasure trove of useful info about recent WSS4J releases.
Thanks for all your help. I have made progress on this. I am using CXF 2.4.2 and WSS4J 1.6.2. The framework now takes care of checking the password for you. So the correct inside section is
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
sString login = pc.getIdentifier();
String password = getPassword(login);
pc.getPassword(login);
//...
}
Instead of retrieving the password from the soap header to compare against the expected value, you lookup the expected value and pass it to the framework to do the comparison.
I add this :
// set the password on the callback.
This will be compared to the
// password which was sent from the client.
pc.setPassword("password");
==> the password between "" will be compared with password sended by client.
Client side: write login = bob ; Password = bobPassword (will be digested)
Server side: Catch user = bob and the function user.setPassword(bobPassword) verify if the password received is correct or no.

Ant load property file and pass value as arg when exec java file

How can I load a value from a property file and pass it as arg when I want to execute a java file?
The content the file of aa.properties:
home_path=C:/myhome/apps
The ant:
<target name="tst">
<property file="aa.properties"/>
<property name="homepath" value="${home_path}/"/>
<java classpathref="clspath" classname="com.mytest.myapp" fork="true">
<arg value="${homepath}"/>
</java>
</target>
you pass it like any other argument to the java task via nested arg values or arg line
Note that vmargs like f.e. -Dwhatever=foobar are passed as jvmarg to the java task
f.e. your propertyfile aa.properties looks like :
vmarg.foo=-Dsomevalue=whatever
arg.key=value
arg.foo=bar
...
ant then
<target name="tst">
<property file="aa.properties"/>
<property name="homepath" value="${home_path}/"/>
<java classpathref="clspath" classname="com.mytest.myapp" fork="true">
<jvmarg value="${vmarg.foo}"/>
<arg value="${homepath}"/>
<arg value="${arg.key}"/>
<arg value="${arg.foo}"/>
...
</java>
</target>

Resources