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

Също така се опитах да наложа Class тест на проксито:

    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 беше коригирано чрез премахване на "init-method" на клиентския компонент в клиентския blueprint.xml. Сега, вместо doProcess() да се стартира от init-method, той се стартира от 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