JBoss ws4ee 一个兄弟写的中文的ws4ee的教程
JBoss ws4ee 鸟
关键词: JBoss ws4ee webservice
晕,这几天尝试在JBoss4.0.3上面做Web Service。因为有可能用EJB做Web Service所以选用JBoss。一开始我所看到的资料上讲用JBoss3中的JBoss.NET做,于是上JBoss官方网站,搜索.NET,发现此.NET已经是old的了,JBoss4中用ws4ee了。倒,于是狂搜一阵ws4ee。终于搜到一篇HelloWorld。http://www.csd.abdn.ac.uk/~bscharla/teaching/mtp_software/jboss/jboss-ws4ee-HelloWorld.shtml 这篇文章真是好,里面还提供了一个用.NET做HelloWorld Web Service的文章的链接。http://www.csd.abdn.ac.uk/~bscharla/teaching/mtp_software/jboss/jboss-net-HelloWorld.shtml。
依葫芦画瓢,我照着上面做了一下,没有任何问题。接下来就做自己的,三个Web Service,分别是加法,乘法和查询。ws4ee居然是以war形式部署的,还要提供远程接口。
AddService远程接口
package com.fitech.demo.ws.add;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface AddServiceRemote extends Remote{
public abstract int add(int param1, int param2) throws RemoteException;
}
AddService实现类
package com.fitech.demo.ws.add;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.server.ServiceLifecycle;
import com.fitech.example.demo.bean.CalculateBean;
import com.fitech.example.demo.dao.hibernate.CalculateBeanDao;
public class AddService implements AddServiceRemote, ServiceLifecycle {
/* (非 Javadoc)
* @see com.fitech.demo.ws.AddServiceRemote#add(int, int)
*/
public int add(int param1, int param2)throws RemoteException {
int result = param1 + param2;
CalculateBeanDao cbd = new CalculateBeanDao();
CalculateBean cb = new CalculateBean();
cb.setParam1(param1);
cb.setParam2(param2);
cb.setValue(String.valueOf(result));
cbd.saveCalculateBean(cb);
return result;
}
public void init(Object arg0) throws ServiceException {
// TODO Auto-generated method stub
}
public void destroy() {
// TODO Auto-generated method stub
}
}
WEB-INF
|---wsdl
|-----addservice.wsdl(由Java2WSDL自动生成)
|---jaxrpc-mapping.xml
|---jboss-web.xml
|---web.xml
|---webservices.xml
===============
jaxrpc-mapping.xml
<?xml version='1.0' encoding='UTF-8' ?>
<java-wsdl-mapping xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd"
version="1.1">
<package-mapping>
<package-type>com.fitech.demo.ws.add</package-type>
<namespaceURI>http://add.ws.demo.fitech.com</namespaceURI>
</package-mapping>
</java-wsdl-mapping>
jboss-web.xml(没有使用任何资源,所以是空的)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.2//EN" "http://www.jboss.org/j2ee/dtd/jboss-web.dtd">
<jboss-web>
<!-- Resource references -->
<!-- EJB References -->
</jboss-web>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>AddServiceServlet</servlet-name>
<servlet-class>com.fitech.demo.ws.add.AddService</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AddServiceServlet</servlet-name>
<url-pattern>/add/jse</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
webservices.xml(其他文件的名字和路径都是在这里配置的)
<?xml version='1.0' encoding='UTF-8' ?>
<webservices xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:impl="http://com.myapp/ws4ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd"
version="1.1">
<webservice-description>
<webservice-description-name>
AddService</webservice-description-name>
<wsdl-file>WEB-INF/wsdl/addservice.wsdl</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/jaxrpc-mapping.xml</jaxrpc-mapping-file>
<port-component>
<port-component-name>AddService</port-component-name>
<wsdl-port>AddService</wsdl-port>
<service-endpoint-interface>
com.fitech.demo.ws.add.AddServiceRemote</service-endpoint-interface>
<service-impl-bean>
<servlet-link>AddServiceServlet</servlet-link>
</service-impl-bean>
</port-component>
</webservice-description>
</webservices>
然后我仿照那个例子写了一个ant的build文件
<project name="jboss-ws4ee-AddService" default="main" basedir=".">
<property name="app.name" value="addservice-ws4ee" />
<property environment="env" />
<!--需要修改JBoss安装目录-->
<property name="jboss.home" value="D:/CompanyProject/jboss-4.0.3SP1" />
<!--需要修改各个Web Service的WEB-INF名字-->
<property name="webinf.name" value="Add_WEB-INF" />
<!--需要修改各个Web Service要包含的class-->
<property name="include.classes" value="com/fitech/demo/ws/add/*.class" />
<!--需要修改各个Web Service的url-->
<property name="service.url" value="http://localhost:8080/ws4ee/services/AddService" />
<!--需要修改各个Web Service的名字-->
<property name="service.name" value="AddService" />
<!--需要修改各个wsdl的路径-->
<property name="wsdl.name" value="Add_WEB-INF/wsdl/addservice.wsdl" />
<!--需要修改各个Web Service的远程接口-->
<property name="remote.interface" value="com.fitech.demo.ws.add.AddServiceRemote" />
<!--需要修改各个Web Service的输出路径-->
<property name="build.dir" value="${basedir}/build/addservice" />
<property name="webinf.dir" value="${basedir}/${webinf.name}" />
<property name="deploy.home" value="${jboss.home}/server/default/deploy" />
<property name="dist.home" value="${deploy.home}" />
<property name="dist.src" value="${app.name}.jar" />
<property name="dist.wsr" value="${app.name}.wsr" />
<property name="dist.war" value="${app.name}.war" />
<property name="dist.ear" value="${app.name}.ear" />
<!--property name="build.war.dir" value="${build.dir}/add_war" /-->
<!-- need to add in details of src.dir -->
<property name="src.dir" value="${basedir}/src" />
<path id="base.libraries">
<pathelement location="${build.dir}/WEB-INF/classes" />
<fileset dir="${jboss.home}/lib">
<include name="*.jar" />
</fileset>
<fileset dir="${jboss.home}/server/default/lib">
<include name="*.jar" />
</fileset>
<fileset dir="${jboss.home}/server/default/deploy/jboss-ws4ee.sar">
<include name="*.jar" />
</fileset>
</path>
<path id="client.classpath">
<pathelement location="${build.classes.dir}" />
<fileset dir="${jboss.home}/client">
<include name="*.jar" />
</fileset>
</path>
<target name="clean">
<delete dir="${build.dir}" />
</target>
<target name="validate">
<available property="classpath_id" value="base.libraries"
file="${jboss.home}/server/default/lib/javax.servlet.jar" />
</target>
<target name="fail_if_not_valid" unless="classpath_id">
<fail
message="jboss.home=${jboss.home} is not a valid JBoss dist directory "
/>
</target>
<target name="prepare" depends="clean, validate, fail_if_not_valid">
<mkdir dir="${build.dir}" />
<mkdir dir="${build.dir}/WEB-INF" />
<mkdir dir="${build.dir}/WEB-INF/classes" />
<!--mkdir dir="${build.dir}/META-INF" /-->
<!-- set the classpath for compiling files -->
<property name="classpath" refid="${classpath_id}" />
<!--copy todir="${build.dir}">
<fileset dir="${basedir}/web">
<include name="**/*" />
</fileset>
</copy-->
<copy todir="${build.dir}/WEB-INF">
<fileset dir="${webinf.dir}">
<include name="**/*" />
</fileset>
</copy>
</target>
<!-- complie the code -->
<target name="compile" depends="prepare">
<!--javac srcdir="src" destdir="${build.classes.dir}"
classpath="${build.classes.dir}" debug="on" optimize="off"
deprecation="on">
<classpath path="${classpath}" />
</javac-->
<copy todir="${build.dir}/WEB-INF/classes">
<fileset dir="bin">
<include name="${include.classes}"/>
</fileset>
</copy>
</target>
<target name="javadoc" depends="prepare">
<javadoc sourcepath="src" packagenames="*" destdir="${javadoc.home}" />
</target>
<!-- now build the wsdl file -->
<target name="wsdl" depends="compile">
<mkdir dir="${build.dir}/WEB-INF/wsdl" />
<java classname="org.jboss.axis.wsdl.Java2WSDL" fork="yes" dir=".">
<classpath path="${classpath}" />
<arg value="-l${service.url}" />
<arg value="-s${service.name}" />
<arg value="-o${wsdl.name}" />
<arg value="-uLITERAL" />
<arg value="${remote.interface}" />
<!-- This last arg value may need to be com.myapp.HelloWorld in order for the class to be found -->
</java>
</target>
<!-- now build the war file -->
<target name="war" depends="wsdl">
<war destfile="${build.dir}/${dist.war}" webxml="${webinf.name}/web.xml">
<!--fileset dir="web" /-->
<webinf dir="${webinf.name}">
<exclude name="web.xml" />
<include name="*.xml" />
<include name="wsdl/*.*" />
</webinf>
<classes dir="${build.dir}/WEB-INF/classes">
<include name="${include.classes}" />
</classes>
</war>
</target>
<!-- for ease of checking that all of the contents are correct -->
<!--target name="unwar" depends="war">
<mkdir dir="${build.war.dir}" />
<unwar src="${build.dir}/${dist.war}" dest="${build.war.dir}" />
</target-->
<!-- now deploy the war file unwar-->
<target name="dist" depends="war">
<copy file="${build.dir}/${dist.war}" todir="${deploy.home}" />
</target>
<!-- run the client -->
<!--target name="run_client"-->
<!--copy file="${src.dir}/main/client/log4j.xml" todir="${build.classes.dir}" /-->
<!--java classname="com.fitech.example.ws.hello.DIIClient" fork="yes"
dir=".">
<classpath refid="client.classpath" />
</java>
</target-->
<target name="main" depends="dist">
</target>
</project>
直接运行ant进行构建,什么事都完成了,包括部署。
由于我在实现类里面通过Hibernate连接数据库,另外建立了一个工程用于与数据库交互。
我把它打成一个包,放到JBoss的Default下面的lib里。初始化Hibernate的语句我把它放到一个类的static块里面,第一次使用该类的时候将进行初始化。
其他两个服务基本和AddService一致,一步一步就做完了。(苦头在后头呢)
客户端:
package com.fitech.demo.ws.client.add;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.ParameterMode;
public class DIIClient {
// modified from sun j2ee jaxrpc example
private static String add_endpoint = "http://localhost:8080/addservice-ws4ee/add/jse";
private static String add_qnameService = "AddServiceRemoteService";
private static String add_qnamePort = "AddServiceRemote";
private static String ADD_BODY_NAMESPACE_VALUE = "http://add.ws.demo.fitech.com";
private static String multiply_endpoint = "http://localhost:8080/multiplyservice-ws4ee/multiply/jse";
private static String multiply_qnameService = "MultiplyServiceRemoteService";
private static String multiply_qnamePort = "MultiplyServiceRemote";
private static String MULTIPLY_BODY_NAMESPACE_VALUE = "http://multiply.ws.demo.fitech.com";
private static String query_endpoint = "http://localhost:8080/queryservice-ws4ee/query/jse";
private static String query_qnameService = "QueryServiceRemoteService";
private static String query_qnamePort = "QueryServiceRemote";
private static String QUERY_BODY_NAMESPACE_VALUE = "http://query.ws.demo.fitech.com";
private static String ENCODING_STYLE_PROPERTY = "javax.xml.rpc.encodingstyle.namespace.uri";
private static String NS_XSD = "http://www.w3.org/2001/XMLSchema";
private static String URI_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
public static void main(String[] args) {
System.out.println("提供3种web服务,加,乘,查询");
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
String command = br.readLine();
ServiceFactory factory = ServiceFactory.newInstance();
while (!command.equals("quit")) {
if (command.startsWith("add")) {
StringTokenizer st = new StringTokenizer(command);
st.nextToken();
int param1 = Integer.parseInt(st.nextToken());
int param2 = Integer.parseInt(st.nextToken());
Service service = factory.createService(new QName(
add_qnameService));
QName port = new QName(add_qnamePort);
Call call = service.createCall(port);
call.setTargetEndpointAddress(add_endpoint);
call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(
true));
call.setProperty(Call.SOAPACTION_URI_PROPERTY, "");
call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING);
QName QNAME_TYPE_INT = new QName(NS_XSD, "int");
call.setReturnType(QNAME_TYPE_INT);
call.setOperationName(new QName(ADD_BODY_NAMESPACE_VALUE,
"add"));
call.addParameter("in0", QNAME_TYPE_INT, ParameterMode.IN);
call.addParameter("in1", QNAME_TYPE_INT, ParameterMode.IN);
Object[] params = { new Integer(param1),
new Integer(param2) };
Object result = call.invoke(params);
System.out.println(result);
} else if (command.startsWith("multiply")) {
StringTokenizer st = new StringTokenizer(command);
st.nextToken();
int param1 = Integer.parseInt(st.nextToken());
int param2 = Integer.parseInt(st.nextToken());
Service service = factory.createService(new QName(
multiply_qnameService));
QName port = new QName(multiply_qnamePort);
Call call = service.createCall(port);
call.setTargetEndpointAddress(multiply_endpoint);
call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(
true));
call.setProperty(Call.SOAPACTION_URI_PROPERTY, "");
call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING);
QName QNAME_TYPE_INT = new QName(NS_XSD, "int");
call.setReturnType(QNAME_TYPE_INT);
call.setOperationName(new QName(
MULTIPLY_BODY_NAMESPACE_VALUE, "multiply"));
call.addParameter("in0", QNAME_TYPE_INT, ParameterMode.IN);
call.addParameter("in1", QNAME_TYPE_INT, ParameterMode.IN);
Object[] params = { new Integer(param1),
new Integer(param2) };
Object result = call.invoke(params);
System.out.println(result);
} else if (command.startsWith("findall")) {
Service service = factory.createService(new QName(
query_qnameService));
QName port = new QName(query_qnamePort);
Call call = service.createCall(port);
call.setTargetEndpointAddress(query_endpoint);
call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(
true));
call.setProperty(Call.SOAPACTION_URI_PROPERTY, "");
call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING);
QName QNAME_TYPE_STRING = new QName(NS_XSD, "string");
call.setReturnType(QNAME_TYPE_STRING);
call.setOperationName(new QName(QUERY_BODY_NAMESPACE_VALUE,
"findAllCalculateBean"));
Object[] params = {};
Object result = call.invoke(params);
System.out.println(result);
} else if (command.startsWith("findbyvalue")) {
StringTokenizer st = new StringTokenizer(command);
st.nextToken();
String param1 = st.nextToken();
Service service = factory.createService(new QName(
query_qnameService));
QName port = new QName(query_qnamePort);
Call call = service.createCall(port);
call.setTargetEndpointAddress(query_endpoint);
call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(
true));
call.setProperty(Call.SOAPACTION_URI_PROPERTY, "");
call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING);
QName QNAME_TYPE_STRING = new QName(NS_XSD, "string");
call.setReturnType(QNAME_TYPE_STRING);
call.setOperationName(new QName(QUERY_BODY_NAMESPACE_VALUE,
"findByValue"));
call.addParameter("in0", QNAME_TYPE_STRING,
ParameterMode.IN);
Object[] params = { param1 };
Object result = call.invoke(params);
System.out.println(result);
}
command = br.readLine();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
^_^,说说运行调试的惨痛经历吧。
遇到的第一个问题是,在web.xml中我把servlet-class写成了远程接口,导致出现Initiation异常,百思不得其解的时候查看了那个HelloWorld例子才发现!
接下来一个问题就更加莫名奇怪了,原来我的那个实现类没有实现ServiceLifecycle接口!
然后遇到的问题就比较好解决,没有把Hibernate的包放到default的lib下面会出现ClassNotFoundException。
最后一个问题就根本没有解决,就是那个查询服务,本来想返回给客户端一个对象数组,总是出现找不到serializer问题。晕,后来想想,这个项目是由Delphi客户端来调,传Java对象回去也没什么用,还不如直接传string回去。谁知后来又出现can't find package type for class...问题,搜了n久才发现jaxrpc-mapping.xml中的package没有映射对。jaxrpc-mapping中的namespaceURI应该和wsdl中的一致的!
唉,最后总算搞定了,晕地一塌!