本文討論WebLogic Server 9(下簡稱WLS9)中的新特性:Java Web Service (JWS)。WLS9的Web Services子系統實現了J2EE 1.4中的Web Services的新標準: Enterprise Web Services 1.1 specification (JSR-921)。
該規范定義了標準的J2EE Web Service打包格式,部署模塊以及運行時服務。
JSR-921是J2EE 1.3中Web Services規范JSR-109的1.1維護版本。在Web Services 1.1中描述了J2EE Web Service的業務邏輯有兩種實現方式:一種是使用Web容器中的JavaBean,另一種是使用EJB容器中的無狀態Session Bean。與舊的Web Services開發方式不同,BEA建議使用JWS這種基于注釋的Web Services編程方式以簡化開發。這種編程方式的開發過程大概是這樣,利用JDK5的新特性元數據注釋(JSR-175),在編寫上述的Java Bean或EJB的Bean類時在業務邏輯代碼中添加一些特殊注釋,然后用ANT的一些擴展任務可以生成一些相關JAVA類代碼(主要是EJB的存根、樁)和配置文件,最后自動編譯這些類代碼并自動打包。所以可以說JWS方式是Web Services新標準的核心。JWS文件實際就是普通的.JAVA文件(擴展名依舊是.JAVA),通過添加注釋來制定WS的特性。這些注釋在JSR181中有完整的說明。如果Web Service用Java Bean類實現,自動打包后會包含web.xml,weblogic.xml, webservices.xml,weblogic-webservices.xml,JAX-RPC數據類型映射文件和WSDL等,并被打包成標準Web應用的WAR。如果用EJB實現,則會包含ejb-jar.xml和weblogic-ejb.jar.xml等,并被自動打包成標準EJB的JAR。下圖描述了JWS文件生成可部署的J2EE模塊的詳細過程。后面我們會用兩個例子詳細說明如何開發、部署基于Java Bean和基于EJB的Web Services。
JSR181與JSR175介紹
我們先來看一段典型的使用JSR175特征的代碼。
package webservices.jsr181.pojo;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(name="StringChangerPort", targetNamespace="http://wwtt.bea.com")
public class StringChanger {
@WebMethod()
public String toUpper(String upperReqString)
{
……
這個類的源代碼和普通的JAVA代碼沒太多區別,但和普通JAVA代碼不同的是這里面還包含了很多以@開頭的代碼,或者稱為注釋,也就是在Java 5中的新語法,JSR-175。JSR-175規范只是定義這種語法規則,而用這種語法來如何將這個類生成一個Web Service接口,則需要由JSR-181規范來決定。所以這些JSR-175的注釋才真正決定了這個Web Service的行為和外觀。
也許你會覺得這種語法比較奇怪,有些像普通java方法的語法,只是前面多了一個@。實際在JSR175規范的早期,該語法并不是像現在這樣的。如果按早期寫法,@WebService()會該寫為:
/**
* @WebService(......)
*/ 后來出于簡化,成了現在的樣子。如果使用Weblogic Platform 7.x或8.x產品,會在許多其專有的代碼文件中看到這種格式的注釋。由于撰寫本文時Weblogic Platform 9還沒有發布。發布后是否那些專有代碼會使用基于JSR-175的語法還不得而知,但可以確定的是在Weblgic Server 9中這種語法已經被全面支持了,無論在Web Service中,還是在EJB中。
事實上JSR 181是BEA提出的用于加速Web Services開發的一種基于注釋驅動的編程模式,并被批準納入到J2EE 1.5標準。JSR181提供了一種簡單的Web Service開發編程模型和標準的編譯及部署方式。只需要編寫JSR-175風格的注釋就可以制定WSDL,消息產生屬性,安全認證方式,以及特定的消息頭。
練習的預備工作
準備必要軟件。
進行練習前需要預先安裝WLS9正式版,可以到BEA官方網站上免費下載。本練習可在能安裝WLS9的任何操作系統上完成,為了方便起見,文中僅以在Windows XP上開發為例。此外本文中代碼的開發環境為Eclipse 3.1及對應的Lomboz,當然如您所愿任何其他支持ANT的開發環境都是可以的。
配置Weblogic Server。
準備好上述軟件后,首先用配置創建一個新的WLS Domain。記得用戶名和密碼要都設為weblogic,端口為7001。創建好后啟動該Domain,并用瀏覽器啟動相應的Console,用帳戶weblogic/weblogic登錄進入。
配置Eclipse。
如果希望Eclipse的配置盡量吻合本文的環境,可參考我的另一篇文章:“使用Eclipse加速Weblogic Server開發”的第一步到第二步。配置好后在Eclipse的File->New Project中選取Java Project,在Project Name中將我們這個練習的名字設為JSR-181 Web Services或任何你喜歡的名字,JDK Compliance中選擇“Use a project specific compliance 5.0”,其余保持默認。一個符合我們需要的Project就建好了。
修改腳本文件。
本練習所有的構建過程都由ANT來完成,因此我們需要添加一些ANT的腳本配置文件。屬性文件,宏定義文件可以完全參照《使用Eclipse加速Weblogic Server開發》,因此只需要吧那里面的那三個文件拿過來用就可以了。
需要修改的是build.xml文件,這里定義的屬性主要是為后面兩個例子設置一些路徑。
<?xml version="1.0"?>
<project name="WLS v9 JSR-181 Web Services" basedir=".">
<property file="wls-build-tools/weblogicServer.properties" />
<import file="wls-build-tools/weblogicServer.macrodef" />
<taskdef file="wls-build-tools/weblogicTasks.properties" classpathref="jwsbuild.class.path" />
<property name="apps.src.dir" location="." />
<property name="apps.dest.dir" location="${temp.dir}" />
<property name="clients.src.dir" location="." />
<property name="clients.dest.dir" location="${temp.dir}" />
<property name="clients.package.name" value="client.test"/>
<property name="clients.package.path" value="client/test"/>
<property name="jbApp.context.name" value="jb" />
<property name="jbApp.package.name" value="webservices.jsr181.pojo"/>
<property name="jbApp.src.dir" location="${apps.src.dir}/webservices/jsr181/pojo"/>
<property name="jbApp.jwsSource.file" value="StringChanger.java" />
<property name="jbApp.dest.dir" location="${apps.dest.dir}/${jbApp.context.name}" />
<property name="jbApp.service.name" value="StringChangerService" />
<property name="jbApp.wsdl.url" value="http://${domain.address}:${domain.port}/${jbApp.context.name}/${jbApp.service.name}?WSDL" />
<property name="jbApp.deploy.name" value="WLS v9 JSR-181 Javabean Web Service" />
<property name="ejbApp.context.name" value="ejb" />
<property name="ejbApp.package.name" value="webservices.jsr181.ejb"/>
<property name="ejbApp.src.dir" location="${apps.src.dir}/webservices/jsr181/ejb"/>
<property name="ejbApp.jwsSource.file" value="PurchaseOrder.java" />
<property name="ejbApp.dest.dir" location="${apps.dest.dir}/${ejbApp.context.name}" />
<property name="ejbApp.service.name" value="PurchaseOrderService" />
<property name="ejbApp.wsdl.url" value="http://${domain.address}:${domain.port}/${ejbApp.context.name}/${ejbApp.service.name}?WSDL" />
<property name="ejbApp.wsdl.local" value="jar:file:${apps.dest.dir}/${ejbApp.context.name}/PurchaseOrder.jar!/META-INF/${ejbApp.service.name}.wsdl" />
<property name="ejbApp.deploy.name" value="WLS v9 JSR-181 EJB Web Service" />
<path id="jwsbuild.class.path">
<fileset dir="${weblogic.home}/server/lib">
<include name="weblogic.jar" />
<include name="xbean.jar" />
</fileset>
<fileset dir="${jdk5.home}/lib">
<include name="tools.jar" />
</fileset>
</path>
<path id="javabuild.class.path">
<pathelement path="${clients.dest.dir}" />
<fileset dir="${weblogic.home}/server/lib">
<include name="webserviceclient.jar" />
</fileset>
</path>
<!--后面的練習中我們將根據需要在此添加一些target。-->
</project>
如何快速查看例子的結果,而跳過開發環節。
做好1到4步驟就可以按照后面幾節所述完成練習。但如果想快速看一下練習結果,將本文附件solution包括所有源代碼。解壓到您磁盤任何位置,用Eclipse創建好一空的名為JSR-181 Web Services的Project后,用solution解出的JSR-181 Web Services文件夾替換這個Project的文件夾。最后在Eclipse的Package Explorer中刷新一下,就瀏覽已經開發配置好Eclipse Project代碼了。修改項目的wls-build-tools路徑下weblogicServer.properties中的WLS和JDK環境變量,然后就可以執行ANT腳本中的任務來編譯,部署,測試等步驟。
開發基于JavaBean的Web Services
基于JavaBean的Web Servics是最簡單的一種方式。我們只需要在普通的JavaBean碼中添加一些符合JSR181的注釋,在build.xml中調用WLS提供的擴展ANT Task,就可以完成一個完整的Web Services。
創建一個Java Bean。
在Project的根目錄下創建一個類名為StringChanger,包名為webservices.jsr181.pojo,寫入如下內容:
package webservices.jsr181.pojo;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import weblogic.jws.WLHttpTransport;
@WebService(name="StringChangerPort", targetNamespace="http://bea.com")
@SOAPBinding(style=SOAPBinding.Style.RPC, use=SOAPBinding.Use.ENCODED)
@WLHttpTransport(contextPath="jb", serviceUri="StringChangerService")
public class StringChanger {
@WebMethod()
public String toUpper(String upperReqString)
{
String upper = upperReqString.toUpperCase();
System.out.println("toUpper Request: " + upperReqString);
System.out.println("toUpper Reply: " + upper);
return(upper);
}
@WebMethod(operationName="toLower")
public String toLowerCase(String lowerReqString)
{
String lower = lowerReqString.toLowerCase();
System.out.println("toLowerCase Request: " + lowerReqString);
System.out.println("toLowerCase Reply: " + lower);
return(lower);
}
}
這個類是用于實現我們這個Web Services模塊的業務邏輯,以及描述這個Web Service接口。該類中包含兩個public的業務方法:toUpper(String): String和toLowerCase(String): String。其中的邏輯也很簡單:前者將傳入的字符串全變成大寫,后者則全變成小寫。并且兩個方法都將在終端上將操作過程打印出來。除了這兩法方法,其余都是用于描述Web Service接口的JSR-181注釋。
先看一些類級別的注釋。@WebService()表示這個類可以生成Web Service。name用于映射到WSDL文件的<wsdl:portType>元素,可以在生成的WSDL中找到<wsdl:portType>的值為StringChangerPort。targetNamespace用于指定WSDL文件中元素的命名空間,能在生成的WSDL中找到對應的targetNamespace="http://bea.com"。@SOAPBinding()表示這個服務可以映射到一個SOAP消息中。Style用于指定SOAP消息請求和回應的編碼方式為RPC。use用于指定SOAP消息請求和回應是明文還是密文,此處表示為密文。@WLHttpTransport是一個Weblogic專用的注釋,用于指生成的配置文件中的上下文路徑和這個Web Service的URI。contextPath用于指定上下文路徑為jb,也就是說可以用 http://localhost:7001/jb/ 這個URL來調用這個Web Services應用。serviceUri表示客戶端訪問這個Web Service的URI為 http://localhost:7001/jb/StringChangerService。
再看一些方法級別的注釋。方法級注釋為@WebMethod()。operationName為操作的名字,用于映射到WSDL文件的<wsdl:operation>元素。默認值為對應的方法名。因此在這個JavaBean生成的Web Service中toUpper方法對應的操作名為toUpper,toLowerCase方法對應的操作名為toLower。
編寫build.xml Target。
<target name="build.jb" depends="clean.jb">
<jwsc srcdir="${jbApp.src.dir}" destdir="${jbApp.dest.dir}" listfiles="true" classpathref="jwsbuild.class.path">
<jws file="${jbApp.jwsSource.file}" />
</jwsc>
</target>
<target name="deploy.jb" depends="check.jb" if="jb.exists">
<wls.deploy deploy.dir="${jbApp.dest.dir}" deploy.name="${jbApp.deploy.name}" />
</target>
build.jb 這個Target主要用于建立一個可部署的Web Services模塊。jwsc這個任務是用于分析JWS文件中的注釋,生成對應JAVA文件配置文件,編譯代碼,最后在destdir指定的位置生成這個Web Services的WAR包。
deploy.jb這個Target主要用于把Web Service模塊部署到WLS Domain中。wls.deploy是一個在weblogicServer.macrodef中定義的Task,調用WLS的ANT擴展任務wldeploy。
編譯Web Services。
現在我們在ANT View中執行任務build.ws.pojo,可以看到在Console窗口顯示出對應的操作過程。
Buildfile: C:\project\eclipse31\workspace\JSR-181 Web Services\build.xml
clean.jb:
[delete] Deleting directory C:\temp\jb
[mkdir] Created dir: C:\temp\jb
build.jb:
[jwsc] 1 JWS files will be processed.
[jwsc] Processing JWS: C:\project\eclipse31\workspace\JSR-181 Web Services\webservices\jsr181\pojo\StringChanger.java
[jwsc] JWS: C:\project\eclipse31\workspace\JSR-181 Web Services\webservices\jsr181\pojo\StringChanger.java Validated.
[jwsc] Compiling 2 source files to c:\temp\_ukbwfm
[jwsc] C:\TEMP\_ukbwfm\StringChangerPortType.java
[jwsc] C:\project\eclipse31\workspace\JSR-181 Web Services\webservices\jsr181\pojo\StringChanger.java
[jwsc] Building war: C:\temp\jb\StringChanger.war
[jwsc] Created JWS deployment file: C:\temp\jb\StringChanger.war
[AntUtil.deleteDir] Deleting directory c:\temp\_ukbwfm
BUILD SUCCESSFUL
Total time: 22 seconds
打開目錄C:\TEMP\jb,我們能看到生成了兩個文件夾和一個WAR文件。在文件夾META-INF下的 application.xml中的<web-uri>元素的值來自JWS中的注釋@WLHttpTransport。打開生成的WAR文件我們能看WEB-INF路徑下已經生成了一些對應的配置文件。查看其中的WSDL文件名為StringChangerService.wsdl,這也是來自JWS中的注釋@WLHttpTransport。在WSDL文件中能看到targetNamespace為http://wwtt.bea.com,這是來自JWS中的注釋@WebService。同樣我們能在該文件中看到service元素中port為StringChangerPort,也是來自@WebService。在這個文件中包括了兩個operation元素,name分別為toLower和toUpper,對應到JWS中兩個注釋@WebMethod。同時我們能看到對應的style為rpc,use為encoded。這些都符合我們在JWS的@SOAPBinding注釋中的設置。同時我們能看到該WAR的WEB-INF\classes\webservices\jsr181\pojo 目錄中包含兩個class文件:StringChanger.class內是StringChanger.java描述的業務邏輯,StringChangerPortType是為這個類生成的接口。StringChangerPortType會在后面生成Web Services代碼時被自動調用。
public interface StringChangerPortType extends Remote{
public abstract String toLowerCase(String s)
throws RemoteException;
public abstract String toUpper(String s)
throws RemoteException;
}
部署Web Service
我們在ANT View中執行任務deploy.jb,可以看到在Console窗口中顯示對應部署過程。
Buildfile: C:\project\eclipse31\workspace\JSR-181 Web Services\build.xml
check.jb:
deploy.jb:
[wldeploy] weblogic.Deployer -noexit -name WLS v9 JSR-181 Javabean Web Service -source C:\temp\jb -targets AdminServer -adminurl t3://localhost:7001 -user weblogic -password ******** -deploy
[wldeploy] weblogic.Deployer invoked with options: -noexit -name WLS v9 JSR-181 Javabean Web Service -source C:\temp\jb -targets AdminServer -adminurl t3://localhost:7001 -user weblogic -deploy
[wldeploy] <2005-11-28 下午06時12分15秒 CST>
[wldeploy] Task 13 initiated: [Deployer:149026]deploy application WLS v9 JSR-181 Javabean Web Service on AdminServer.
[wldeploy] Task 13 completed: [Deployer:149026]deploy application WLS v9 JSR-181 Javabean Web Service on AdminServer.
[wldeploy] Target state: deploy completed on Server AdminServer
BUILD SUCCESSFUL
Total time: 14 seconds
用瀏覽器打開http://localhost:7001/console/,用weblogic/webogic登錄,在左邊目錄樹的deploy展開能看到已經部署了一個名為“WLS v9 JSR-181 Javabean Web Service”的企業應用(Enterprise Application),狀態為Active。
測試
用瀏覽器打開 http://localhost:7001/jb/StringChangerService?WSDL ,可以看到一個展開的WSDL文件。這個文件的內容和我們前面在WAR中看到的WSDL文件應該是完全一致的。到此我們已經學會了開發一個簡單的基于JavaBean的Web Service應用。
基于JavaBean的Web Service開發測試客戶端
從上面的例子我們已經了解了如何開發,部署及測試一個Web Services模塊,下面我們要學習如何開發一個Web Service客戶端來調用Web Service邏輯。
編寫build.xml Target
<target name="build.jbClient">
<clientgen wsdl="${jbApp.wsdl.url}" destDir="${clients.src.dir}" packageName="${clients.package.name}" />
<javac srcdir="${clients.src.dir}" destdir="${clients.dest.dir}" includes="${clients.package.path}/*.java" debug="on" classpathref="javabuild.class.path" />
</target>
<target name="build.jbDriver">
<javac srcdir="${jbApp.src.dir}" destdir="${clients.dest.dir}" includes="*.java" classpathref="javabuild.class.path" />
</target>
build.jbClient 這個Target主要用于建立一個Web Services模塊的客戶端,其中包含兩個任務。clientgen這個任務可以根據一個WSDL文件生成一組調用該Web Service的客戶端文件。Clientgen的屬性wsdl指定WSDL文件的位置,packageName指定生成的測試代碼的包名。Javac這個任務將生成的客戶端java代碼文件編譯成對應的class文件。
build.jbDriver這個Target主要用于編譯測試類。
生成并編譯客戶端代碼
現在我們在ANT View中執行任務build.jbClient,可以看到在Console窗口顯示出對應的操作過程。
Buildfile: C:\project\eclipse31\workspace\JSR-181 Web Services\build.xml
build.jbClient:
[clientgen] Generating client from http://localhost:7001/jb/StringChangerService?WSDL ...
[clientgen] Getting partner link
[clientgen] Package name is client.test
[clientgen] DestDir is C:\project\eclipse31\workspace\JSR-181 Web Services
[clientgen] class name is StringChangerPort_Stub
[clientgen] service class name is StringChangerService
[clientgen] Porttype name is StringChangerPort
[clientgen] service impl name is StringChangerService_Impl
[javac] Compiling 4 source files to C:\temp
BUILD SUCCESSFUL
Total time: 20 seconds
回到Eclipse的Package Explorer視圖,在“JSR-181 Web Services”上右鍵選Refresh,能看到在項目中增加了一個名為client.test的包。展開這個包能看到里面包含若干JAVA文件,XML文件和WSDL文件。這些文件就是自動生成的客戶端代碼。打開資源管理器到C:\TEMP\client\test,能看到生成的客戶端代碼的class文件。
我們注意到,一共生成了4個類,接口StringChangerPort和其實現類StringChangerPort_Stub是我們在StringChanger類中用@WebService(name="StringChangerPort",......)指定的,用于定義業務方法的參數類型和參數轉換傳輸的方法。接口StringChangerService和其實現類StringChangerService_Impl是我們在StringChanger類中用@WLHttpTransport(......, serviceUri="StringChangerService")中指定的,用于獲得Service連接,定義消息的收發方式。
創建并編譯一個測試類
下面我們創建一個測試類TestDriver_POJO來調用剛才我們創建的Web Service客戶端。和剛才創建Java Bean一樣,在webservices.jsr181.pojo中創建一個類TestDriver_POJO,寫入如下內容:
package webservices.jsr181.pojo;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import client.test.StringChangerPort;
import client.test.StringChangerService;
import client.test.StringChangerService_Impl;
public class TestDriver_POJO {
public static void main(String[] args) throws ServiceException, RemoteException{
String url = "http://localhost:7001/jb/StringChangerService?WSDL";
StringChangerService service = new StringChangerService_Impl(url);
StringChangerPort port = service.getStringChangerPortSoapPort();
String testString = "This is my test String ;-)";
System.out.println("toUpper request: " + testString);
System.out.println("toUpper results: " + port.toUpper(testString));
System.out.println("toLower request: " + testString);
System.out.println("toLower results: " + port.toLower(testString));
}
}
我們能看到,一個JAVA類調用一個Web Service客戶端是非常簡單的。首先通過提供WSDL文件的位置來獲得客戶端類(StringChangerService)以及SOAP接口(StringChangerPort)。然后就可以通過服務名來調用這個SOAP接口提供的各種服務(toUpper和toLower)。
運行測試類觀察結果
因為測試類只是用于測試,簡化起見我們直接運行這個類而不使用ANT。右鍵點這個類的java文件,選擇“run as…=> java application”。這時我們在Console能看到運行結果。如果一切正確:
toUpper request: This is my test String ;-)
toUpper results: THIS IS MY TEST STRING ;-)
toLower request: This is my test String ;-)
toLower results: this is my test string ;-)
到此,我們已經成功創建了一個基于JSR-181的Web Service以及對應客戶端。如果有興趣,可以試著在JWS文件中修改一些代碼和注釋,看看這些代碼和注釋會影響什么。無論如何,這會加深你對JSR-181的理解。
開發基于Session EJB的Web Service
使用基于EJB的Web Servics和基于Javabean的方式類似。我們只需在Bean類中添加一些符合JSR181的注釋,在build.xml中調用WLS提供的擴展ANT Task來完成Web Services。
1. 創建一個EJB。
在Project的根目錄下創建一個類名為PurchaseOrder,包名為webservices.jsr181.ejb,寫入如下內容:
package webservices.jsr181.ejb;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import weblogic.ejbgen.Constants;
import weblogic.ejbgen.FileGeneration;
import weblogic.ejbgen.JndiName;
import weblogic.ejbgen.RemoteMethod;
import weblogic.ejbgen.Session;
import weblogic.jws.WLHttpTransport;
@Session(ejbName = "PurchaseOrderEJB", serviceEndpoint = "webservices.jsr181.ejb.PurchaseOrderPortType")
@JndiName(remote = "PurchaseOrderEJB.Remote")
@FileGeneration(remoteClass = Constants.Bool.TRUE, remoteClassName = "PurchaseOrderRemote", remoteHome = Constants.Bool.TRUE, remoteHomeName = "PurchaseOrderHome")
@WebService(name="PurchaseOrderPort", serviceName="PurchaseOrderService", targetNamespace="http://bea.com /PurchaseOrder")
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT, use=SOAPBinding.Use.LITERAL, parameterStyle=SOAPBinding.ParameterStyle.BARE)
@WLHttpTransport(portName="PurchaseOrderPort", contextPath="ejb", serviceUri="PurchaseOrderService")
public class PurchaseOrder implements SessionBean {
private static final long serialVersionUID = 1L;
public void ejbCreate() {}
@RemoteMethod()
@WebMethod()
public String toUpper(String upperReqString)
{
String upper = upperReqString.toUpperCase();
System.out.println("toUpper Request: " + upperReqString);
System.out.println("toUpper Reply: " + upper);
return(upper);
}
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {}
public void ejbRemove() throws EJBException, RemoteException {}
public void ejbActivate() throws EJBException, RemoteException {}
public void ejbPassivate() throws EJBException, RemoteException {}
}
這個類是我們創建的EJB的Bean類,并通過JSR175方式描述該EJB接口以及生成的Web Service接口。該類中只包含一個public的業務方法:toUpper(String): String,其余都是EJB要求的方法,以及用于描述EJB和Web Service的JSR-175注釋。
先看一些類級別的注釋。和基于Javabean的JWS類似,包含了JSR181定義的三行注釋@WebService(),@SOAPBinding()和@WLHttpTransport()。與JavaBean不同的是這里還包括一些用于生成EJB配置文件和接口的注釋。@Session表示這是一個session bean,屬性ejbName和serviceEndpoint分別表示EJB的名字和接口名。@JndiName()中屬性remote表示這個EJB發布在JNDI上的地址為PurchaseOrderEJB.Remote。@FileGeneration()表示由這個Bean類生成的代碼文件。屬性remoteClass,remoteClassName,remoteHome和remoteHomeName分別指定使用遠程接口和遠程Home接口,并且這兩個接口為PurchaseOrderRemote和PurchaseOrderHome。
在方法級別上,除了和Javabean類似用@WebMethod()聲明暴露的Web Service操作外,用@RemoteMethod()將這個方法指定為發布到遠程接口上的方法。
2. 編寫build.xml Target。
<target name=”build.ejb” depends=”clean.ejb”>
<jwsc srcdir=”${ejbApp.src.dir}” destdir=”${ejbApp.dest.dir}” listfiles=”true” classpathref=”jwsbuild.class.path”>
<jws file=”${ejbApp.jwsSource.file}” />
</jwsc>
</target>
<target name=”deploy.ejb” depends=”check.ejb” if=”ejb.exists”>
<wls.deploy deploy.dir=”${ejbApp.dest.dir}” deploy.name=”${ejbApp.deploy.name}” />
</target>
build.jb和deploy.jb兩個Target主要用于建立一個可部署的Web Services模塊并部署到Domain中。這與前面JavaBean例子使用方式完全一致。
3. 編譯Web Services。
現在我們在ANT View中執行任務build.ejb,可以看到在Console窗口顯示出對應的操作過程。
Buildfile: C:\project\eclipse31\workspace\JSR-181 Web Services\build.xml
clean.ejb:
[delete] Deleting directory C:\temp\ejb
[mkdir] Created dir: C:\temp\ejb
build.ejb:
[jwsc] 1 JWS files will be processed.
[jwsc] Processing JWS: C:\project\eclipse31\workspace\JSR-181 Web Services\webservices\jsr181\ejb\PurchaseOrder.java
[jwsc] JWS: C:\project\eclipse31\workspace\JSR-181 Web Services\webservices\jsr181\ejb\PurchaseOrder.java Validated.
[jwsc] EJBGen 9.0
[jwsc] Creating c:\temp\_f26ur6\PurchaseOrderHome.java
[jwsc] Creating c:\temp\_f26ur6\PurchaseOrderRemote.java
[jwsc] Creating c:\temp\_f26ur6\\ejb-jar.xml
[jwsc] Creating c:\temp\_f26ur6\\weblogic-ejb-jar.xml
[jwsc] Compiling 4 source files to c:\temp\_f26ur6
[jwsc] C:\TEMP\_f26ur6\PurchaseOrderHome.java
[jwsc] C:\TEMP\_f26ur6\PurchaseOrderPortType.java
[jwsc] C:\TEMP\_f26ur6\PurchaseOrderRemote.java
[jwsc] C:\project\eclipse31\workspace\JSR-181 Web Services\webservices\jsr181\ejb\PurchaseOrder.java
[jwsc] Building jar: C:\temp\ejb\PurchaseOrder.jar
[jwsc] Created JWS deployment file: C:\temp\ejb\PurchaseOrder.jar
[AntUtil.deleteDir] Deleting directory c:\temp\_f26ur6
Creating c:\temp\_f26ur6\ejbgen-build.xml
BUILD SUCCESSFUL
Total time: 17 seconds
打開目錄C:\TEMP\ejb,我們能看到生成了兩個文件夾和一個jar文件。在文件夾META-INF下的。打開生成的JAR文件我們能看META-INF路徑下已經生成了一些對應的配置文件。其中大部分和在Javabean中生成的配置文件類似,此外還包括一些與EJB相關的配置文件,比如weblogic-ejb-jar.xml,ejbgen-build.xml和ejb-jar.xml,沒有了與Web應用相關的配置文件weblogic.xml和web.xml
部署Web Service
我們在ANT View中執行任務deploy.ejb,可以看到在Console窗口中顯示對應部署過程。
Buildfile: C:\project\eclipse31\workspace\JSR-181 Web Services\build.xml
check.ejb:
deploy.ejb:
[wldeploy] weblogic.Deployer 每noexit 每name WLS v9 JSR-181 EJB Web Service 每source C:\temp\ejb 每targets AdminServer 每adminurl t3://localhost:7001 每user weblogic 每password ******** -deploy
[wldeploy] weblogic.Deployer invoked with options: -noexit 每name WLS v9 JSR-181 EJB Web Service 每source C:\temp\ejb 每targets AdminServer 每adminurl t3://localhost:7001 每user weblogic 每deploy
[wldeploy] <2005-11-28 狟敁09奀21煦47鏃 CST>
[wldeploy] Task 1 initiated: [Deployer:149026]deploy application WLS v9 JSR-181 EJB Web Service on AdminServer.
[wldeploy] Task 1 completed: [Deployer:149026]deploy application WLS v9 JSR-181 EJB Web Service on AdminServer.
[wldeploy] Target state: deploy completed on Server AdminServer
BUILD SUCCESSFUL
Total time: 7 seconds
用瀏覽器打開http://localhost:7001/console/,用weblogic/webogic登錄,在左邊目錄樹的deploy展開能看到已經部署了一個名為“WLS v9 JSR-181 EJB Web Service”的企業應用(Enterprise Application),狀態為Active。
5. 測試
用瀏覽器打開http://localhost:7001/ejb/StringChangerService?WSDL,可以看到一個展開的WSDL文件。這個文件的內容和我們前面在JAR中看到的WSDL文件應該是完全一致的。
為基于Session EJB的Web Service開發測試客戶端
和JavaBean一樣,我們可以為這個基于Session Bean的Web Service創建一個客戶端,并用來測試。
1. 編寫build.xml Target
<target name="build.ejbClient">
<clientgen wsdl="${ejbApp.wsdl.local}" destDir="${clients.src.dir}" packageName="${clients.package.name}"/>
<javac srcdir="${clients.src.dir}" destdir="${clients.dest.dir}" includes="${clients.package.path}/*.java" debug="on" classpathref="javabuild.class.path" />
</target>
<target name="build.ejbDriver">
<javac srcdir="${ejbApp.src.dir}" destdir="${clients.dest.dir}" includes="*.java" classpathref="javabuild.class.path" />
</target>
build.jbClient 與build.ejbDriver和Javabean中的對應目標也類似。唯一區別的是在clientgen任務中使用的WSDL文件不是來自URL,而是來自build.ejb生成的JAR包。使用local或URL方式對其他客戶端代碼沒有影響,基本這兩種方式可以互換使用。
2. 生成并編譯客戶端代碼
現在我們在ANT View中執行任務build.jbClient,可以看到在Console窗口顯示出對應的操作過程。
Buildfile: C:\project\eclipse31\workspace\JSR-181 Web Services\build.xml
build.ejbClient:
[clientgen] Generating client from jar:file:C:\temp/ejb/PurchaseOrder.jar!/META-INF/PurchaseOrderService.wsdl …
[clientgen] Getting partner link
[clientgen] Package name is client.test
[clientgen] DestDir is C:\project\eclipse31\workspace\JSR-181 Web Services
[clientgen] class name is PurchaseOrderPort_Stub
[clientgen] service class name is PurchaseOrderService
[clientgen] Porttype name is PurchaseOrderPort
[clientgen] service impl name is PurchaseOrderService_Impl
[javac] Compiling 4 source files to C:\temp
BUILD SUCCESSFUL
Total time: 11 seconds
回到Package Explorer視圖的包client.test。能看到里面又增加了若干JAVA文件,XML文件和WSDL文件。這些文件就是自動生成的客戶端代碼。打開資源管理器到C:\TEMP\client\test,能看到生成的客戶端代碼的class文件。
我們注意到,一共生成了4個類,StringChangerPort和StringChangerPort_Stub是我們在StringChanger類中用@WebService(name="StringChangerPort",......)指定的。StringChangerService和StringChangerService_Impl是我們在StringChanger類中用@WLHttpTransport(......, serviceUri=”StringChangerService”)中指定的。
3. 創建并編譯一個測試類
下面我們在webservices.jsr181.ejb中創建一個類TestDriver_EJB,寫入如下內容:
package webservices.jsr181.ejb;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import client.test.PurchaseOrderPort;
import client.test.PurchaseOrderService;
import client.test.PurchaseOrderService_Impl;
public class TestDriver_EJB
{
public static void main(String[] args)
throws ServiceException, RemoteException{
String url = “http://localhost:7001/ejb/PurchaseOrderService?WSDL”;
PurchaseOrderService service = new PurchaseOrderService_Impl(url);
PurchaseOrderPort port = service.getPurchaseOrderPort();
String testString = “This is my test String ;-)”;
System.out.println(port.toUpper(testString));
}
}
這里面的內容和在Javabean中也沒什么區別。因此我們可以看出來,在Web Service后端使用什么方式實現,在前端看是完全透明的。
4. 運行測試類觀察結果
右鍵點文件TestDriver_EJB.java,選擇“run as…=> java application”。這時我們在Console能看到運行結果。如果一切正確:
THIS IS MY TEST STRING ;-)
到此,我們完成了這個基于EJB的Web Services的例子。事實上我們可以用各種方法創建Web Services的業務邏輯,從而輕松的實現系統組件間的松耦合。
原文轉自:http://www.anti-gravitydesign.com