在不同的项目中分离Java EE组件

时间:2014-02-22 07:37:56

标签: jpa jar ejb

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

我想将我的jpa实体,ejbs和Web客户端分成不同的项目

所以我开发了四个不同的项目,并在他们自己的罐子/战争中编译它们

  1. DomainEntities - 包含我的JPA实体
  2. RemoteInterface - 包含远程接口(我试图将实现分开)
  3. RemoteEJB - 从RemoteInterface(项目2)
  4. 实现接口
  5. WebApp客户端(我有一个调用RemoteInterface来测试ejb是否正常工作的servlet)
  6. 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文件标签时,ejb无法部署到服务器,所以我对它进行评论。

    调用的servlet使用ejb是:

    @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].
    

1 个答案:

答案 0 :(得分: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序列化所有对象以通过网络发送它们。