«Неизвестный Bayeux Transport» для веб-сокетного транспорта, работающего на Tomcat. - PullRequest
0 голосов
/ 23 мая 2019

Я пытаюсь использовать CometD с транспортом веб-сокетов в моем веб-приложении, но рукопожатие с таким транспортом завершается неудачно с ошибкой «Неизвестный транспорт Байе», и CometD всегда возвращается к длинному опросу.

Я использую

  • Java 8
  • CometD 3.1.8 и Jetty 9.4.14.v20181114
  • Tomcat 8.5 в качестве контейнера

Вот web.xml

<servlet>
  <servlet-name>cometd</servlet-name>
  <servlet-class>org.cometd.server.CometDServlet</servlet-class>
  <init-param>
    <param-name>jsonContext</param-name>
    <param-value>com.myapp.MyAppJettyJSONContextServer</param-value>
  </init-param>
  <init-param>
    <param-name>allowedTransports</param-name>
    <param-value>websocket,long-polling</param-value>
  </init-param>
  <init-param>
    <param-name>transports</param-name>
    <param-value>org.cometd.websocket.server.JettyWebSocketTransport,org.cometd.server.transport.AsyncJSONTransport</param-value>
  </init-param>
  <init-param>
    <param-name>ws.cometdURLMapping</param-name>
    <param-value>/cometd/*</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
  <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
  <servlet-name>cometd</servlet-name>
  <url-pattern>/cometd/*</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>configuration</servlet-name>
    <servlet-class>com.myapp.MyAppConfigurationServlet</servlet-class>
    <init-param>
      <param-name>SERVER_URL</param-name>
      <param-value>http://localhost:8380/myapp/cometd</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>

<filter>
  <filter-name>cross-origin</filter-name>
  <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  <async-supported>true</async-supported>
</filter>
<filter-mapping>
  <filter-name>cross-origin</filter-name>
  <url-pattern>/cometd/*</url-pattern>
</filter-mapping>

Вот код MyAppConfigurationServlet.java

public class MyAppConfigurationServlet extends GenericServlet
{

    private static final long serialVersionUID = 6918716199131599352L;

    private static final Logger log = LoggerFactory.getLogger(MyAppConfigurationServlet.class);

    public static final String PUSH_SERVICE = "pushService";

    public static final String CONFIG_SERVER_URL = "SERVER_URL";

    @Override
    public void init() throws ServletException
    {
        WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        BayeuxServer bayeux = (BayeuxServer) getServletContext().getAttribute(BayeuxServer.ATTRIBUTE);
        String serverUrl = getInitParameter(CONFIG_SERVER_URL);
        log.debug("Creating PushService at url {}", serverUrl);
        PushService pushService = new PushService(bayeux, serverUrl);
        sharePushService(ctx, pushService);
    }

    private void sharePushService(WebApplicationContext ctx, PushService pushService)
    {
        try
        {
            PushServiceHolder container = (PushServiceHolder) ctx.getBean(PUSH_SERVICE);
            container.setPushService(pushService);
        }
        catch (BeansException e)
        {
            log.warn("Cannot find the bean {});
            log.trace("Error!", e);
        }
    }

    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException
    {
        throw new ServletException();
    }

}

, где PushServiceHolder - это простой пружинный компонент, который предоставляет PushService другим компонентам.

Вот реализация клиента

Map<String, Object> options = new HashMap<>();
JettyJSONContextClient jsonContext = new MyAppJettyJSONContextClient();
options.put(ClientTransport.JSON_CONTEXT_OPTION, jsonContext);

HttpClient httpClient = new HttpClient();
httpClient.setMaxConnectionsPerDestination(2);
httpClient.setConnectTimeout(60000);
httpClient.start();

WebSocketClient webSocketClient = new WebSocketClient(httpClient);
webSocketClient.start();
ClientTransport wsTransport = new JettyWebSocketTransport(options, null, webSocketClient);
BayeuxClient client = new BayeuxClient(url, wsTransport, longPollingTransport);
client.handshake();
client.waitFor(5000, BayeuxClient.State.CONNECTED);

Рукопожатие никогда не бывает успешным для транспорта через веб-сокет, с кодом ошибки 404 http, поэтому CometD отступает при длинном опросе.

Отладка в org.cometd.server.CometDServlet Я нашел эту часть

@Override
protected void service(HttpServletRequest request, HttpServletResponse     response) throws ServletException, IOException {
    if ("OPTIONS".equals(request.getMethod())) {
        serviceOptions(request, response);
        return;
    }

    AbstractHttpTransport transport = _bayeux.findHttpTransport(request);
    if (transport == null) {
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unknown Bayeux Transport");
    } else {
        transport.handle(request, response);
    }
}

org.cometd.websocket.server.JettyWebSocketTransport не является AbstractHttpTransport, поэтому этот код никогда не будет учитываться этим кодом, даже если он был правильно настроен как разрешенный транспорт.
Таким образом, запрос подтверждения связи для транспорта веб-сокета всегда заканчиваетсяс ошибкой "Неизвестный транспорт Bayeux" .

Я использовал документацию CometD здесь и здесь для создания web.xml.
Я хотел бы взглянуть на CometD maven primer , как много раз советовала команда CometD, но команда

$ mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate -DarchetypeCatalog=http://cometd.org 

возвращает эту ошибку

[WARNING] Error reading archetype catalog http://cometd.org
org.apache.maven.wagon.TransferFailedException: URI does not specify a valid host name: http:/cometd.org
at org.apache.maven.wagon.providers.http.wagon.shared.AbstractHttpClientWagon.fillInputData (AbstractHttpClientWagon.java:1069)
at org.apache.maven.wagon.providers.http.wagon.shared.AbstractHttpClientWagon.fillInputData (AbstractHttpClientWagon.java:963)
at org.apache.maven.wagon.StreamWagon.getInputStream (StreamWagon.java:126)
at org.apache.maven.wagon.StreamWagon.getIfNewer (StreamWagon.java:88)
at org.apache.maven.wagon.StreamWagon.get (StreamWagon.java:61)
at org.apache.maven.archetype.source.RemoteCatalogArchetypeDataSource.downloadCatalog (RemoteCatalogArchetypeDataSource.java:119)
at org.apache.maven.archetype.source.RemoteCatalogArchetypeDataSource.getArchetypeCatalog (RemoteCatalogArchetypeDataSource.java:87)
at org.apache.maven.archetype.DefaultArchetypeManager.getRemoteCatalog (DefaultArchetypeManager.java:216)
at org.apache.maven.archetype.ui.generation.DefaultArchetypeSelector.getArchetypesByCatalog (DefaultArchetypeSelector.java:218)
at org.apache.maven.archetype.ui.generation.DefaultArchetypeSelector.selectArchetype (DefaultArchetypeSelector.java:71)
at org.apache.maven.archetype.mojos.CreateProjectFromArchetypeMojo.execute (CreateProjectFromArchetypeMojo.java:181)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:208)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:954)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:288)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:192)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)
Caused by: org.apache.maven.wagon.providers.http.httpclient.client.ClientProtocolException: URI does not specify a valid host name: http:/cometd.org
at org.apache.maven.wagon.providers.http.httpclient.impl.client.CloseableHttpClient.determineTarget (CloseableHttpClient.java:95)
at org.apache.maven.wagon.providers.http.httpclient.impl.client.CloseableHttpClient.execute (CloseableHttpClient.java:83)
at org.apache.maven.wagon.providers.http.wagon.shared.AbstractHttpClientWagon.execute (AbstractHttpClientWagon.java:825)
at org.apache.maven.wagon.providers.http.wagon.shared.AbstractHttpClientWagon.fillInputData (AbstractHttpClientWagon.java:986)
at org.apache.maven.wagon.providers.http.wagon.shared.AbstractHttpClientWagon.fillInputData (AbstractHttpClientWagon.java:963)
at org.apache.maven.wagon.StreamWagon.getInputStream (StreamWagon.java:126)
at org.apache.maven.wagon.StreamWagon.getIfNewer (StreamWagon.java:88)
at org.apache.maven.wagon.StreamWagon.get (StreamWagon.java:61)
at org.apache.maven.archetype.source.RemoteCatalogArchetypeDataSource.downloadCatalog (RemoteCatalogArchetypeDataSource.java:119)
at org.apache.maven.archetype.source.RemoteCatalogArchetypeDataSource.getArchetypeCatalog (RemoteCatalogArchetypeDataSource.java:87)
at org.apache.maven.archetype.DefaultArchetypeManager.getRemoteCatalog (DefaultArchetypeManager.java:216)
at org.apache.maven.archetype.ui.generation.DefaultArchetypeSelector.getArchetypesByCatalog (DefaultArchetypeSelector.java:218)
at org.apache.maven.archetype.ui.generation.DefaultArchetypeSelector.selectArchetype (DefaultArchetypeSelector.java:71)
at org.apache.maven.archetype.mojos.CreateProjectFromArchetypeMojo.execute (CreateProjectFromArchetypeMojo.java:181)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:208)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:954)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:288)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:192)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)

Чего мне не хватает в моей конфигурации?Каков правильный адрес каталога архетипов CometD?

Большое спасибо

1 Ответ

0 голосов
/ 23 мая 2019

Как правило, CometD рекомендует развертываться в Jetty и использовать последнюю версию (на данный момент 4.0.4).

Ваш web.xml имеет неверные значения для transports init-param.

JettyWebSocketTransport - это транспорт CometD, который использует специфичный для Jetty API в своей реализации;поэтому он работает только при развертывании вашего приложения в Jetty.

Я рекомендую удалить transports init-param и позволить CometD выбрать правильные значения по умолчанию, которые будут работать как в Jetty, так и в Tomcat.

Для записи, транспорт WebSocket по умолчанию - org.cometd.websocket.server.WebSocketTransport, основанный на стандартных API-интерфейсах JSR 356, которые реализованы в Jetty и Tomcat.

Ваш клиент правильный, хотя и выВозможно, вы захотите использовать стандартный транспорт WebSocket, org.cometd.websocket.client.WebSocketTransport.

Я попробовал команду для генерации проекта из архетипов и отлично работает для меня.Возможно, у вас есть подсказка в ошибке: URI does not specify a valid host name: http:/cometd.org - посмотрите, что есть только 1 слеш, а не 2 обязательных слеша.

В итоге:

  • Перейти к CometD 4.0.x
  • Перейдите к Jetty, если можете
  • Удалите конфигурацию transports и используйте значения по умолчанию.
  • Перезапустите архетипы, указав правильный URL: https://cometd.org.
...