【问题标题】:Invoke soap webservice returning list of objects from java client with axis使用轴调用soap webservice从java客户端返回对象列表
【发布时间】:2012-03-12 14:08:03
【问题描述】:

我对网络服务很生气。

我有一个非常简单的soap webservice:

@Remote
public interface StudentService
{
public String sayHello();
public List<Student> getStudents();
}

还有

@Stateless
@WebService
public class StudentServiceImpl implements StudentService
{

@Override
public String sayHello()
{
    return "Hello World";
}

public List<Student> getStudents()
{
    List<Student> students = new ArrayList<Student>();

    Student st1 = new Student();
    st1.setMatricule(1234);
    st1.setName("student1");
    students.add(st1);

    Student st2 = new Student();
    st2.setMatricule(5678);
    st2.setName("student2");
    students.add(st2);

    return students;
    }
}

public class Student implements Serializable
{
private static final long serialVersionUID = 8286393242028201686L;

private int matricule; 
private String name;

public int getMatricule()
{
    return matricule;
}
public void setMatricule(int matricule)
{
    this.matricule = matricule;
}

public String getName()
{
    return name;
}
public void setName(String name)
{
    this.name = name;
}
}

我在 glassfish 3.1 下部署服务。

使用 glassfish 控制台,它正在工作。

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getStudentsResponse xmlns:ns2="http://services.tuto.java.com/">
            <return>
                <matricule>1234</matricule>
                <name>student1</name>
            </return>
            <return>
                <matricule>5678</matricule>
                <name>student2</name>
            </return>
        </ns2:getStudentsResponse>
    </S:Body>
</S:Envelope>

使用 php 它也可以工作(对于这两种方法)。

现在有了一个 java 客户端:

import javax.xml.namespace.QName;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;

public class Client
{
public static void main(String[] args) throws Exception
{
    String endPoint = "http://localhost:8080/StudentServiceImplService/StudentServiceImpl";

    Service service = new Service();
    Call call = (Call) service.createCall();
    call.setTargetEndpointAddress(new java.net.URL(endPoint));
    call.setOperationName(new QName("http://services.tuto.java.com/","sayHello"));

    System.out.println(call.invoke(new Object[0]));

    Service service2 = new Service();
    Call call2 = (Call) service2.createCall();
    call2.setTargetEndpointAddress(new java.net.URL(endPoint));
    call2.setOperationName(new QName("http://services.tuto.java.com/","getStudents"));

    System.out.println(call2.invoke(new Object[0]));
    }
}

第一个电话有效,但第二个电话无效。

Hello World
12-mars-2012 14:53:23 org.apache.axis.client.Call invoke
GRAVE: Exception:
org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.
at org.apache.axis.encoding.ser.SimpleDeserializer.onStartChild(SimpleDeserializer.java:145)
at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035)
at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165)
at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141)
at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:345)
at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384)
at org.apache.axis.client.Call.invoke(Call.java:2467)
at org.apache.axis.client.Call.invoke(Call.java:2366)
at org.apache.axis.client.Call.invoke(Call.java:1812)
at Client.main(Client.java:24)

我能做什么?

在互联网上搜索了很多小时并尝试了不同的解决方案后仍然没有任何效果......

有简单的解决办法吗?

谢谢。

编辑:

也试过了:

public class SoapClient
{
public static void main(String[] args) throws Exception
{
    SOAPMappingRegistry smr = new SOAPMappingRegistry();
    BeanSerializer beanSer = new BeanSerializer();
    smr.mapTypes(Constants.NS_URI_SOAP_ENC,new QName("http://services.tuto.java.com/", "StudentServiceImplService"),Student.class, beanSer, beanSer);       

    Call call = new Call();
    call.setSOAPMappingRegistry(smr);
    call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);

    call.setTargetObjectURI("http://services.tuto.java.com/");
    call.setMethodName("getStudents");

    Response resp;
    try
    {
        resp = call.invoke(new URL("http://8h9l45j:8080/StudentServiceImplService/StudentServiceImpl"), "");
    }
    catch (SOAPException e)
    {
        System.err.println("Caught SOAPException (" +
          e.getFaultCode() + "): " + e.getMessage());
        return;
    }

    if (!resp.generatedFault())
    {
        Parameter ret = resp.getReturnValue();
        Object value = ret.getValue();
        if ( value != null )
        {
            String[] tlist = (String[])value;
            System.out.println();
            for ( int i = 0; i < tlist.length; i++ )
                System.out.println(tlist[i]);
        }
    }
    else
    {
        Fault fault = resp.getFault();
        System.err.println("Generated fault: ");
        System.out.println ("  Fault Code   = "
                            + fault.getFaultCode());
        System.out.println ("  Fault String = "
                            + fault.getFaultString());
    }
}

有了这个结果:

Caught SOAPException (SOAP-ENV:Client): No Deserializer found to deserialize a ':return' using encoding style 'http://schemas.xmlsoap.org/soap/encoding/'.

【问题讨论】:

  • 学生是否实现了可序列化?
  • 尝试记录消息。根据错误消息消息错误:遇到子元素,这是不期望的
  • 好的,现在我理解了 ':return' 的含义——查看消息的编辑问题——我尝试使用带有矩阵和名称属性、getter 和 setter 的 Return 类。并更改此行: smr.mapTypes(Constants.NS_URI_SOAP_ENC,new QName("services.tuto.java.com", "return"),Return.class, beanSer, beanSer);但仍然无法正常工作,同样的异常。
  • 如何将我的响应肥皂消息中的 更改为

标签: java web-services glassfish-3 axis


【解决方案1】:

使用soap客户端响应的第一个元素。

问题来自于 maptypes 命名空间:没有命名空间

所以现在,我有

    smr.mapTypes(Constants.NS_URI_SOAP_ENC,new QName("","student"),Student.class, null, new BeanSerializer());  
    smr.mapTypes(Constants.NS_URI_SOAP_ENC,new QName("","matricule"),Integer.class, null, new IntDeserializer());   
    smr.mapTypes(Constants.NS_URI_SOAP_ENC,new QName("","name"),Integer.class, null, new StringDeserializer()); 

还有添加

@XmlRootElement(name = "Student",namespace="http://services.tuto.java.com/")

到Student类去拥有

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getStudentsResponse xmlns:ns2="http://services.tuto.java.com/">
            <student>
                <matricule>1236</matricule>
                <name>student1</name>
            </student>
            <student>
                <matricule>5678</matricule>
                <name>student2</name>
            </student>
        </ns2:getStudentsResponse>
    </S:Body>
</S:Envelope>

轴客户端:

 public class AxisClient
{
    public static void main(String[] args) throws Exception
    {
    String endPoint = "http://localhost:8080/StudentServiceImplService/StudentServiceImpl";
    Service service2 = new Service();
    Call call2 = (Call) service2.createCall();
    call2.setTargetEndpointAddress(new java.net.URL(endPoint));
    call2.setOperationName(new QName("http://services.tuto.java.com/","getStudents"));
    call2.setReturnType(new QName("","student"), Student.class);
    call2.setReturnType(new QName("", "student"));
    call2.registerTypeMapping(Student.class, new QName("", "student"), null,new BeanDeserializerFactory(Student.class, new QName("", "student")));
    List<Student> students = (List<Student>) call2.invoke(new Object[0]);
    for (Student student : students)
    {
        System.out.println(student);
    }
    }
 }

所有学生:

Student [matricule=1236, name=student1]
Student [matricule=5678, name=student2]

axis2 客户端:

public static void main(String[] args) throws Exception
{
    String endPoint = "http://localhost:8080/StudentServiceImplService/StudentServiceImpl";

    ServiceClient sc = new ServiceClient();

    Options opts = new Options();
    opts.setTo(new EndpointReference("http://localhost:8080/StudentServiceImplService/StudentServiceImpl"));
    sc.setOptions(opts);

    OMFactory fac = OMAbstractFactory.getOMFactory();
    OMNamespace omNs = fac.createOMNamespace("http://services.tuto.java.com/","ns1");

    OMElement method = fac.createOMElement("getStudents", omNs);
    OMElement res = sc.sendReceive(method);
    System.out.println(res);

    Iterator<OMElement> it = res.getChildElements();
    while(it.hasNext())
    {
        System.out.println(it.next());
    }
}

给予

<ns2:getStudentsResponse xmlns:ns2="http://services.tuto.java.com/"><student><matricule>1236</matricule><name>student1</name></student><student><matricule>5678</matricule><name>student2</name></student></ns2:getStudentsResponse>
<student><matricule>1236</matricule><name>student1</name></student>
<student><matricule>5678</matricule><name>student2</name></student>

但我不知道如何反序列化 omeelement。

我试过了

Student student = (Student) BeanUtil.deserialize(Student.class,res,new DefaultObjectSupplier(),null);

但是给了我

Student [matricule=null, name=null]

我该怎么办?

留下问题:

  • 不知道如何对轴做同样的事情--OK 见前面--/axis 2
  • “resp”(soap 客户端)仅包含第一个学生

【讨论】:

  • 不知道如何反序列化 omeelement - 请参阅编辑后的回复。
【解决方案2】:

你能不能访问 WSDL 之类的东西

http://localhost:8080/StudentServiceImplService/StudentServiceImpl?wsdl

然后使用axis wsdl2java 让Axis 为您创建客户端代码(其中将包含所有正确的类型映射和命名空间)?

【讨论】:

  • 谢谢。我没有使用您的解决方案,但现在我的轴客户端正在工作。
【解决方案3】:

您使用的是什么 SOAP 绑定样式,RPC/DOCUMENT?如果您使用 RPC,则请求和响应将被编码和处理,Axis2 不支持 RPC 编码格式的消息。尝试使用 DOCUMENT SOAP 绑定样式。 (我应该把这个放在 cmets 中,请多多包涵)

参考https://stackoverflow.com/a/9598193/752129

【讨论】:

  • 谢谢。我尝试添加 @SOAPBinding(style=Style.DOCUMENT, parameterStyle = ParameterStyle.WRAPPED) AxisClient 和 SoapClient 都不起作用。同样的例外。但我使用的是轴而不是轴2。
猜你喜欢
  • 2010-09-16
  • 1970-01-01
  • 2015-11-11
  • 1970-01-01
  • 1970-01-01
  • 2011-11-02
  • 1970-01-01
  • 2020-11-13
  • 1970-01-01
相关资源
最近更新 更多