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