Karaf OSGI Aries Blueprint ClassCastException: Impl не может быть приведен к интерфейсу

Karaf v2.3.0, org.apache.aries.blueprint.core:1.0.1, создает ClassCastException, когда метод интерфейса вызывается для службы, импортированной из другого пакета. Метод интерфейса определен в интерфейсе и реализован классом реализации. Я не могу понять, как прокси службы считает, что это Impl (TicketServiceImpl), а не интерфейс (TicketService). Я благодарен за любые предложения или советы о том, как обойти это.

Исключение:

    Caused by: java.lang.ClassCastException: 
    org.abc.TicketServiceImpl cannot be cast to
    org.abc.TicketService at 
    Proxy3ac85313_c60c_42db_8def_ea7bd3d7411c.add(Unknown Source)
    ...
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.6.0_37]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)[:1.6.0_37]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)[:1.6.0_37]
    at java.lang.reflect.Method.invoke(Method.java:597)[:1.6.0_37]
    at org.apache.aries.blueprint.utils.ReflectionUtils.invoke(ReflectionUtils.java:297)[7:org.apache.aries.blueprint.core:1.0.1]
    at org.apache.aries.blueprint.container.BeanRecipe.invoke(BeanRecipe.java:958)[7:org.apache.aries.blueprint.core:1.0.1]
    ...

Как ни странно, непосредственно перед исключением я печатаю прокси .getInterfaces(), что подразумевает, что прокси — это TicketService, а не TicketServiceImpl.

    MyTicketServer proxy interfaces: org.abc.TicketService, 
    org.apache.aries.proxy.weaving.WovenProxy 
    MyTicketServer Proxy class name: Proxy3ac85313_c60c_42db_8def_ea7bd3d7411c

Я также попытался принудительно протестировать класс на прокси:

    if (myTicketService instanceof TicketService) { <-- you'd think this would help
        myTicketService.add(ticket); //<-- Throws proxy ClassCastException!!
    } // implies problem is in the return path through proxy back to method

person spiraleddy    schedule 31.12.2012    source источник


Ответы (1)


Почти получилось... Исключение classCastException в TicketService было исправлено путем удаления "метода инициализации" в клиентском компоненте в клиентском blueprint.xml. Теперь, вместо запуска doProcess() из метода init, он запускается с помощью driver.onRegisterService(), который вызывает client.doProcess(), который вызывает TicketService.add() без проблем, без исключений.

<bean id="driver" class="org.xyz.RetrieveDriver"></bean>
<service id="ticketRetriever" interface="org.xyz.TicketRetriever"
    ref="ticketRetrieverRT">
    <registration-listener ref="driver"
        registration-method="onRegisterService" 
        unregistration-method="onUnregisterService" />
</service>

Это навело меня на мысль, что клиент пытался использовать службу (в ее init-method="doProcess") до того, как была завершена сборка прокси службы. Я думал, что третий класс (драйвер), ожидающий официальной регистрации клиента, обеспечит готовность прокси к использованию клиентом.

Но затем я добавил к клиенту второй атрибут службы. Вторая служба периодически генерирует ClassCastException при вызове своего метода. Теперь я думаю, что это может быть простое старое состояние гонки; что я немного замедлил работу клиента, добавив драйвер, но не настолько, чтобы предотвратить использование второго сервиса до того, как он будет готов. Это тоже может быть неправильно. Я благодарен за любые мысли.

Если проблема не исчезнет волшебным образом, я добавлю отлов для ClassCastException с предположением, что сервис еще не готов.

person spiraleddy    schedule 31.12.2012
comment
Может быть? wiki.osgi.org/wiki/Service_Compatibility игнорировать совместимость... вместо этого вызывая getAllServiceReferences() из getServiceReferences(). С помощью ServiceTracker вызовите open(true) вместо просто open()… попытка приведения экземпляра службы к интерфейсу приведет к исключению ClassCastException. ПОСМОТРЕТЬ svn.apache.org/viewvc/camel/trunk/components/, getOsgiService(){...tracker.open(true)..} - person spiraleddy; 04.01.2013
comment
на основании этого проверит код для пакета, который не может импортировать какой-либо пакет, содержащий службу, которую вы хотите проксировать mail.osgi.org/pipermail/osgi-dev/2011-February/003019.html - person spiraleddy; 04.01.2013
comment
После ужесточения импорта и экспорта между пакетами я больше не сталкивался с проблемой. Я почти уверен, что проблема была связана с пакетом TicketService, открытым другим пакетом в группе Ticket. - person spiraleddy; 15.01.2013
comment
Чувак, это было огромной помощью для подобной проблемы, с которой я столкнулся. Большое спасибо, что нашли время, чтобы обновить свой SO! :) - person Bane; 21.06.2014