【发布时间】:2016-01-26 07:15:33
【问题描述】:
我有三个蓝图包(不同的罐子):
- ap-data:只包含一个名为 Game.java 的类,应该用作 DTO。它是一个实体,带有 @Entity 注释。
- ap-dao:一个持久性捆绑包,包含 persistence.xml、OSGI 清单中的 Meta-Persistence 标头,并从 ap-data 导入 Game.java。
- ap-service:同样从ap-data导入Game.java和ap-dao暴露的接口IGameDAO.java。它还公开了 IGameService.java。
意识到这些捆绑包构成了模块游戏的层。场景:
- 所有包都在 Karaf 3.0.5 中正确部署(都是“活动”)。
- ap-dao 包被正确加载为持久包,可以访问配置的数据源,并且可以毫无问题地访问 EntityManager。它可以执行查询,我可以看到结果。一切都很好。
- ap-service 可以毫无问题地注入 IGameDAO 的实例。到这里为止一切都很好。
- Game.java (DTO) 类仅包含在 ap-data 包中。没有重复(我检查过)。
问题:
GameServiceImpl 中的 Game typed 由 ap-service 包类加载器加载,而 IGameDAO 服务返回的实例属于另一种类型因为它们是由 ap-dao 包类加载器加载的,因此会生成 ClassCastException。意识到这个类是相同的 (app.Game.java) ,应该是一个 DTO。 DTO 是我必须能够使用并通过捆绑(通过服务)传递它们的基本对象。在 OSGI 中如何处理 DTO?我该如何解决这个问题?
// code in GameServiceImpl, from ap-service bundle
public void prettyPrintGames() {
List<Game> games = gameDao().findAll();
/* ClassCastException in the for-loop, since the type Game, in ap-service
* is not the same of the instances of varible 'games',
* returned by the DAO service instance. This is the reason
* of the classloader issue.
*/
for(Game g : games){
System.out.println(g.toString());
}
}
结构:
应用数据
+---ap-data
| | pom.xml
| |
| +---src
| | \---main
| | +---java
| | | \---br
| | | \---com
| | | \---company
| | | \---game
| | | \---entity
| | | Game.java
捆绑清单:
Manifest-Version: 1.0
Bnd-LastModified: 1445945039034
Build-Jdk: 1.7.0_07
Built-By: user
Bundle-Description: ap-data
Bundle-ManifestVersion: 2
Bundle-Name: ap-data
Bundle-SymbolicName: ap-data
Bundle-Version: 1.0.0
Created-By: Apache Maven Bundle Plugin
Export-Package: br.com.company.game.entity;version="1.0.0";uses:="javax.
persistence"
Import-Package: javax.persistence;version="[2.1,3)"
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.7))"
Tool: Bnd-3.0.0.201509101326
ap-dao
+---ap-dao
| | pom.xml
| +---src
| | \---main
| | +---java
| | | \---br
| | | \---com
| | | \---company
| | | \---game
| | | \---dao
| | | +---api
| | | | IGameDAO.java
| | | |
| | | \---impl
| | | GameDAOImpl.java
| | |
| | \---resources
| | +---META-INF
| | | persistence.xml
| | |
| | \---OSGI-INF
| | \---blueprint
| | blueprint.xml
| |
捆绑清单
Manifest-Version: 1.0
Bnd-LastModified: 1445945039855
Build-Jdk: 1.7.0_07
Built-By: user
Bundle-Blueprint: OSGI-INF/blueprint/blueprint.xml
Bundle-Description: game-module
Bundle-ManifestVersion: 2
Bundle-Name: ap-dao
Bundle-SymbolicName: ap-dao
Bundle-Version: 1.0.0
Created-By: Apache Maven Bundle Plugin
Export-Package: br.com.company.game.dao.api;version="1.0.0";uses:="br.co
m.company.game.entity"
Export-Service: br.com.company.game.dao.api.IGameDAO
Import-Package: br.com.company.game.dao.api;version="[1.0,2)",br.com.com
pany.game.entity;version="[1.0,2)",javax.persistence;version="[2.1,3)",
org.osgi.service.blueprint;version="[1.0.0,2.0.0)"
Meta-Persistence: META-INF/persistence.xml
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.7))"
Tool: Bnd-3.0.0.201509101326
ap-服务
+---ap-service
| | pom.xml
| |
| +---src
| | \---main
| | +---java
| | | \---br
| | | \---com
| | | \---company
| | | \---game
| | | \---service
| | | +---api
| | | | IGameService.java
| | | |
| | | \---impl
| | | GameServiceImpl.java
| | |
| | \---resources
| | \---OSGI-INF
| | \---blueprint
| | service.xml
| |
捆绑清单
Manifest-Version: 1.0
Bnd-LastModified: 1445945040469
Build-Jdk: 1.7.0_07
Built-By: user
Bundle-Blueprint: OSGI-INF/blueprint/service.xml
Bundle-Description: game-module
Bundle-ManifestVersion: 2
Bundle-Name: ap-service
Bundle-SymbolicName: ap-service
Bundle-Version: 1.0.0
Created-By: Apache Maven Bundle Plugin
Export-Package: br.com.company.game.service.api;version="1.0.0"
Export-Service: br.com.company.game.service.api.IGameService
Import-Package: br.com.company.game.dao.api;version="[1.0,2)",br.com.com
pany.game.entity;version="[1.0,2)",br.com.company.game.service.api;vers
ion="[1.0,2)",org.osgi.service.blueprint;version="[1.0.0,2.0.0)"
Import-Service: br.com.company.game.dao.api.IGameDAO;multiple:=false
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.7))"
Tool: Bnd-3.0.0.201509101326
分析:
我在 ap-dao 中进行了一些测试,然后才意识到如果我返回实体而不通过 EntityManager,创建硬编码的对象,例如,一切正常。一旦我使用 entityManager 查询实体,问题又回来了,我得到 ClassCastException。
private EntityManager entityManager;
@SuppressWarnings("unchecked")
@Override
public List<Game> findAll() {
return _findAllHardCoded(); // this work just fine in service layer, no ClassCastException
return entityManager.createQuery("SELECT s FROM Game s").getResultList(); // if I use this, ClassCastException is generated in the service layer
}
protected List<Game> _findAllHardCoded() {
List<Game> games = new ArrayList<Game>();
games.add(new Game(Short.valueOf("1"), "Game1"));
games.add(new Game(Short.valueOf("2"), "Game2"));
return games;
}
【问题讨论】:
-
Christian Christian Schneider 能否提供帮助?
-
如果我是你,我会在发生 ClassCastException 的地方使用 Object 类型的辅助变量。我会在那里调试并检查对象的真实类型并将其与我想要转换的类类型进行比较。我会检查他们的类加载器。有了它,我可能会得到一些信息,例如:JPA 使用黑魔法并在运行时创建一个类类型,或者 JPA 将类类型缓存在 Map 中并基于此实例化它,但其他人重新启动 Game.java 的捆绑包并执行捆绑包编织...
-
顺便说一句,您使用什么持久性提供程序?
-
类是一样的,我认为只有类加载器不同:java.lang.ClassCastException: br.com.company.game.entity.Game 不能强制转换为 br.com.company.game。 entity.Game at br.com.company.game.service.impl.GameServiceImpl.prettyPrintGames(GameServiceImpl.java:30) at Proxy561ddac9_3d0d_4154_ac2b_f63a1852e182.prettyPrintGames(Unknown Source) at Proxy63e0d3db_6f54_4231_a8b0_d20e2665a1e7. .rest.GameResourceImpl.prettyPrintGames(GameResourceImpl.java:15)
-
我使用 Hibernate 作为 JPA 提供程序。查询执行成功。
标签: osgi apache-karaf blueprint-osgi