Java 前台 cxf 调用 WebService 问题汇总

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dkbnull/article/details/87915172

Java EE 目录:https://blog.csdn.net/dkbnull/article/details/87932809


最近与客户对接接口,客户提供了WebService测试地址,调用过程中出现了一些问题,在此记录下。

1. unexpected element (uri:“http://xxx.xxx.xxx”, local:“arg”). Expected elements are <{}arg>

直接使用axis方式调用WebService,返回异常信息 unexpected element (uri:“http://xxx.xxx.xxx”, local:“arg”). Expected elements are <{}arg>

经查,是因为WebService服务端是使用cxf集成发布的,axis方式调用cxf发布的WebService服务时,要求

1、cxf服务端发布WebService接口时,需要在接口类上注解@WebService(targetNamespace=“http://xxx.xxx.xxx”),来声明命名空间,命名空间缺失会抛出异常 Unexpected wrapper element {http://service.jx4a.services.ismp.sitech.com}xxx found. Expected {http://xxx.xxx.xxx}xxx.

2、cxf服务端发布WebService接口时,需要在定义的方法参数上注解@WebParam(name=“xxxx”),来声明参数,例:public String xxx(@WebParam(name=“xxxx”) String xxxx)。否则会抛出异常 unexpected element (uri:“http://xxx.xxx.xxx”, local:“arg”). Expected elements are <{}xxxx>

即,出现unexpected element (uri:“http://xxx.xxx.xxx”, local:“arg”). Expected elements are <{}arg>异常是因为cxf发布的WebService服务没有使用@WebParam注解参数。

解决办法

1、让对方修改发布的WebService服务,在对应方法上增加@WebParam注解。
但我们让对方修改已经发布的WebService服务显然不太现实,那就只有从客户端找寻解决的办法。

2、使用cxf方式调用cxf集成发布的WebService服务,不管有没有注解参数都可成功调用

cxf方式调用WebService服务参考文章 Java 调用 WebServicehttps://blog.csdn.net/dkbnull/article/details/87915104


2. WSDLException (at /soap:Envelope): faultCode=INVALID_WSDL: Expected element ‘{http://schemas.xmlsoap.org/wsdl/}definitions’.

详细报错信息如下:

org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.

Caused by: javax.wsdl.WSDLException: WSDLException (at /soap:Envelope): faultCode=INVALID_WSDL: Expected element '{http://schemas.xmlsoap.org/wsdl/}definitions'.

解决办法

请求地址加上?wsdl后缀

例如:原来请求地址为,http://localhost:8080/WebService/service ,现修改为 http://localhost:8080/WebService/service?wsdl


3. java.lang.IllegalStateException: No compiler detected, make sure you are running on top of a JDK instead of a JRE.

在使用idea debug或者run 调试程序时,运行没有问题,能正常访问,也能正常接收到返回信息,但是打包成jar包以 java -jar 命令运行,就报错,详细报错信息如下:

java.lang.IllegalStateException: No compiler detected, make sure you are running on top of a JDK instead of a JRE.
	at org.apache.cxf.common.util.Compiler.useJava6Compiler(Compiler.java:193)
	at org.apache.cxf.common.util.Compiler.compileFiles(Compiler.java:141)
	at org.apache.cxf.common.util.Compiler.compileFiles(Compiler.java:136)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.compileJavaSrc(DynamicClientFactory.java:639)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:389)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:244)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:237)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:192)

按照字面意思是 没有检测到编译器,请确保是在JDK而不是JRE上运行程序

网上找解决办法,也是说程序使用了JRE运行,没有使用JDK运行。那怎么让程序以JDK运行呢?

1、环境变量中配置了JRE_HOME,去掉环境变量中的JRE_HOME。但是我并没有配置JRE_HOME的环境变量。

2、环境变量中JAVA_HOME配置成了jre路径,例如E:\Program Files\Java\jre1.8.0_161,修改成正确的jdk路径即可。但是我这里配置的就是jdk的路径。

网上解决办法,基本上都是说环境变量问题,如何修改环境变量,但是我这里环境变量配置的是没有问题的。

看来我们只能从源码来分析了,报错信息说at org.apache.cxf.common.util.Compiler.useJava6Compiler(Compiler.java:193)这里报错,我们进到这个方法。

    protected boolean useJava6Compiler(String[] files) {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            throw new IllegalStateException("No compiler detected, make sure you are running on top of a JDK instead of a JRE.");
        } else {
            StandardJavaFileManager fileManager = compiler.getStandardFileManager((DiagnosticListener)null, (Locale)null, (Charset)null);
            Iterable<? extends JavaFileObject> fileList = fileManager.getJavaFileObjectsFromStrings(Arrays.asList(files));
            return this.internalJava6Compile(compiler, this.wrapJavaFileManager(fileManager), this.setupDiagnosticListener(), fileList);
        }
    }

当JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();为null的时候,会抛出这个异常。

再进到这个方法

    private static final String defaultJavaCompilerName
        = "com.sun.tools.javac.api.JavacTool";

    public static JavaCompiler getSystemJavaCompiler() {
        return instance().getSystemTool(JavaCompiler.class, defaultJavaCompilerName);
    }

我们发现他是去加载com.sun.tools.javac.api.JavacTool类,这个类是在jdk安装目录\lib\tools.jar,jre安装目录\lib中没有这个jar。

那他既然说我们是在jre上运行,而没有在jdk上运行,并且是要去lib\tooks.jar中加载com.sun.tools.javac.api.JavacTool,那我们把jdk安装目录\lib\tools.jar复制到jre安装目录\lib文件夹下

解决办法

1、把jdk安装目录\lib\tools.jar复制到jre安装目录\lib文件夹下

再次运行,程序正常,能正常访问WebService。

但是我们每次安装完Java环境,都把tools.jar复制一遍会很麻烦,这里就可以直接指定 java -jar 命令运行的 jdk环境。

2、指定 java -jar 命令运行的JDK环境,即使用指定JDK来运行Java程序

例如,博主这里使用的Spring Boot框架,启动命令如下

java -jar springbootdemo.jar

修改成为

"%JAVA_HOME%\bin\java" -jar springbootdemo.jar

猜你喜欢

转载自blog.csdn.net/dkbnull/article/details/87915172
今日推荐