cancel
Showing results for 
Search instead for 
Did you mean: 

PHP using soap to call EJB

johannes_gilbert
Participant
0 Kudos

Hello everybody,

I've a problem to call a EJB form a PHP script.

There is a Apache with PHP 5.2.0 and a SAP NetWeaver Application Server 7.10 / AS Java 7.10 running on the system.

I wanted to use soap to call a method in an EJB. It's only a test EJB:

[code]

package beans;

import javax.ejb.Stateless;

import javax.jws.WebService;

import javax.jws.WebMethod;

@WebService(name="HelloWorldEARBean",serviceName="HelloWorldEARBeanService",targetNamespace="http://beans/",portName="HelloWorldEARBeanPort") @Stateless public class HelloWorldEARBean {

@WebMethod public String sayHello(String testStr){

return "Hello Mr. "+testStr;

}

@WebMethod public String getReturn(String inputStr){

return "the return value is"+inputStr;

}

}

[/code]

I tried it with the PEAR SOAP in the following script:

[code]

<?php

require_once 'SOAP/Client.php';

$wsdl_url = 'http://localhost:50000/HelloWorldEARBeanService/HelloWorldEARBean?wsdl';

$WSDL = new SOAP_WSDL($wsdl_url);

$client = $WSDL->getProxy();

$client->__trace(1);

$options=array('namespace' => 'http://beans/',

'style' => 'rpc',

'soapaction' => 'sayHello');

$NAME = "Bob";

$parameters=array(

'parameters', $NAME

);

$result = $client->getReturn($parameters);

echo "<pre>";

print_r($params);

echo "</pre>";

echo "<h2>return</h2>";

echo "<pre>";

print_r($result);

echo "</pre>";

echo '<h2>Request</h2>';

echo '<pre>' . htmlspecialchars($client->__getlastrequest(), ENT_QUOTES) . '</pre>';

echo '<h2>Response</h2>';

echo '<pre>' . htmlspecialchars($client->__getlastresponse(), ENT_QUOTES). '</pre>';

?>

[/code]

The AS distributes the following WSDL:

[code]

- <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://beans/" xmlns:tns="http://beans/">

- <wsdl:types>

- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://beans/">

<xs:element name="getReturn" type="tns:getReturn" />

<xs:element name="getReturnResponse" type="tns:getReturnResponse" />

<xs:element name="sayHello" type="tns:sayHello" />

<xs:element name="sayHelloResponse" type="tns:sayHelloResponse" />

- <xs:complexType name="sayHello">

- <xs:sequence>

<xs:element name="arg0" type="xs:string" minOccurs="0" />

</xs:sequence>

</xs:complexType>

- <xs:complexType name="sayHelloResponse">

- <xs:sequence>

<xs:element name="return" type="xs:string" minOccurs="0" />

</xs:sequence>

</xs:complexType>

- <xs:complexType name="getReturn">

- <xs:sequence>

<xs:element name="arg0" type="xs:string" minOccurs="0" />

</xs:sequence>

</xs:complexType>

- <xs:complexType name="getReturnResponse">

- <xs:sequence>

<xs:element name="return" type="xs:string" minOccurs="0" />

</xs:sequence>

</xs:complexType>

</xs:schema>

</wsdl:types>

- <wsdl:message name="sayHelloIn">

<wsdl:part name="parameters" element="tns:sayHello" />

</wsdl:message>

- <wsdl:message name="sayHelloOut">

<wsdl:part name="sayHelloResponse" element="tns:sayHelloResponse" />

</wsdl:message>

- <wsdl:message name="getReturnIn">

<wsdl:part name="parameters" element="tns:getReturn" />

</wsdl:message>

- <wsdl:message name="getReturnOut">

<wsdl:part name="getReturnResponse" element="tns:getReturnResponse" />

</wsdl:message>

- <wsdl:portType name="HelloWorldEARBean">

- <wsdl:operation name="sayHello" parameterOrder="parameters">

<wsdl:input message="tns:sayHelloIn" />

<wsdl:output message="tns:sayHelloOut" />

</wsdl:operation>

- <wsdl:operation name="getReturn" parameterOrder="parameters">

<wsdl:input message="tns:getReturnIn" />

<wsdl:output message="tns:getReturnOut" />

</wsdl:operation>

</wsdl:portType>

- <wsdl:binding name="HelloWorldEARBeanBinding" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" type="tns:HelloWorldEARBean">

<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />

- <wsdl:operation name="sayHello">

<soap:operation soapAction="" />

- <wsdl:input>

<soap:body parts="parameters" use="literal" />

</wsdl:input>

- <wsdl:output>

<soap:body use="literal" />

</wsdl:output>

</wsdl:operation>

- <wsdl:operation name="getReturn">

<soap:operation soapAction="" />

- <wsdl:input>

<soap:body parts="parameters" use="literal" />

</wsdl:input>

- <wsdl:output>

<soap:body use="literal" />

</wsdl:output>

</wsdl:operation>

</wsdl:binding>

- <wsdl:service name="HelloWorldEARBeanService">

- <wsdl:port name="HelloWorldEARBeanPort" binding="tns:HelloWorldEARBeanBinding">

<soap:address xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" location="http://localhost:50000/HelloWorldEARBeanService/HelloWorldEARBean" />

</wsdl:port>

</wsdl:service>

</wsdl:definitions>

[/code]

By the following output it's obvious that the AS or the EJB (webservice) doesn't receive the parameter send by the PHP script. Look at the output:

return value:

the return value is null

[code]

Request:

POST /HelloWorldEARBeanService/HelloWorldEARBean HTTP/1.0

User-Agent: PEAR-SOAP 0.8.0RC4-devel

Host: localhost

Content-Type: text/xml; charset=UTF-8

Content-Length: 438

SOAPAction: ""

<?xml version="1.0" encoding="UTF-8"?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"

>

<SOAP-ENV:Body>

<getReturn xmlns="http://beans/">

<item>parameters</item>

<item>Bob</item></getReturn>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

Response:

HTTP/1.1 200 OK

server: SAP NetWeaver Application Server 7.10 / AS Java 7.10

content-type: text/xml; charset=utf-8

date: Wed, 14 Feb 2007 15:51:53 GMT

connection: close

<?xml version="1.0" encoding="utf-8"?>

<SOAP-ENV:Envelope xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<SOAP-ENV:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">

<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

<wsu:Created>2007-02-14T15:51:53Z</wsu:Created>

<wsu:Expires>2007-02-14T15:52:23Z</wsu:Expires></wsu:Timestamp></wsse:Security></SOAP-ENV:Header>

<SOAP-ENV:Body><ns2:getReturnResponse xmlns:ns2='http://beans/'>

<return>the return value is null</return></ns2:getReturnResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>

[/code]

I used different soap interfaces for PHP like nusoap and the integrated soap interface of PHP 5.

Further I experimented with different parameters inside the function call

that results in small differencies at the xml-request.

Thanks.

Accepted Solutions (0)

Answers (1)

Answers (1)

Former Member
0 Kudos

hi,

most of the setup works fine as far as i can see.

pretty obviously you're transmitting not only parameter 'Bob' but two parameters 'parameter' and 'Bob' as seen in

<getReturn xmlns="http://beans/">
<item>parameters</item>
<item>Bob</item></getReturn>

You might have wanted tow write 'parameters' => 'Bob'

How you handle a table as input when the Java method signature requires a String...I don't know.

anton

johannes_gilbert
Participant
0 Kudos

thanks,

but i have tried it with this piece of code too:

[code]

$parameters=array(

'parameters' => 'Bob'

);

$result = $client->getReturn($parameters);

[/code]

It caused to same result.

johannes_gilbert
Participant
0 Kudos

hi,

now I have also implemented a soap client in java to exclude the possibility of a PHP specific problem. It caused same result that the return String is

Hello Mr. null

. So the problem might be located in the EJB part. I have tried to use the

@WebParam(name="testStr")

option without success.

So the problem seems to be at the server side soap part. It can't handle the sent parameter(s). Does anybody has any further ideas?

Former Member
0 Kudos

hi,

I'd try to save the WSDL locally and replace

<xs:complexType name="getReturn">
  <xs:sequence>
  <xs:element name="arg0" type="xs:string" minOccurs="0" /> 
  </xs:sequence>
  </xs:complexType>

by

<xs:complexType name="getReturn">
  <xs:element name="arg0" type="xs:string" minOccurs="0" /> 
  </xs:complexType>

and call the operation with


...array('arg0' => 'Bob')...

my 2 cents,

anton

johannes_gilbert
Participant
0 Kudos

hi,

my request now looks like this:


<SOAP-ENV:Body>

<sayHello xmlns="http://beans/">
<testStr>Bob</testStr></sayHello>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

but I think it should look like this:


<SOAP-ENV:Body>

<sayHello xmlns="http://beans/">
<testStr xsi:type="xsd:string">Bob</testStr></sayHello>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

So how can I get this right?

johannes_gilbert
Participant
0 Kudos

Hi

I've solved the problem now. I just have to add

@SOAPBinding(style=SOAPBinding.Style.RPC)

in the EJB, that's all.

Here is the complete code, ... maybe some other guys have this problem too, so I will post the working code:

At first the EJB:


package beans;
import javax.ejb.Stateless;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;

import beans.HelloWorldEARBean;

@WebService(name="HelloWorldEARBean",serviceName="HelloWorldEARBeanService",targetNamespace="http://beans/",portName="HelloWorldEARBeanPort") 
@SOAPBinding(style=SOAPBinding.Style.RPC)
@Stateless public class HelloWorldEARBean {
	@WebMethod public String sayHello(@WebParam(name="testStr") String testStr){
		  return "Hello Mr. "+testStr;
  }

}

2. the local XML:

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://beans/" xmlns:tns="http://beans/">
  <wsdl:types>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://beans/">
      <xs:element name="sayHello" type="tns:sayHello"/>
      <xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/>
      <xs:complexType name="sayHello">
          <xs:element name="testStr" type="xs:string" minOccurs="0"/>
      </xs:complexType>
      <xs:complexType name="sayHelloResponse">
          <xs:element name="return" type="xs:string" minOccurs="0"/>
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="sayHelloIn">
    <wsdl:part name="parameters" element="tns:sayHello"/>
  </wsdl:message>
  <wsdl:message name="sayHelloOut">
    <wsdl:part name="sayHelloResponse" element="tns:sayHelloResponse"/>
  </wsdl:message>
  <wsdl:portType name="HelloWorldEARBean">
    <wsdl:operation name="sayHello" parameterOrder="parameters">
      <wsdl:input message="tns:sayHelloIn"/>
      <wsdl:output message="tns:sayHelloOut"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloWorldEARBeanBinding" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" type="tns:HelloWorldEARBean">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="sayHello">
      <soap:operation soapAction=""/>
      <wsdl:input>
        <soap:body parts="parameters" use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloWorldEARBeanService">
    <wsdl:port name="HelloWorldEARBeanPort" binding="tns:HelloWorldEARBeanBinding">
      <soap:address xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" location="http://localhost:50000/HelloWorldEARBeanService/HelloWorldEARBean"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

3. the PHP script:

see next post

Thank you very much for your help.

johannes_gilbert
Participant
0 Kudos

And the PHP script:

<?php

require_once 'SOAP/Client.php';

$wsdl_url = 'http://localhost/bean.xml';

$WSDL = new SOAP_WSDL($wsdl_url);

$client = $WSDL->getProxy();

$client->_namespace = 'urn:http://beans/';

$client->__trace(1);

$parameters=array(

'testStr' => 'Bob'

);

$soapoptions =

array(

'trace' => 1,

'soapaction' => 'xmlns:http://beans/',

'Content-Type' => 'text/xml;charset=utf-8'

);

$result = $client->sayHello($parameters,$soapoptions);

echo "<pre>";

print_r($parameters);

echo "</pre>";

echo "<h2>return</h2>";

echo "<pre>";

print_r($result);

echo "</pre>";

echo '<h2>Request</h2>';

echo '<pre>' . htmlspecialchars($client->__getlastrequest(), ENT_QUOTES) . '</pre>';

echo '<h2>Response</h2>';

echo '<pre>' . htmlspecialchars($client->__getlastresponse(), ENT_QUOTES). '</pre>';

?>

johannes_gilbert
Participant
0 Kudos

Hi,

but there is still one problem remaining:

I have to use the local XML, otherwise it's an error.

johannes_gilbert
Participant
0 Kudos

Hi,

it's crazy! The local XML that I mentioned is the provided XML of the WebService <b>before</b> I add the annotation

@SOAPBinding(style=SOAPBinding.Style.RPC)

to the EJB in <i>Document</i> mode.

When I used the <i>RPC</i> mode with the "local" XML file (which was provided in <i>Document</i> mode), it works.

Now I analysed both XML files and customized the "local" XML to nearly the WebService's XML. There is only one difference remaining (which makes the script working or not):

the "local" XML (working):

<wsdl:part name="testStr" element="tns:sayHello"/>

the remote XML (not working):

<wsdl:part name="testStr" type="p0:string"/>

Is there any possibility to change this behavior?

Because I don't always want to use the "local" XML file. (I don't think this was the idea when providing WebServices.)

Many thanks.

Former Member
0 Kudos

hi,

AFAIK you don't need that namespace/datatype information on an XML instance. This information is mainly useful in the schema definition, where you describe the instance data to be sent based on that definition.

The information(xml attribute) is pretty surely being discarded at runtime by the receiving service runtime or maybe - more severely - raising an error, because the WSDL doesn't define an attribute to be in that element .

anton

Former Member
0 Kudos

<i>...but there is still one problem remaining:

I have to use the local XML, otherwise it's an error....</i>

IMHO this is simply an error in your Service implementation. I.e. it's creating a WSDL, which allows/forces service calls to be sent which it can't handle.

regards,

anton

johannes_gilbert
Participant
0 Kudos

Sorry the order of the post got a bit mixed up. Please see my reply at Feb 15,2007 2:07PM.

Thanks

Former Member
0 Kudos

is there a namespace p0 defined?

johannes_gilbert
Participant
0 Kudos

I have no namespace "p0" specified.


package beans;
import javax.ejb.Stateless;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;

import beans.HelloWorldEARBean;

@WebService(name="HelloWorldEARBean",serviceName="HelloWorldEARBeanService",targetNamespace="http://beans/",portName="HelloWorldEARBeanPort") 
@SOAPBinding(style=SOAPBinding.Style.RPC )
@Stateless public class HelloWorldEARBean {
	@WebMethod public String sayHello(@WebParam(name="testStr") String testStr){
		
		return "Hello Mr. "+testStr;
  }

}

Former Member
0 Kudos

hi johannes,

I believe that your Java wizard simply creates a "broken" WSDL. it references a variable of type string defined in the namespace p0 (that'swhat p0:string means) but there is no namespace p0 defined.

I have not worked with the respective classes of Netweaver, so I can't tell if this is a bug or a problem of your call. You might ask that part again in one of the Java forums. Probably people over there know that.

anton

johannes_gilbert
Participant
0 Kudos

thanks for your help Anton,

that's a good idea. Like you said it seems that the Java wizard creates a "borken" WSDL. So I will post it in a Java Forum.

Johannes