0

我正在尝试在 Apache Felix 上部署 Jersey 应用程序。我安装了这些捆绑包:

    ID|State      |Level|Name
    0|Active     |    0|System Bundle (4.4.1)
    1|Active     |    1|Apache Felix Bundle Repository (2.0.2)
    2|Active     |    1|Apache Felix Gogo Command (0.14.0)
    4|Active     |    1|Apache Felix Gogo Shell (0.10.0)
   10|Active     |    1|Apache Felix Configuration Admin Service (1.2.8)
   11|Active     |    1|Apache Felix EventAdmin (1.2.10)
   35|Active     |    1|Apache Felix Gogo Runtime (0.12.1)
   90|Installed  |    1|Apache Felix Log Service (1.0.0)
   91|Resolved   |    1|OSGi R4 Compendium Bundle (4.0.0)
   92|Installed  |    1|Apache Felix Declarative Services (1.6.0)
   94|Installed  |    1|Apache Felix Web Management Console (3.1.2)
   95|Installed  |    1|Apache Felix iPOJO WebConsole Plugins (1.6.0)
   96|Resolved   |    1|Apache Felix Shell Service (1.4.2)
  119|Installed  |    1|Servlet 2.1 API (1.0.0)
  144|Active     |    1|OSGi JAX-RS Connector (4.1.0.201407081443)
  147|Active     |    1|jersey-all (2.10.1)
  157|Active     |    1|OPS4J Pax Web - Jetty Bundle (4.0.0)
  158|Active     |    1|OPS4J Pax Web - Runtime (4.0.0)
  163|Active     |    1|http://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7-sources.jar (0.0.0)
  165|Active     |    1|Java Servlet API (3.0.1)
  167|Active     |    1|OPS4J Pax Logging - API (1.8.1)
  170|Active     |    1|Apache Felix Dependency Manager (3.2.0)
  171|Active     |    1|OPS4J Pax Web - Extender - WAR (4.0.0)
  174|Active     |    1|Apache Felix Dependency Manager Runtime (3.2.0)
  177|Active     |    1|ASM (5.0.3)
  178|Active     |    1|ASM commons classes (5.0.3)
  179|Active     |    1|ASM Tree class visitor (5.0.3)
  182|Active     |    1|Apache XBean OSGI Bundle Utilities (3.18.0)
  183|Active     |    1|Apache XBean :: Classpath Resource Finder (3.18.0)
  216|Active     |    1|Auth Test (2.0.0.SNAPSHOT)

最后一个,Auth Test 是我要发布的 Jersey 应用程序。我可以安装捆绑包并启动它。当我启动它时,我得到这些日志:

g! start 216
Started Activator
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.WebEventDispatcher] : Sending web event WebEvent [replay=false, type=DEPLOYING, bundle=platform-component-web-rest-service-authentication [216], extenderBundle=org.ops4j.pax.web.pax-web-extender-war [171], cause=null, timestamp=1416226629360, contextPath=/authentication, collisionIds=null, httpService=null, httpContext=null] for bundle platform-component-web-rest-service-authentication
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.WebEventDispatcher] : org/osgi/service/web/DEPLOYING
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.parser.WebAppParser] : version found in web.xml - 3.0
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.parser.WebAppParser] : metadata-complete is: false
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.parser.WebAppParser] : scanning for ServletContainerInitializers
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.parser.WebAppParser] : found container initializers by SafeServiceLoader ... skip the old impl. 
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.Activator] : Scheduling start of extension for bundle platform-component-web-rest-service-authentication asynchronously
org.ops4j.pax.web.pax-web-extender-war[org.ops4j.pax.web.extender.war.internal.WebAppPublisher] : Publishing web application [WebApp{displayName=Authentication Manager,contextName=authentication,m_httpContext=null}]

我想整个问题都在 web.xml 后面,它看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="platform-component-web-rest-manager-authentication" version="3.0">


    <display-name>Authentication Manager</display-name>


    <!-- ****************************************************************** -->
    <!-- SERVLETS -->
    <!-- ****************************************************************** -->         
    <servlet>
        <servlet-name>wd-platform-product-web</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>
                com.mycompany.platform.component.web.rest;
                com.mycompany.wd.platform.component.web.rest,
            </param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.scanning.recursive</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>
                com.wordnik.swagger.jersey.listing.ApiListingResourceJSON;
                com.wordnik.swagger.jersey.listing.JerseyApiDeclarationProvider;
                com.wordnik.swagger.jersey.listing.JerseyResourceListingProvider
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>wd-platform-product-web</servlet-name>
        <url-pattern>/rest/2.0.0/*</url-pattern>
    </servlet-mapping>


    <servlet>
        <servlet-name>swagger-default-jaxrs-config</servlet-name>
        <servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
        <init-param>
            <param-name>api.version</param-name>
            <param-value>2.0.0</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.api.basepath</param-name>
            <param-value>/rest/2.0.0/</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>

</web-app>

我的激活器类是标准模型:

import java.util.HashMap;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;

/**
 * This is to make sure we signal the application has been deployed/un-deployed
 * via the OSGi EventAdmin service.
 *
 * @author Jakub Podlesak (jakub.podlesak at oracle.com)
 */
public class WebAppContextListener implements BundleActivator, ServletContextListener {

    static EventAdmin ea;

    BundleContext bc;
    ServiceReference eaRef;

    synchronized static EventAdmin getEa() {
        return ea;
    }

    synchronized static void setEa(EventAdmin ea) {
        WebAppContextListener.ea = ea;
    }

    @Override
    public void contextInitialized(final ServletContextEvent sce) {
        if (getEa() != null) {
            final String contextPath = sce.getServletContext().getContextPath();
            getEa().sendEvent(new Event("jersey/test/DEPLOYED",new HashMap<String, String>(){{
                put("context-path", contextPath);}}));
        }
    }

    @Override
    public void contextDestroyed(final ServletContextEvent sce) {
        if (getEa() != null) {
            getEa().sendEvent(new Event("jersey/test/UNDEPLOYED",new HashMap<String, String>(){{put("context-path", sce.getServletContext().getContextPath());}}));
        }
    }

    @Override
    public void start(BundleContext context) throws Exception {
        System.out.println("Started Activator");
        bc = context;
        eaRef = bc.getServiceReference(EventAdmin.class.getName());
        if (eaRef != null) {
            setEa((EventAdmin)bc.getService(eaRef));
        }
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        if (eaRef != null) {
            setEa(null);
            bc.ungetService(eaRef);
        }
    }
}

我的主要 REST 服务如下所示:

@Path("/service/authentication")
@Api(value = "/service/authentication", description = "Authentication Service")
public class AuthenticationServiceRestService extends RestService
{

    ServiceLayer<Request<?>> serviceLayer;
    AuthenticationLayer<Request<?>> authenticationLayer;
    ExceptionLayer<Request<?>> exceptionLayer;


    public AuthenticationServiceRestService() throws AuthenticationServiceRestServiceException
    {
        this.serviceLayer = new ServiceLayer<Request<?>>();

        try
        {
            this.authenticationLayer = new AuthenticationLayer<Request<?>>(this.serviceLayer);
        }
        catch (AuthenticationServiceException exception)
        {
            throw new AuthenticationServiceRestServiceException(exception.getMessage(), exception);
        }

        this.exceptionLayer = new ExceptionLayer<Request<?>>(this.authenticationLayer);
    }


    @POST
    @Path("/auth")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "Get authentication token.", response = AuthenticationTokenFacade.class)
    public Response getAuthenticationToken(@ApiParam(value = "Authentication Data", required = true) AuthenticationRequestFacade authenticationRequestFacade)
    {
        System.out.println("auth request");
        GetAuthenticationTokenJsonRequest getAuthenticationTokenJsonRequest = new GetAuthenticationTokenJsonRequest(authenticationRequestFacade);

        return exceptionLayer.execute(getAuthenticationTokenJsonRequest);
    }

当我向我发出 POST 请求时,http://localhost:8080/authentication/rest/2.0.0/service/authentication/auth我得到 404。我什至不知道我的整个服务是否发布在码头上。我怎样才能做到这一点?当我提出请求时,Jetty 在大量日志的中间显示:

org.ops4j.pax.logging.pax-logging-api[org.ops4j.pax.web.service.spi.model.ServerModel] : Matching [/authentication/rest/2.0.0/service/authentication/auth]...
org.ops4j.pax.logging.pax-logging-api[org.ops4j.pax.web.service.spi.model.ServerModel] : Path [/authentication/rest/2.0.0/service/authentication/auth] does not match any context

任何有助于完成这项工作的帮助都会很棒。在此先感谢并对这个冗长的问题感到抱歉,但我必须确保提供了所有信息。

4

1 回答 1

2

首先,感谢详细的问题,这种方式要好得多,唯一缺少的是您正在使用的 Pax Web 版本;-)
其次,您可能有兴趣将 Karaf 与 Pax Web 一起使用。通过发出

feature:install war

命令在 Karaf 中安装 Pax Web。现在为什么我一开始建议这个,因为你说你不知道应用程序是否真的可用。为此,Karaf shell 中有两个可用的命令会告诉你它是否存在。一个是

web:list

另一个是

http:list

任何一个都会为您提供 a) 已部署的 Web 应用程序包或 b) 已注册的 servlet 的列表。

这可以让您更好地了解已部署的应用程序。
现在,我不明白的是,为什么您的 WebApplicationBundle (WAB) 中有一个 Activator,因为对于 WAB,您只需使用包括 Web-ContextPath 在内的 OSGi Manifest 的“常规”战争。从那里开始,WebExtender 将为您完成工作,就像您的情况一样。如果您想使用 ServletContextListener,请以常规方式在 web.xml 中注册它,或者因为您使用的是带有标准注释的 Servlet3 web.xml。

现在是最后一部分,日志消息已经告诉您,在向服务器发出请求时,还没有找到该请求的 httpContext。其原因很可能是在那之前的长日志中的某个地方。注册 servlet 可能有问题。再次, web:list命令可能有助于获得更好的图片。

由于 Pax Web 尚未对此进行明确测试 :-) 向 Pax Web 社区提供一个简单的示例以将其添加到示例中并进行集成测试可能会很有趣。在ops4j邮件列表中询问也总是很好的。

于 2014-11-18T06:26:20.543 回答