我目前有两个OSGi包( bundle1
和 bundle2
)都通过EBA中的蓝图公开服务 . 在 bundle2
的 blueprint.xml
中,我想引用 bundle1
中的服务并将其注入BuildService(下面的代码),因为BuildService将用于调用TicketService . 然而,这会导致超时异常(也在下面) . 似乎BuildService从未在OSGi中注册 . 我怎么做这样的工作?
blueprint.xml
for bundle1
:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:bptx="http://aries.apache.org/xmlns/transactions/v1.0.0">
<bean id="TicketServiceBean" class="com.example.b2.impl.TicketServiceImpl">
<bptx:transaction value="Required" method="*" />
</bean>
<service ranking="0" id="TicketService" interface="com.example.b2.service.TicketService" ref="TicketServiceBean">
<service-properties>
<entry key="service.exported.interfaces" value="*" />
</service-properties>
</service>
</blueprint>
blueprint.xml
for bundle2
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean
id="BuildServiceImplBean"
class="com.example.b1.impl.BuildServiceImpl"
activation="eager" >
<property name="ticketService" ref="TicketServiceRef" />
</bean>
<service
id="BuildService"
ref="BuildServiceImplBean"
interface="com.example.b1.service.BuildService"
activation="eager">
<service-properties>
<entry key="service.exported.interfaces" value="*" />
</service-properties>
</service>
<reference
id="TicketServiceRef"
interface="com.example.b2.service.TicketService"
availability="mandatory"
activation="eager" />
</blueprint>
BuildService的实现:
public class BuildServiceImpl implements BuildService {
private TicketService ticketService;
@Override
public TicketBuildResponse ticketBuild(TicketBuildRequest ticketBuildRequest) throws BuildServiceException {
//do stuff here
}
public TicketService getTicketService() {
return ticketService;
}
public void setTicketService(TicketService ticketService) {
this.ticketService = ticketService;
}
}
启动应用程序服务器(Websphere)时,我收到以下异常:
BlueprintCont E org.apache.aries.blueprint.container.BlueprintContainerImpl$1 run Unable to start blueprint container for bundle com.example.b1.module due to unresolved dependencies [(objectClass=com.example.b2.service.TicketService)]
java.util.concurrent.TimeoutException
at org.apache.aries.blueprint.container.BlueprintContainerImpl$1.run(BlueprintContainerImpl.java:273)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:453)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:315)
at java.util.concurrent.FutureTask.run(FutureTask.java:150)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:207)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:736)
1 回答
下面是解决方案:OSGi应用程序运行时将远程服务与本地服务区别对待,因为默认调用语义不同(本地传递引用与远程传值) . 为了防止应用程序意外调用仅为传值调用而设计的导出服务,它将从本地查找中隐藏 .
解决方案是两次导出相同的bean,一次用于远程调用,第二次用于本地 . 换句话说,您将添加具有相同配置的另一个
<service />
元素,但不包含service.exported.interfaces
属性 .在websphere中实际上还有一个osgi控制台,它可以在
[local websphere installation]/profiles/[profileName]/bin/osgiApplicationConsole.bat
下找到 . 一旦发射,help()
会给你一个命令列表 . 要从SCA查看导入的服务,首先要连接到您的应用程序(例如connect(2)
,其中在list()
命令的结果中给出了应用程序的编号) . 然后,您可以执行services("(service.imported=true)")
以查看SCA添加的服务代理 . 命令services()
将列出应用程序中的所有服务 .