我们有一个项目可以创建一个包含JPA实体和服务类的jar文件来访问数据库。我们有许多不同的应用程序需要使用这个jar文件。我们希望将JPA jar文件部署为ejb-jar,让其他应用程序通过战争中包含的客户端jar文件来使用它。
与实体类一起,我们的JPA项目有一个通用服务接口,定义如下:
public interface GenericService {
<T> T create(T t) throws Exception;
<T> T find(Class<T> t, Object id) throws Exception;
<T> T update(T t);
List<?> findWithNamedQuery(String queryName) throws Exception;
List<?> findWithNamedQuery(String queryName, int resultLimit) throws Exception;
List<?> findWithNamedQuery(String namedQueryName, Map<String, Object> parameters) throws Exception;
List<?> findWithNamedQuery(String namedQueryName, Map<String, Object> parameters, int resultLimit) throws Exception;
<T> List<T> findWithNativeQueryListResult(String sql, Class<T> type) throws IllegalArgumentException;
<T> List<T> findWithNativeQueryListResult(String sql) throws IllegalArgumentException;
<T> T findWithNativeQuerySingleResult(String sql, Class<T> type) throws IllegalArgumentException;
<T> T findWithNativeQuerySingleResult(String sql) throws IllegalArgumentException;
}
在无状态会话bean中实现:
@Stateless
@EJB(name = "java:global/DataService", beanName = "DataService", beanInterface = DataService.class)
@Local
public class DataService implements GenericService {
@PersistenceContext(unitName = "database")
private EntityManager em;
protected EntityManager getEntityManager() {
return this.em;
}
@Override
public <T> T create(T t) throws IllegalArgumentException, EntityExistsException, PersistenceException {
em.persist(t);
return t;
}
.... etc ....
}
我们将Maven用于构建并将其设置为生成客户端jar:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<!-- this is false by default -->
<generateClient>true</generateClient>
<ejbVersion>3.1</ejbVersion>
</configuration>
</plugin>
并设置了一个空的ejb-jar.xml文件:
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.1" metadata-complete="false">
<enterprise-beans>
</enterprise-beans>
</ejb-jar>
生成的客户端文件在我们的war项目中用作依赖项:
<dependency>
<groupId>my.package</groupId>
<artifactId>data-model</artifactId>
<version>1.0</version>
<classifier>client</classifier>
</dependency>
当我们部署ejb-jar和war文件时,所有看起来都没问题。当我们尝试从war应用程序访问服务/实体类时,我们得到:
[#|2014-06-02T11:14:34.323-0600|WARNING|glassfish3.1.2|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=276;_ThreadName=Thread-6;|javax.ejb.EJBTransactionRolledbackException
at com.sun.ejb.containers.BaseContainer.mapLocal3xException(BaseContainer.java:2314)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2096)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
at com.sun.proxy.$Proxy133.createBatch(Unknown Source)
at my.package.app1.__EJB31_Generated__BatchProcessor__Intf____Bean__.createBatch(Unknown Source)
at my.package.app1.BatchRestService.createBatch(BatchRestService.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
... snip ...
Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean: java.lang.NoSuchMethodError: my.package.datamodel.entity.Batch.__jr_selector__(I[Ljava/lang/Object;)Ljava/lang/Object;
at com.sun.ejb.containers.BaseContainer.checkExceptionClientTx(BaseContainer.java:5074)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4906)
at com.sun.ejb.containers.StatefulSessionContainer.postInvokeTx(StatefulSessionContainer.java:1648)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
... 78 more
Caused by: java.lang.NoSuchMethodError: my.package.datamodel.entity.Batch.__jr_selector__(I[Ljava/lang/Object;)Ljava/lang/Object;
at my.package.app1.BatchProcessor.createBatch(BatchProcessor.java:394)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:4180)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5368)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5348)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:214)
... 76 more
显然,我们的Batch实体类__jr_selector__
上没有定义任何方法,所以它来自哪里?我该如何调试呢?
关于我们如何设置ejb-jar和/或使用它的战争的任何建议也将受到赞赏。
我们正在部署到Glassfish 3.1.2.2服务器。