Pregunta

Actualmente tengo dos paquetes OSGI (bundle1 y bundle2) ambos exponen los servicios a través de un plan en una EBA. En bundle2's blueprint.xml Quiero hacer referencia a un servicio de bundle1 y Inyectar En el BuildService (código a continuación), ya que BuildService se usará para llamar a TicketService. Sin embargo, esto da como resultado una excepción de tiempo de espera (también a continuación). Parece que BuildService nunca se registra en OSGI. ¿Cómo haría que algo como esto funcione?

blueprint.xml por 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 por 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>

Implementación de 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;
    }


}

Al iniciar el servidor de aplicaciones (WebSphere), obtengo la siguiente excepción:

  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)
¿Fue útil?

Solución

Aquí está la solución: el tiempo de ejecución de OSGI Aplications trata los servicios remotos de manera diferente a los locales, debido a la diferente semántica de invocación predeterminada (pase por referencia local versus pase por valor remoto). Para evitar que una aplicación llame accidentalmente a un servicio exportado que solo está diseñado para llamadas de paso por valor, está oculto para las búsquedas locales.

La solución a esto es exportar el mismo frijol dos veces, una vez para llamadas remotas, y la segunda para local. En otras palabras, agregarías otro <service /> elemento con la misma configuración, pero sin el service.exported.interfaces propiedad.

<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"/>

En realidad, también hay una consola OSGI en WebSphere y se puede encontrar en [local websphere installation]/profiles/[profileName]/bin/osgiApplicationConsole.bat. Una vez lauched, help() te da una lista de comandos. Para ver sus servicios importados de SCA, primero se conecta a su solicitud (por ejemplo, connect(2), donde el número de la aplicación se da en los resultados del list() dominio). Entonces puedes hacer services("(service.imported=true)") Para ver los proxies de servicio que han sido agregados por SCA. El comando services() Enumerará todos los servicios en la aplicación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top