我目前有两个 OSGi 包(bundle1
和 bundle2
)都通过 EBA 中的蓝图公开服务。在 bundle2
的 blueprint.xml
中,我想从 bundle1
中引用一个服务并将其注入(inject)到 BuildService (下面的代码),因为 BuildService 将用于调用 TicketService。然而,这会导致超时异常(也在下面)。 BuildService 似乎从未在 OSGi 中注册过。我怎样才能使这样的东西发挥作用?
blueprint.xml
用于 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
用于 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>
构建服务的实现:
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)
最佳答案
解决方案如下:OSGi 应用程序运行时对待远程服务的方式与本地服务不同,因为默认调用语义不同(本地按引用传递与远程按值传递)。为了防止应用程序意外调用专为按值传递调用而设计的导出服务,它在本地查找中是隐藏的。
解决办法是将同一个bean导出两次,一次用于远程调用,第二次用于本地。换句话说,您将添加另一个 <service />
具有相同配置的元素,但没有 service.exported.interfaces
属性(property)。
<service ranking="0" id="TicketServiceExport" interface="com.example.b2.service.TicketService" ref="TicketServiceBean">
<service-properties>
<entry key="service.exported.interfaces" value="*" />
</service-properties>
</service>
<service ranking="0" id="TicketService" interface="com.example.b2.service.TicketService" ref="TicketServiceBean"/>
其实在websphere中也有一个osgi控制台,可以在[local websphere installation]/profiles/[profileName]/bin/osgiApplicationConsole.bat
下找到。 .一旦启动,help()
给你一个命令列表。要查看从 SCA 导入的服务,您首先连接到您的应用程序(例如 connect(2)
,其中应用程序的编号在 list()
命令的结果中给出)。然后你可以做 services("(service.imported=true)")
查看 SCA 添加的服务代理。命令services()
将列出应用程序中的所有服务。
关于java - OSGi/blueprint 中的服务引用无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5343388/