[Question] How to create a Java client for a Zend_Soap server using autodiscover functionality

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[Question] How to create a Java client for a Zend_Soap server using autodiscover functionality

mouneyrac
Hi,
I try to create a Java client for testing at least one web service function from the WSDL generated by Zend autodiscover. First I'm going to explain how to reach the point where you can generate a Java client then I'll explain why I'm blocked and I cannot call the web service function.

***********************************************************
First write the server code is:
***********************************************************
$autodiscover = new Zend_Soap_AutoDiscover();
//the following is important, because Java didn't want to generate if it was 'use' => 'encoded'
$autodiscover->setOperationBodyStyle(
                    array('use' => 'literal',
                          'namespace' => $CFG->wwwroot)
 );
 $autodiscover->setBindingStyle(
                    array('style' => 'rpc')
);
$autodiscover->setClass('ws_authentication');
$autodiscover->handle();
************************************************************
The loaded class
************************************************************
class ws_authentication {
    /**
     * Here the function I'm going to call, note that the param is an associative Array containing string
     * @param array|struct $params
     * @return integer
     */
    function get_token($params) {
        if ($params['username'] == 'wsuser' && $params['password'] == 'wspassword') {
            return '456';
        } else {
            throw new moodle_exception('wrongusernamepassword');
        }
    }
}
*************************************************************

I can generate some class from Netbeans:
1. Create an empty basic Java project
2. On the project title, right click, select create web service client
3. Choose JAX-RPC style and enter the WSDL address
4. Click on finish, some classes should be generated
5. Insert Code in the Main.java ... call web service operation

At this moment I have the following line:
_ws_authenticationPort.get_token();

I have to pass some params inside the function that are a new java generated class call Array(), that should contains some sort of SOAPElement. I have no idea how to create these params. In the PHP server side you can see that is a associative array.
Were the classes well generated? How to use them ?

Thanks,
Jerome


*************************************************************************************************************************
Following the WSDL (generated by autodiscover) retrieved by the Java client generator in Netbeans
*************************************************************************************************************************
<?xml version="1.0"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://jerome.moodle.com/Moodle_HEAD/moodle/webservice/soap/server.php" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="ws_authentication" targetNamespace="http://jerome.moodle.com/Moodle_HEAD/moodle/webservice/soap/server.php">
    <portType name="ws_authenticationPort">
        <operation name="get_token">
            <input message="tns:get_tokenRequest"/>
            <output message="tns:get_tokenResponse"/>
        </operation>
    </portType>
    <binding name="ws_authenticationBinding" type="tns:ws_authenticationPort">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="get_token">
            <soap:operation soapAction="http://jerome.moodle.com/Moodle_HEAD/moodle/webservice/soap/server.php#get_token"/>
            <input>
                <soap:body use="literal" namespace="http://jerome.moodle.com/Moodle_HEAD/moodle"/>
            </input>
            <output>
                <soap:body use="literal" namespace="http://jerome.moodle.com/Moodle_HEAD/moodle"/>
            </output>
        </operation>
    </binding>
    <service name="ws_authenticationService">
        <port name="ws_authenticationPort" binding="tns:ws_authenticationBinding">
            <soap:address location="http://jerome.moodle.com/Moodle_HEAD/moodle/webservice/soap/server.php"/>
        </port>
    </service>
    <message name="get_tokenRequest">
        <part name="params" type="soap-enc:Array"/>
    </message>
    <message name="get_tokenResponse">
        <part name="return" type="xsd:int"/>
    </message>
</definitions>
Reply | Threaded
Open this post in threaded view
|

Re: [Question] How to create a Java client for a Zend_Soap server using autodiscover functionality

Bugzilla from fabien@crespel.net
Hello,

mouneyrac wrote :
> I have to pass some params inside the function that are a new java generated
> class call Array(), that should contains some sort of SOAPElement. I have no
> idea how to create these params. In the PHP server side you can see that is
> a associative array.
> Were the classes well generated? How to use them ?

As far as I know the soap-enc:Array type is not an associative array, but a
classical "flat" one.. meanwhile, the type of the contained elements isn't
described here, so the caller has no clue what kind of content the service
expects. I wouldn't really recommend using "@param array" at all.

Instead I would suggest using 2 string parameters like this:

/**
 * Some description...
 * @param string $username
 * @param string $password
 * @return integer
function get_token($username, $password) {
   if ($username == 'wsuser' && $password == 'wspassword') {
       return '456';
   } else {
       throw new moodle_exception('wrongusernamepassword');
   }
}

If you still want only 1 parameter, you could use a class, but it seems easier to
use the solution above.

- Fabien.

Reply | Threaded
Open this post in threaded view
|

Re: [Question] How to create a Java client for a Zend_Soap server using autodiscover functionality

mouneyrac
Thanks Fabien for your answer. I'd like to create some web service functions with array as parameter. I'll just give a documentation about the array content. I'll have to find out how to write a Java client when Zend_soap recieve and return array or object.

Jerome

PS: I went on your website I love the dog picture www.crespel.net


Bugzilla from fabien@crespel.net wrote
Hello,

mouneyrac wrote :
> I have to pass some params inside the function that are a new java generated
> class call Array(), that should contains some sort of SOAPElement. I have no
> idea how to create these params. In the PHP server side you can see that is
> a associative array.
> Were the classes well generated? How to use them ?

As far as I know the soap-enc:Array type is not an associative array, but a
classical "flat" one.. meanwhile, the type of the contained elements isn't
described here, so the caller has no clue what kind of content the service
expects. I wouldn't really recommend using "@param array" at all.

Instead I would suggest using 2 string parameters like this:

/**
 * Some description...
 * @param string $username
 * @param string $password
 * @return integer
function get_token($username, $password) {
   if ($username == 'wsuser' && $password == 'wspassword') {
       return '456';
   } else {
       throw new moodle_exception('wrongusernamepassword');
   }
}

If you still want only 1 parameter, you could use a class, but it seems easier to
use the solution above.

- Fabien.
Reply | Threaded
Open this post in threaded view
|

Re: [Question] How to create a Java client for a Zend_Soap server using autodiscover functionality

mouneyrac
In reply to this post by Bugzilla from fabien@crespel.net
Hi Fabien,
my function example was more about to use complex parameters.
If my Zend Soap Client can send array and object, why my java client can not?
To speak more about use case, I've got some functions called get_users, create_users, ... so you can see that I need to pass array containing objects. I think they are quite classic common web service functions. I guess there is a good way/pratice to use Zend_soap_server+autodiscover and be able to write a Java client?



Bugzilla from fabien@crespel.net wrote
Hello,

mouneyrac wrote :
> I have to pass some params inside the function that are a new java generated
> class call Array(), that should contains some sort of SOAPElement. I have no
> idea how to create these params. In the PHP server side you can see that is
> a associative array.
> Were the classes well generated? How to use them ?

As far as I know the soap-enc:Array type is not an associative array, but a
classical "flat" one.. meanwhile, the type of the contained elements isn't
described here, so the caller has no clue what kind of content the service
expects. I wouldn't really recommend using "@param array" at all.

Instead I would suggest using 2 string parameters like this:

/**
 * Some description...
 * @param string $username
 * @param string $password
 * @return integer
function get_token($username, $password) {
   if ($username == 'wsuser' && $password == 'wspassword') {
       return '456';
   } else {
       throw new moodle_exception('wrongusernamepassword');
   }
}

If you still want only 1 parameter, you could use a class, but it seems easier to
use the solution above.

- Fabien.
Reply | Threaded
Open this post in threaded view
|

Re: [Question] How to create a Java client for a Zend_Soap server using autodiscover functionality

Bugzilla from fabien@crespel.net
mouneyrac wrote:
> Hi Fabien,

Hi, and sorry for the late response, I'm in the middle of university exams :(

> my function example was more about to use complex parameters.
> If my Zend Soap Client can send array and object, why my java client can
> not?

I don't know Java clients very well, but Java is probably stricter than PHP...

The WSDL generated when using "@param array" uses soap-enc:Array, which is a bit
vague as it doesn't specify the type of the contained elements. Moreover, these
arrays are "flat" as far as I know.

In your case, you are expecting an *associative* array on the PHP side (with a
string as the key), which is a different matter.

If I remember correctly, PHP uses some kind of Apache "Map" type, defined in the
http://xml.apache.org/xml-soap namespace, for associative arrays. This seems to
be a fake URL though, and it won't give you an XML Schema for the Map type.. So I
don't think this solution is very interoperable at all. But again, I don't really
know Java clients. Maybe the solution is somewhere in Apache Axis? Maybe it could
magically convert a Java Hashtable into a "Map" that PHP understands ?

> To speak more about use case, I've got some functions called get_users,
> create_users, ... so you can see that I need to pass array containing
> objects. I think they are quite classic common web service functions. I
> guess there is a good way/pratice to use Zend_soap_server+autodiscover and
> be able to write a Java client?

Personally, I would use a PHP class to wrap these objects instead of an
associative array. For example:

class AuthData {
    /** @var string */
    $username;
    /** @var string */
    $password;
}

Then your web service class would look like that:

class ws_authentication {
    /**
     * Authenticate an user.
     * @param AuthData $params
     * @return integer
     */
    public function get_token($params) {
        if ($params->username == 'wsuser' && $params->password == 'wspassword') {
            return '456';
        } else {
            throw new moodle_exception('wrongusernamepassword');
        }
    }
}

With this solution you should be able to get a Java client working, the only
downside is that you would have to create many classes if you have many
functions. But at least they would properly define what the client must provide.

Hope this helps.
- Fabien.