【问题标题】:Separating Java EE components in different projects在不同项目中分离 Java EE 组件
【发布时间】:2014-02-22 07:37:55
【问题描述】:

我正在尝试学习如何分离 Java EE 组件。

我想将我的 jpa 实体、ejb 和 Web 客户端分离到不同的项目中

所以我开发了四个不同的项目并将它们编译到自己的 jars/wars 中

  1. DomainEntities - 包含我的 JPA 实体
  2. RemoteInterface - 包含远程接口(我正在尝试分离实现)
  3. RemoteEJB - 从 RemoteInterface 实现接口(项目 2)
  4. WebApp 客户端(我有一个调用 RemoteInterface 来测试 ejb 是否工作的 servlet)

DomainEntities 的 jar 结构是

DomainEntities
      -META-INF
          -MANIFEST.MF
      -entities
          -Student.class

RemoteEJB的jar结构是

RemoteEJB
      -META-INF
           -MANIFEST.MF
           -persistence.xml
      -sample
            MyStatelessBean.class

RemoteEJB中的persistence.xml是(根据网上搜索):

<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="RemoteEJBPU" transaction-type="JTA"><provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/pwucdb</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <!--<jar-file>DomainEntities.jar</jar-file>-->
  </persistence-unit>

</persistence>

jta 数据源在我的 glassfish 服务器中定义。 exclude-unlisted-classes 和 jar-file 标签基于我对在不同 jar 上分离 jpa 实体的研究。当我取消注释jar-file标签时,ejb无法部署到服务器,所以我注释它。

调用使用ejb的servlet是:

@WebServlet(name = "NewServlet", urlPatterns = {"/NewServlet"})
public class NewServlet extends HttpServlet {

    @EJB
    private MyRemoteInterface myRemoteInterface;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            out.println(myRemoteInterface.getMessage());
            out.println("Num of records retrived: " + myRemoteInterface.getStudents().size());
        }
    }


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }


    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

}

当我尝试访问 servlet 时出现此警告/错误

WARNING: The collection of metamodel types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element
WARNING: A system exception occurred during an invocation on EJB MyStatelessBean method public java.util.List sample.MyStatelessBean.getStudents()
javax.ejb.EJBException
.....
Caused by: java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Error compiling the query [SELECT s FROM Student s]. Unknown entity type [Student].
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1477)

如果我注释掉 exclude-unlisted-classes 标记,取消注释 jar-file 标记并部署。我收到此服务器警告:

 a jar-file [DomainEntities.jar] specified in persistence.xml is not found
 The server also looked for a file called [...\build\DomainEntities_jar].

【问题讨论】:

    标签: jpa jar ejb


    【解决方案1】:

    我建议将 JAR 和 WAR 捆绑到 EAR-Archive 中。 如果您使用 maven,您可以将此插件添加到 EAR 的 pom:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ear-plugin</artifactId>
        <version>2.8</version>
        <configuration>
            <version>6</version>
            <encoding>${project.build.sourceEncoding}</encoding>
            <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
            <fileNameMapping>no-version</fileNameMapping>
            <displayName>${project.artifactId}</displayName>
            <modules>
                <jarModule>
                    <groupId>${project.groupId}</groupId>
                    <artifactId>domain</artifactId>
                </jarModule>
                <ejbModule>
                    <groupId>${project.groupId}</groupId>
                    <artifactId>ejb</artifactId>
                </ejbModule>
            </modules>
        </configuration>
    </plugin>
    

    因此,EAR 的所有库都将被复制到 /APP-INF/lib 中。 在这个范围内,它现在可以从 EJB 视图中访问。就这样称呼它:

    <jar-file>APP-INF/lib/domain.jar</jar-file>
    

    注意

    <fileNameMapping>no-version</fileNameMapping>
    

    如果您想经常更改域存档的版本,这一点非常重要,否则您必须一直编辑 EJB 的 persistence.xml ;)

    一些补充:

    如果您将所有内容捆绑到 EAR-Archive 中,则不再需要使用远程接口。你只需要本地接口。这是一件好事,因为通过远程接口访问 EJB 比使用本地接口访问它们要慢得多。那是因为 Java 序列化所有对象以通过网络发送它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-05
      • 2021-03-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      相关资源
      最近更新 更多