使用 ant 让 JAX-WS 客户端在 Weblogic 9.2 上工作
最近,我在尝试在 Weblogic 9.2 上部署 JAX-WS Web 服务客户端时遇到了很多问题。事实证明,没有关于如何实现这一目标的简单指南,因此我决定整理这个简短的 wiki 条目,希望对其他人有用。
首先,Weblogic 9.2 一般不支持使用 JAX-WS 的 Web 服务。它附带了旧版本的 XML 相关 java 库,与最新的 JAX-WS 不兼容(Axis2 也出现类似问题,只有 Axis1 似乎可以完美地与 Weblogic 9.x 一起工作,但这是一个非常旧且不受支持的库)。
因此,为了使其正常工作,需要进行一些黑客攻击。我就是这样做的(请注意,我们在遗留企业项目中使用 ant,您可能应该使用 Maven,它应该消除下面 50% 的步骤):
1.从 https://jax-ws.dev.java.net/ (我得到的确切版本是JAXWS2.2-20091203.zip)
2.将 JAX-WS jar 及其依赖项放在单独的文件夹中,例如 lib/webservices。
3. 在 ant 中创建一个模式集来引用这些 jar:
<?xml version="1.0"?>
<patternset id="jaxws.classpath">
<include name="webservices/jsr173_api.jar" />
<include name="webservices/jsr181-api.jar" />
<include name="webservices/jaxb-api.jar" />
<include name="webservices/jaxb-impl.jar" />
<include name="webservices/jaxb-xjc.jar" />
<include name="webservices/jaxws-tools.jar" />
<include name="webservices/jaxws-rt.jar" />
<include name="webservices/jaxws-api.jar" />
<include name="webservices/policy.jar" />
<include name="webservices/woodstox.jar" />
<include name="webservices/streambuffer.jar" />
<include name="webservices/stax-ex.jar" />
<include name="webservices/saaj-api.jar" />
<include name="webservices/saaj-impl.jar" />
<include name="webservices/gmbal-api-only.jar" />
</patternset>
4. 将模式集包含在您的 WAR 相关目标中。这可能看起来像:(
<?xml version="1.0"?>
<copy todir="${wardir.lib}" includeEmptyDirs="false" flatten="true">
<fileset dir="${libs}">
<!--lots of libs here, related to your project -->
<patternset refid="jaxws.classpath"/>
</fileset>
</copy>
不是 flatten="true" 参数 - 这很重要,因为默认情况下 Weblogic 9.x 不够智能,无法访问位于与 WEB-INF/lib 不同的位置的 jar在您的 WAR 文件中)
5.如果发生冲突,Weblogic 默认使用自己的 jar。我们希望它使用我们应用程序中的 JAX-WS jar。这是通过准备一个 weblogic-application.xml 文件并将其放置在部署的 EAR 文件的 META-INF 文件夹中来实现的。它应该如下所示:
<?xml version="1.0"?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<prefer-application-packages>
<package-name>javax.jws.*</package-name>
<package-name>javax.xml.bind.*</package-name>
<package-name>javax.xml.crypto.*</package-name>
<package-name>javax.xml.registry.*</package-name>
<package-name>javax.xml.rpc.*</package-name>
<package-name>javax.xml.soap.*</package-name>
<package-name>javax.xml.stream.*</package-name>
<package-name>javax.xml.ws.*</package-name>
<package-name>com.sun.xml.api.streaming.*</package-name>
</prefer-application-packages>
</weblogic-application>
6.记住将 weblogic-application.xml 文件放入您的 EAR 中! ant 的目标可能类似于:
<?xml version="1.0"?>
<target name="build-ear" depends="war, manifest">
<delete dir="${dist}"/>
<mkdir dir="${dist}"/>
<jar destfile="${warfile}" basedir="${wardir}"/>
<ear destfile="${earfile}" appxml="resources/${app.name}/application.xml">
<fileset dir="${dist}" includes="${app.name}.war"/>
<metainf dir="resources/META-INF"/>
</ear>
</target>
7.此外,您还需要告诉 weblogic 更喜欢您的 WEB-INF 类而不是分发中的类。您可以通过将以下几行放入 WEB-INF/weblogic.xml 文件中来完成此操作:
<?xml version="1.0"?>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
8. 这就是与 weblogic 相关的配置。现在只需设置您的 JAX-WS 目标。下面的示例将根据本地部署的 WSDL 文件简单地生成 Web 服务存根和类,并将它们放在应用程序的文件夹中:
<?xml version="1.0"?>
<target name="generate-jaxws-client">
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath path="classpath.main"/>
</taskdef>
<wsimport
destdir="${src}"
package="acme.somewhere.in.your.package.tree.webservices."
keep="true"
wsdl="http://localhost:8088/mockWebService?WSDL">
</wsimport>
</target>
记住 keep="true" 参数。没有它,wsimport 会生成类并...删除它们,无论您相信与否!
为了模拟 Web 服务,我建议使用 SOAPUI(一个开源项目)。非常易于部署,对于 Web 服务集成测试至关重要。
9.我们快到了。最后一件事是编写一个 Java 类来测试 Web 服务,尝试首先将其作为独立应用程序运行(或作为单元测试的一部分)
10.然后尝试在 Weblogic 中运行相同的代码。它应该有效。这对我有用。经过大约3天的沮丧。 是的,我知道我应该将 9 和 10 放在一个要点下,但是标题“使用 ant 在 Web 逻辑 9.2 下部署 JAX-WS Web 服务的 10 个步骤”听起来好多了。
如果您发现缺少内容,请编辑这篇文章并进行改进!
I've recently had lots of issues trying to deploy a JAX-WS web servcie client on Weblogic 9.2. It turns out there is no straightforward guide on how to achieve this, so I decided to put together this short wiki entry hoping it might be useful for others.
Firstly, Weblogic 9.2 does not support web servcies using JAX-WS in general. It comes with old versions of XML-related java libraries that are incompatible with the latest JAX-WS (similar issues occur with Axis2, only Axis1 seems to be working flawlessly with Weblogic 9.x but that's a very old and unsupported library).
So, in order to get it working, some hacking is required. This is how I did it (note that we're using ant in our legacy corporate project, you probably should be using maven which should eliminate 50% of those steps below):
1.Download the most recent JAX-WS distribution from https://jax-ws.dev.java.net/ (The exact version I got was JAXWS2.2-20091203.zip)
2.Place the JAX-WS jars with the dependencies in a separate folder like lib/webservices.
3.Create a patternset in ant to reference those jars:
<?xml version="1.0"?>
<patternset id="jaxws.classpath">
<include name="webservices/jsr173_api.jar" />
<include name="webservices/jsr181-api.jar" />
<include name="webservices/jaxb-api.jar" />
<include name="webservices/jaxb-impl.jar" />
<include name="webservices/jaxb-xjc.jar" />
<include name="webservices/jaxws-tools.jar" />
<include name="webservices/jaxws-rt.jar" />
<include name="webservices/jaxws-api.jar" />
<include name="webservices/policy.jar" />
<include name="webservices/woodstox.jar" />
<include name="webservices/streambuffer.jar" />
<include name="webservices/stax-ex.jar" />
<include name="webservices/saaj-api.jar" />
<include name="webservices/saaj-impl.jar" />
<include name="webservices/gmbal-api-only.jar" />
</patternset>
4.Include the patternset in your WAR-related goal. This could look something like:
<?xml version="1.0"?>
<copy todir="${wardir.lib}" includeEmptyDirs="false" flatten="true">
<fileset dir="${libs}">
<!--lots of libs here, related to your project -->
<patternset refid="jaxws.classpath"/>
</fileset>
</copy>
(not the flatten="true" parameter - it's important as Weblogic 9.x is by default not smart enough to access jars located in a different lcoation than WEB-INF/lib inside your WAR file)
5.In case of clashes, Weblogic uses its own jars by default. We want it to use the JAX-WS jars from our application instead. This is achieved by preparing a weblogic-application.xml file and placing it in META-INF folder of the deplotyed EAR file. It should look like this:
<?xml version="1.0"?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<prefer-application-packages>
<package-name>javax.jws.*</package-name>
<package-name>javax.xml.bind.*</package-name>
<package-name>javax.xml.crypto.*</package-name>
<package-name>javax.xml.registry.*</package-name>
<package-name>javax.xml.rpc.*</package-name>
<package-name>javax.xml.soap.*</package-name>
<package-name>javax.xml.stream.*</package-name>
<package-name>javax.xml.ws.*</package-name>
<package-name>com.sun.xml.api.streaming.*</package-name>
</prefer-application-packages>
</weblogic-application>
6.Remember to place that weblogic-application.xml file in your EAR! The ant goal for that may look similar to:
<?xml version="1.0"?>
<target name="build-ear" depends="war, manifest">
<delete dir="${dist}"/>
<mkdir dir="${dist}"/>
<jar destfile="${warfile}" basedir="${wardir}"/>
<ear destfile="${earfile}" appxml="resources/${app.name}/application.xml">
<fileset dir="${dist}" includes="${app.name}.war"/>
<metainf dir="resources/META-INF"/>
</ear>
</target>
7.Also you need to tell weblogic to prefer your WEB-INF classes to those in distribution. You do that by placing the following lines in your WEB-INF/weblogic.xml file:
<?xml version="1.0"?>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
8.And that's it for the weblogic-related configuration. Now only set up your JAX-WS goal. The one below is going to simply generate the web service stubs and classes based on a locally deployed WSDL file and place them in a folder in your app:
<?xml version="1.0"?>
<target name="generate-jaxws-client">
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath path="classpath.main"/>
</taskdef>
<wsimport
destdir="${src}"
package="acme.somewhere.in.your.package.tree.webservices."
keep="true"
wsdl="http://localhost:8088/mockWebService?WSDL">
</wsimport>
</target>
Remember about the keep="true" parameter. Without it, wsimport generates the classes and... deletes them, believe it or not!
For mocking a web service I suggest using SOAPUI, an open source project. Very easy to deploy, crucial for web servcies intergation testing.
9.We're almost there. The final thing is to write a Java class for testing the web service, try to run it as a standalone app first (or as part of your unit tests)
10.And then try to run the same code from withing Weblogic. It should work. It worked for me. After some 3 days of frustration.
And yes, I know I should've put 9 and 10 under a single bullet-point, but the title "10 steps to deploy a JAX-WS web service under Web logic 9.2 using ant" sounds just so much better.
Please, edit this post and improve it if you find something missing!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这并不是一个真正的问题,而是一个指南,所以我自己回答它只是为了将其标记为已完成。
This is not really a question but a guide so I'm answering it myself just to mark it as done.
在 Weblogic 9.2 上处理 Web 服务的另一种方法是使用 Apache CXF。这与 Spring 集成得特别好,因为每个 Web 服务都作为一个 bean 公开,并且实际的类甚至不需要知道它们是 Web 服务,它都是配置驱动的。
有关在 Weblogic 上设置 Apache CXF 的精彩指南可以在这里找到:http:// /wheelersoftware.com/articles/spring-cxf-web-services.html
这也适用于 Weblogic 9.2,如果您需要公开 Web 服务,而不仅仅是连接到现有服务,那么这是迄今为止比使用普通的 JAXWS(CXF 无论如何都使用它)。
Another way of dealing with web services on Weblogic 9.2 is using Apache CXF. This particularly well integrates with Spring as each web service is exposed as a bean and the actual classes don't even need to know that they are web services, it's all configuration driven.
A great guide about setting up Apache CXF on Weblogic can be found here: http://wheelersoftware.com/articles/spring-cxf-web-services.html
This works on Weblogic 9.2 as well and if you need to expose web services, not just connect to existing ones, this is by far better approach than using plain JAXWS (which is used by CXF anyway).