我想构建一个将在 Java SE 6.0 中运行的 JAX-WS Web 服务(没有容器,只有标准版 java)。
我从这里描述的旧教程开始http://today.java.net/pub/a/today/2007/07/03/jax-ws-web-services-without-ee-containers.html
但是我遇到了一些问题。
当我对我的 WebService 类 (acximImpl) 运行 wsgen 时,它将生成操作方法的类文件和从操作返回的类,但它不会生成作为参数传递给操作方法的类的代码。
因此,当我使用客户端调用 queryParts1() 方法时,我得到了一个肥皂错误,说“找不到 {http://com/activant/web/services/partorder}queryParts1Request 的调度方法”
我正在使用 NetBeans IDE 7.0.1
由 NetBeans 运行的 build.xml 如下所示:(它在 netbeans 编译我的类文件后运行)
<project name="acximserver" default="default" basedir=".">
<description>Builds, tests, and runs the project acximserver.</description>
<import file="nbproject/build-impl.xml"/>
<target name="-post-compile" >
<echo message="Generating artifacts..."/>
<exec executable="C:/acxim/BuildTools/JAX-WS/2.2.3/bin/wsgen.bat">
<env key="JAVA_HOME" value="C:\BuildTools\jdk\1.6.0.24"/>
<arg value="-verbose"/>
<arg value="-keep"/>
<arg value="-cp"/>
<arg value="C:/Connectivity/APFCLSDK/Components/acximserver/build/classes"/>
<arg value="-d"/>
<arg value="${annotation.processing.source.output}"/>
<arg value="com.epicor.acximsdk.acximserver.acximImpl"/>
</exec>
<javac debug="true"
srcdir="${annotation.processing.source.output}"
destdir="C:/Connectivity/APFCLSDK/Components/acximserver/build/classes"
classpath="${acxclasspath}"/>
</target>
我的主类文件如下所示:
package com.epicor.acximsdk.acximserver;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import javax.xml.bind.annotation.XmlElement;
import org.apache.log4j.Logger;
public class Acximserver {
private Endpoint endpoint = null;
private static final Logger logger = Logger.getLogger("com.epicor.acximsdk.acximserver");
public Acximserver() {
System.out.println("Acximserver constructor called.");
endpoint = Endpoint.create(new acximImpl());
logger.info("Inside Acximserver constructor");
}
private void publish() {
endpoint.publish("http://localhost:1970/acximservice/PartOrderMgr");
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
System.out.println("Acximserver main() function called");
Acximserver acxim = new Acximserver();
acxim.publish();
System.out.println("Acximserver Open for business at:");
System.out.println(" http://localhost:1970/acximservice/PartOrderMgr");
}
}
我的 WebService 类如下所示:
package com.epicor.acximsdk.acximserver;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import javax.xml.bind.annotation.XmlElement;
import javax.jws.HandlerChain;
@WebService(
name = "acximservice",
serviceName = "PartOrderMgr",
targetNamespace = "http://com/activant/web/services/partorder"
)
@HandlerChain(file="soaphandler.xml") // Setup some custom classes to intercept messages for logging.
public class acximImpl {
public acximImpl() {
System.out.println("acximImpl constructor called.");
}
@WebMethod(operationName = "queryParts1")
@WebResult(name = "queryParts1Response")
public QueryParts1Response queryParts1(
@WebParam(name = "Credentials", header = true) Credentials credentials,
@WebParam(name = "queryParts1Request") @XmlElement(required = true) QueryParts1Request request
//Credentials credentials,
//QueryParts1Request request
)
{
String tracknum = "";
QueryParts1Response response = new QueryParts1Response();
if(credentials != null) {
System.out.println("Token = " + (credentials.getToken()==null ? "null" : credentials.getToken()));
System.out.println("TokenSignature = " + (credentials.getTokenSignature()==null ? "null" : credentials.getTokenSignature()));
} else
System.out.println("credentials is null");
if(request != null) {
if(request.metadata != null) {
System.out.println("timeout = " + request.metadata.gettimeout());
System.out.println("ACXTrackNum = " + (request.metadata.getACXTrackNum()==null ? "null" : request.metadata.getACXTrackNum()));
if(request.metadata.getACXTrackNum() != null)
tracknum = request.metadata.getACXTrackNum();
}
else {
System.out.println("metadata is null");
}
if(request.requestString != null)
System.out.println("reqeust = " + request);
else
System.out.println("requestString is null");
}
else
System.out.println("request is null");
response._return = createACXNotification("buyid", "sellid", tracknum, "INFO", "0", "Service is working");
return response;
}
public String makeRequestHeader(String acxRequestName) {
return "<?xml version=\"1.0\" ?>" +
"<!DOCTYPE " + acxRequestName + " SYSTEM '" +
"http://www.aconnex.com/DTD" + "/" + acxRequestName +
"_v1_0" + ".dtd'>";
}
protected String createACXNotification(String Buy, String Sell, String Track, String Sev, String Code, String Msg) {
String version = "1.0"; // somehow make this configurable.
StringBuffer buf = new StringBuffer();
buf.append(makeRequestHeader("ACXNotificationResponse"));
buf.append("<ACXNotificationResponse><Envelope><BuyPartnerID>");
buf.append(Buy);
buf.append("</BuyPartnerID><DocVersNum>");
buf.append(version);
buf.append("</DocVersNum><DocGenBy>Epicor javaSDK</DocGenBy></Envelope>");
buf.append("<NotificationResponse><ACXTrackNum>");
buf.append(Track);
buf.append("</ACXTrackNum><SellPartnerID>");
buf.append(Sell);
buf.append("</SellPartnerID><Severity>");
buf.append(Sev);
buf.append("</Severity><Code>");
buf.append(Code);
buf.append("</Code><Msg>");
buf.append(Msg);
buf.append("</Msg></NotificationResponse></ACXNotificationResponse>");
return buf.toString();
}
}
生成的 queryParts1() 方法返回的类 QueryParts1Response 如下所示:
package com.epicor.acximsdk.acximserver;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
//@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "queryParts1Response", propOrder = {
"_return"
})
@XmlRootElement(name = "queryParts1Response")
public class QueryParts1Response {
@XmlElement(name = "return", required = true)
protected String _return;
/**
* Gets the value of the return property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getReturn() {
return _return;
}
/**
* Sets the value of the return property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setReturn(String value) {
this._return = value;
}
}
作为 queryParts1() 方法的参数并且不会生成的 QueryParts1Request 类如下所示:
package com.epicor.acximsdk.acximserver;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
//@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://com/activant/web/services/partorder", propOrder = {
"requestString",
"metadata"
})
@XmlRootElement(name = "queryParts1Request")
public class QueryParts1Request {
@XmlElement(name = "requestString", required = true)
protected String requestString;
@XmlElement(name = "metadata", required = true)
protected Metadata1TYPE metadata;
/**
* Gets the value of the requestString property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getRequestString() {
return requestString;
}
/**
* Sets the value of the requestString property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setRequestString(String value) {
this.requestString = value;
}
/**
* Gets the value of the metadata property.
*
* @return
* possible object is
* {@link Metadata1TYPE }
*
*/
public Metadata1TYPE getMetadata() {
return metadata;
}
/**
* Sets the value of the metadata property.
*
* @param value
* allowed object is
* {@link Metadata1TYPE }
*
*/
public void setMetadata(Metadata1TYPE value) {
this.metadata = value;
}
}
如何让 wsgen 为方法参数列表中的对象生成类文件?请注意,主类使用 EndPoint 类发布 Web 服务正在侦听的 url。
任何帮助将不胜感激。谢谢。