我有三个蓝图束(不同的罐子):
意识到这些捆绑包形成了模块游戏的层次。情形:
问题:
GameServiceImpl中的游戏 类型由 ap-service 捆绑类加载器加载,而IGameDAO服务返回的实例属于另一种类型因为它们是由 ap-dao 包类加载器加载的,因此会生成ClassCastException。意识到这个类是相同的(app.Game.java),应该是DTO。 DTO是我必须能够使用的基本对象,并通过bundle(通过服务)传递它们。如何在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
| | 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
| |
Bundle Manifest
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-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;
}
答案 0 :(得分:1)
如果你的设置是正确的,那么ap-data应该包含Game类,并且包含Game包的Export-Package。另外两个bundle应该有一个这个包的Import-Package语句。在这种情况下,类Game只能由ap-data的类加载器加载。
还要注意如何设置maven bundle插件。例如,如果您告诉它导出包含在另一个包中的包,那么它会将其嵌入您自己的包中。所以最简单的方法就是将其保留为默认值。
你可以寻找的东西是。多个包中不应包含任何包。您应该使用Aries JPA来进行JPA访问。正如Balazs评论说,持久性提供者经常在内部做黑魔法。与Aries JPA结合使用它应该在OSGi中工作,但如果你使用普通的JPA,可能会有问题。
我在github上检查了这个项目。我认为问题是persistence.xml的位置。此文件应始终位于包含实体类的项目中。你能尝试移动吗?
答案 1 :(得分:0)
相应于Christian Schneider,如评论中所示,尝试在运行时更新KAR文件,在任何持久性束中使用EntityManager,在尝试转换实体类型的bundle之间生成ClassCastException,Aries JPA 1.x的已知问题是什么。 Aries JPA 2x是要走的路。谢谢!