解决Unmarshalling Error: unexpected element...Expected elements are...报错

记录:315

场景:解决org.apache.axis2.AxisFault: Unmarshalling Error: unexpected element(uri:"http://www.pro.com", local:"xmlStr"). Expected elements are<{}arg0>。

版本:

JDK 1.8
Spring Boot 2.6.3
Apache CXF 3.5.1
Apache Axis2 1.8.2

基础环境:

服务端:基于Spring Boot应用Apache CXF发布的Web Services服务作为服务端。

客户端:基于Spring Boot使用Apache Axis2实现的Web Services客户端。

1.报错解决

1.1报错信息

报错信息一:org.apache.axis2.AxisFault: Unmarshalling Error: 意外的元素 (uri:"http://www.pro.com", local:"xmlStr")。所需元素为<{}arg0>

报错信息二:org.apache.axis2.AxisFault: Unmarshalling Error: unexpected element(uri:"http://www.pro.com", local:"xmlStr"). Expected elements are<{}arg0>

报错信息三org.apache.axis2.AxisFault: Unmarshalling Error: 意外的元素 (uri:"http://www.pro.com", local:"arg0")。所需元素为<{}arg0>

报错信息四:org.apache.axis2.AxisFault: Unmarshalling Error: unexpected element(uri:"http://www.pro.com", local:"arg0"). Expected elements are<{}arg0>

报错信息五:org.apache.axis2.AxisFault: Unmarshalling Error: 意外的元素 (uri:"http://www.pro.com", local:"xmlStr")。所需元素为<{}xmlStr>

报错信息六:org.apache.axis2.AxisFault: Unmarshalling Error: unexpected element(uri:"http://www.pro.com", local:"xmlStr"). Expected elements are<{}xmlStr>

1.2问题分析

分析原因:

(1)Apache Axis2实现的客户端,在调用服务端方法时,客户端设置调用方法的参数名和服务端参数名称不匹配;客户端设置设置命名空间名称和服务端发布方法上的命名空间不匹配。

(2)如果使用Apache CXF实现的客户端不会出现这种报错,区别在于Apache CXF一般都是动态方式创建客户端,Apache CXF底层会去做这些参数匹配。而使用Apache Axis2实现的客户端,一般的都是静态指定的相关参数,因此,需要严格匹配。

1.3解决

(1)服务端设置

在服务端发布的方法上,加上@WebParam注解,并且该注解的name和targetNamespace属性都得赋值。

例如:

@WebService(targetNamespace = "http://www.pro.com")
public interface IProvinceInfo {
  String getProvince(@WebParam(name = "xmlStr", targetNamespace = "http://www.pro.com") String xmlStr);
}

(2)客户端设置

客户端需严格匹配服务端的设置。

例如:

@Slf4j
public class Axis2ClientUtils {
  public static void main(String[] args) {
    // 1.服务端地址
    String wsdlAddr = "http://127.0.0.1:18080/example-cxf/WebServices/provinceInfoWS?wsdl";
    // 2.服务端的命名空间
    String targetNamespace = "http://www.pro.com";
    // 3.服务端发布的方法
    String methodName = "getProvince";
    // 4.服务端发布的方法的入参的参数名称
    String paramName = "xmlStr";
    // 5.服务端发布的方法的入参的参数值
    String paramValue = "Hangzhou";
    try {
        String result = Axis2ClientUtils.invokeWs(wsdlAddr, targetNamespace,
                methodName, paramName, paramValue);
        log.info("Axis2客户端接收到服务端返回值:" + result.toString());
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
  public static String invokeWs(String wsdlAddr, String targetNamespace, String methodName, Object... params) {
   String result = "";
   try {
      ServiceClient serviceClient = new ServiceClient();
      Options options = serviceClient.getOptions();
      EndpointReference endpointReference = new EndpointReference(wsdlAddr);
      options.setTo(endpointReference);
      // 服务端没有指定soapAction,则直接设置为空
      options.setAction("");
      OMFactory omFactory = OMAbstractFactory.getOMFactory();
      OMNamespace omNamespace = omFactory.createOMNamespace(targetNamespace, "");
      // 服务端发布的方法,客户端会用一个OMElement对象去对应
      OMElement methodOMElement = omFactory.createOMElement(methodName, omNamespace);
      // 服务端方法的形式参数名称和实参的值是一对的且传入一个OMElement
      // 如果服务端方法有多个参数,则就会构造多个OMElement
      for (int i = 0; i < params.length; i = i + 2) {
          // 参数名称
          OMElement paraOMElement = omFactory.createOMElement(String.valueOf(params[i]), omNamespace);
          // 参数值
          paraOMElement.setText(String.valueOf(params[i + 1]));
          // 把设置参数的OMElement加入到方法的OMElement中
          methodOMElement.addChild(paraOMElement);
      }
      methodOMElement.build();
      // 返回结果有一个OMElement对象去对应
      OMElement resultOMElement = serviceClient.sendReceive(methodOMElement);
      result = resultOMElement.getFirstElement().toString();
   } catch (Exception e) {
       e.printStackTrace();
   }
   return result;
  }
  public static String getXmlStr() {
      String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
              "<data>\n" +
              "  <row>\n" +
              "   <column Name=\"ProvinceName\">浙江</column>\n" +
              "   <column Name=\"ProvinceNo\">330000</column>\n" +
              "  </row>\n" +
              "</data>";
      return xmlStr;
  }
}

2.查看wsdl文件

在开发客户端时,一般需要了解到服务端发布服务信息,一般从wsdl文件中获取。

服务端发布wsdl地址:

http://127.0.0.1:18080/example-cxf/WebServices/provinceInfoWS?wsdl

使用wsdl地址在浏览器中访问,可以看到页面信息。

命名空间名称:targetNamespace="http://www.pro.com"。

方法名称:getProvince。

方法参数名称:xmlStr。

soapAction名称:<soap:operation soapAction="" style="document"/>。

服务名称,<wsdl:service name="ProvinceInfoImplService">。

以上,感谢。

2022年11月13日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值