
在企业级java应用开发中,将业务逻辑封装为ejb,并通过jax-ws暴露为web服务是一种常见模式。为了更好地管理和部署这些组件,通常会将它们打包到一个ear文件中。本教程将以一个典型的多模块maven项目为例,演示如何配置项目、解决部署时可能遇到的类加载问题,并最终成功访问web服务。
一个典型的EJB与JAX-WS集成项目通常包含以下Maven模块:
以下是相关pom.xml文件的关键配置片段,展示了这些模块之间的依赖关系:
1. 父项目 pom.xml (myapp-app)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.myapp</groupId>
<artifactId>myapp-app</artifactId>
<packaging>pom</packaging>
<version>0.1.0</version>
<modules>
<module>myapp-ejb</module>
<module>myapp-web</module>
<module>myapp-ear</module>
<module>myapp-ws</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<version.server.bom>18.0.1.Final</version.server.bom>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-jakartaee8-with-tools</artifactId>
<version>${version.server.bom}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myapp-ejb</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myapp-ws</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- ... 其他配置 ... -->
</project>2. EAR项目 pom.xml (myapp-ear)
EAR项目负责将WAR和EJB打包。请确保在dependencies中正确引用了EJB和Web服务模块。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.myapp</groupId>
<artifactId>myapp-ear</artifactId>
<packaging>ear</packaging>
<version>0.1.0</version>
<name>myapp-ear</name>
<parent>
<groupId>org.myapp</groupId>
<artifactId>myapp-app</artifactId>
<version>0.1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myapp-ejb</artifactId>
<type>ejb</type>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myapp-ws</artifactId>
<type>war</type>
<version>0.1.0</version> <!-- 明确版本,或继承自父pom -->
</dependency>
</dependencies>
<!-- ... 其他配置,如maven-ear-plugin ... -->
</project>3. Web服务项目 pom.xml (myapp-ws)
Web服务模块需要EJB接口来进行编译和类型检查,但在运行时,EJB实例将由容器提供。因此,将EJB模块的依赖范围设置为provided是关键,这可以避免将EJB JAR重复打包到WAR中,并依赖EAR容器的类加载机制。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.myapp</groupId>
<artifactId>myapp-ws</artifactId>
<packaging>war</packaging>
<version>0.1.0</version>
<name>myapp-ws Maven Soap WS</name>
<parent>
<groupId>org.myapp</groupId>
<artifactId>myapp-app</artifactId>
<version>0.1.0</version>
</parent>
<dependencies>
<!-- ... 其他依赖 ... -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myapp-ejb</artifactId>
<type>ejb</type>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- ... 其他配置 ... -->
</project>在WildFly中,当一个WAR包部署在EAR内部时,它通常可以访问EAR中其他模块(如EJB JAR)的类。然而,有时会遇到java.lang.NoClassDefFoundError或java.lang.ClassNotFoundException,特别是在Web服务模块尝试通过反射获取EJB接口信息时。错误信息通常类似:
WFLYSRV0153: Failed to process phase POST_MODULE of deployment "myapp-ws.war" Caused by: java.lang.RuntimeException: WFLYSRV0177: Error getting reflective information for class org.ws.MyAppWSImpl with ClassLoader ModuleClassLoader for Module "deployment.myapp-ws.war" Caused by: java.lang.NoClassDefFoundError: Lorg/myapp/MyAppStatelessLocal; Caused by: java.lang.ClassNotFoundException: org.myapp.MyAppStatelessLocal from [Module "deployment.myapp-ws.war"]
这表明尽管myapp-ejb被包含在EAR中,但myapp-ws.war的类加载器在部署阶段未能找到MyAppStatelessLocal接口。为了明确告知WildFly myapp-ws.war依赖于myapp-ejb.jar,可以在myapp-ws.war的WEB-INF/目录下添加一个jboss-deployment-structure.xml文件。
1. 创建 jboss-deployment-structure.xml
在myapp-ws项目的src/main/webapp/WEB-INF/目录下创建或编辑jboss-deployment-structure.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<!-- 明确声明对EAR内部EJB模块的依赖 -->
<module name="deployment.myapp-ear.ear.myapp-ejb.jar" />
</dependencies>
</deployment>
</jboss-deployment-structure>这里的module name格式deployment.<ear-name>.ear.<ejb-jar-name>是WildFly中引用EAR内部子部署的约定。这会确保myapp-ws.war的类加载器能够正确地访问myapp-ejb.jar中的类。
2. Web服务实现 (MyAppWSImpl.java)
Web服务实现类通过@EJB注解注入EJB,这是Java EE规范的标准做法。
package myapp.ws;
import javax.ejb.EJB;
import javax.jws.WebMethod;
import javax.jws.WebService;
import myapp.lab.MyAppStatelessLocal; // 确保导入EJB接口
@WebService(endpointInterface = "myapp.ws.MyAppWS")
public class MyAppWSImpl implements MyAppWS {
@EJB
MyAppStatelessLocal masl; // 注入EJB本地接口
@WebMethod()
public String predict(int value) {
return masl.getPrediction(value);
}
}3. Web服务配置 (web.xml)
web.xml用于配置Servlet和Servlet映射,JAX-WS服务通常通过Servlet暴露。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>myapp-ws</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>myappws</servlet-name>
<servlet-class>myapp.ws.MyAppWSImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myappws</servlet-name>
<url-pattern>/myappws</url-pattern>
</servlet-mapping>
</web-app>这里的<servlet-mapping>定义了Web服务的访问路径,这对于后续访问WSDL至关重要。
在成功部署EAR文件到WildFly服务器后,Web服务即可通过HTTP协议访问。为了获取Web服务的WSDL(Web Services Description Language)定义,需要使用正确的URL。
根据web.xml中定义的<servlet-mapping>,Web服务的访问路径是/myappws。因此,正确的WSDL访问URL应为:
http://localhost:8080/myapp-ws/myappws?wsdl
注意事项:
错误地使用服务实现类名(例如http://localhost:8080/myapp-ws/MyAppWSImpl?wsdl)将无法获取WSDL,因为JAX-WS运行时通常根据web.xml中的Servlet映射来暴露WSDL,而不是直接基于实现类名。
在WildFly中集成EJB与JAX-WS并将其打包到EAR中,需要细致的Maven配置和对Java EE类加载机制的理解。
遵循这些步骤和最佳实践,可以有效地在WildFly环境中构建和部署健壮的企业级Web服务应用。
以上就是在WildFly中集成EJB与JAX-WS:解决部署与访问难题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号