HttpServletRequest не отображается из загрузчика классов

Я пытаюсь запустить Apache Wink в OSGI и использую ресурсы регистрации Felix Whiteboard в качестве сервисов. В минималистской среде OSGI комплект работает как положено. Но затем я переместил пакет в среду Eclipse Equinox, где я разрабатываю плагин, который опирается на него. Я начал получать эту ошибку.

May 22, 2013 11:19:59 AM org.apache.wink.server.internal.application.ApplicationProcessor processWinkApplication
SEVERE: An exception occurred during processing of the com.yarcdata.rest.Repositories instance. This instance is ignored.
 java.lang.IllegalArgumentException: interface javax.servlet.http.HttpServletRequest is not visible from class loader
at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:461)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:690)
at org.apache.wink.common.internal.registry.ContextAccessor.getContextFromAccessor(ContextAccessor.java:92)

Я думаю, что у меня установлены все необходимые пакеты, и если я начинаю искать пакет, который экспортирует HttpServletRequest, я вижу:

g! lb | grep ervlet
311|Resolved   |    4|Servlet API Bundle (3.0.0.v201112011016)
394|Starting   |    4|Http Services Servlet (1.1.300.v20120912-130548)
444|Resolved   |    4|Jetty :: Servlet Handling (8.1.3.v20120522)
578|Resolved   |    4|jersey-servlet (1.12.0)
580|Resolved   |    4|jersey-servlet (1.17.1)
588|Active     |    4|Java Servlet API (3.0.1)
589|Resolved   |    4|javax.servlet.api (2.5.0)
590|Resolved   |    4|javax.servlet.jstl (1.1.2)
622|Active     |    4|Servlet Specification API (2.5.0)
678|Resolved   |    4|Spring Web Servlet (2.5.6)

g! bundle 588
javax.servlet-api_3.0.1 [588]
Id=588, Status=ACTIVE      Data Root=/wspaces/tbcPlugin/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/org.eclipse.osgi/bundles/588/data
"No registered services."
No services in use.
Exported packages
  javax.servlet; version="3.0.0"[exported]
  javax.servlet.descriptor; version="3.0.0"[exported]
  javax.servlet.annotation; version="3.0.0"[exported]
  javax.servlet.http; version="3.0.0"[exported]
No imported packages
No fragment bundles
Named class space
  javax.servlet-api; bundle-version="3.0.1"[provided]
No required bundles

Итак, поскольку полный пакет HttpServletRequest javax.servlet.http.HttpServletRequest Я ожидаю, что пакет 588, находящийся в активном состоянии, решит проблему для Wink. Он активен и экспортирует пакет, есть ли что-то более необходимое? Давайте проверим, какую версию он ищет:

g! lb | grep mdatu
  595|Resolved   |    4|Amdatu Web - JAX RS (1.0.0)
  596|Active     |    4|Amdatu Web - Apache Wink Application (1.0.1)

g! bundle 596
  org.amdatu.web.rest.wink_1.0.1 [596]
  Id=596, Status=ACTIVE      Data Root=/wspaces/tbcPlugin/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/org.eclipse.osgi/bundles/596/data
  "Registered Services"
    {org.amdatu.web.rest.jaxrs.JaxRsSpi}={service.id=139}
    {javax.servlet.Servlet}={init.applicationConfigLocation=/conf/application.properties, alias=/myresource, service.id=140}
    {javax.servlet.Servlet}={init.applicationConfigLocation=/conf/application.properties, alias=/protocol, service.id=141}
    {javax.servlet.Servlet}={init.applicationConfigLocation=/conf/application.properties, alias=/repositories, service.id=142}
    {org.osgi.service.cm.ManagedService}={service.pid=org.amdatu.web.rest.wink, org.amdatu.tenant.pid=org.amdatu.tenant.PLATFORM, service.id=143}
 Services in use:
    {java.lang.Object}={osgi.command.function=[confapply], osgi.command.scope=equinox, service.id=110}
 ...
  No exported packages
  Imported packages
    javax.activation; version="0.0.0"<org.eclipse.osgi_3.8.2.v20130124-134944 [0]>
    javax.annotation; version="0.0.0"<org.eclipse.osgi_3.8.2.v20130124-134944 [0]>
    javax.servlet; version="3.0.0"<javax.servlet-api_3.0.1 [588]>
    javax.servlet.http; version="3.0.0"<javax.servlet-api_3.0.1 [588]>

2 ответа

Решение

Похоже, у вас есть несколько пакетов, которые экспортируют пакеты API сервлетов (например, 588, 589 и 622, возможно, и другие). Поэтому пакет, импортированный вашим пакетом, может отличаться от пакета, импортированного пакетом Apache Wink. При обычных правилах загрузки классов Java два пакета считаются "одинаковыми", только если они имеют одинаковое имя И загружаются одним и тем же загрузчиком классов; что под OSGi означает, что они должны быть экспортированы одним и тем же пакетом.

Wink сообщает, что у вас нет видимости пакета сервлета... что на самом деле означает, что у вас нет видимости того же пакета сервлета, который он использует.

Хотя OSGi может обрабатывать несколько версий одного и того же пакета, вы значительно облегчите себе жизнь, если попытаетесь экспортировать каждый пакет только из одного пакета. Таким образом, в первую очередь вы должны избавиться от всех этих избыточных пакетов API.

Вы можете найти следующий фрагмент кода в ContextAccessor.java:92

(T)Proxy.newProxyInstance(Injectable.class.getClassLoader(),
                                  new Class[] {contextClass},
...

Как вы видите, используется загрузчик классов класса Injectable, который также находится в wink-common.jar. Однако, если вы загляните в файл MANIFEST.MF файла wink-commons.jar, вы увидите, что пакет javax.servlet.http не импортируется этим модулем.

Я не знаю настоящую логику в этом классе. Если у программиста не было очень веской причины использовать загрузчик классов, загружаемый Injectable, вероятно, лучше использовать загрузчик классов contextClass для генерации прокси. Вы можете спросить об этом у разработчиков.

Другие вопросы по тегам