Jetty、websocket、java.lang.RuntimeException:无法加载平台配置器
Jetty, websocket, java.lang.RuntimeException: Cannot load platform configurator
我尝试在 Endpoint 中获取 http 会话。我遵循了这个建议 。这就是我这样做的原因:
public class MyConfigurator extends ServerEndpointConfig.Configurator
{
@Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request,
HandshakeResponse response)
{
HttpSession httpSession = (HttpSession)request.getHttpSession();
config.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}
和
@ServerEndpoint(value = "/foo", configurator = MyConfigurator.class)
public class MyEndpoint {
private Session wsSession;
private HttpSession httpSession;
@OnOpen
public void open(final Session session,EndpointConfig config) {
this.wsSession=session;
this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
}
}
这就是我得到的
java.lang.RuntimeException: Cannot load platform configurator
at javax.websocket.server.ServerEndpointConfig$Configurator.fetchContainerDefaultConfigurator(ServerEndpointConfig.java:123)
at javax.websocket.server.ServerEndpointConfig$Configurator.getContainerDefaultConfigurator(ServerEndpointConfig.java:128)
at javax.websocket.server.ServerEndpointConfig$Configurator.checkOrigin(ServerEndpointConfig.java:192)
at org.eclipse.jetty.websocket.jsr356.server.JsrCreator.createWebSocket(JsrCreator.java:88)
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:187)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:207)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:70)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:276)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:745)
我使用 osgi、jetty 9.3.11 和 pax-web 6.0.0。
问题是 javax.websocket-api jar 没有设置为使用 osgi 中的 ServiceLoader 机制,因此它可以找到自定义配置器实例。
为了让它在 osgi 中工作,javax.websocket-api jar 中的清单需要包含这些行:
Require-Capability: osgi.serviceloader;filter:="(osgi.serviceloader=javax.websocket.server.ServerEndpointConfig.Configurator)";resolution:=optional;cardin
ality:=multiple,osgi.extender;filter:="(osgi.extender=osgi.serviceloa
der.processor)"
因此,由于它没有这些行,因此您将需要添加另一个包,其中包含一个包含这些行的清单,并将自己声明为 javax.websocket-[=23= 的片段] 捆。
如果你使用的是 maven,你需要在 pom 中的行是这样的:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${bundle-symbolic-name};singleton:=true</Bundle-SymbolicName>
<Bundle-Name>OSGi Websocket API Fragment</Bundle-Name>
<Fragment-Host>javax.websocket-api</Fragment-Host>
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=)javax.websocket.server.ServerEndpointConfig.Configurator";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
</instructions>
</configuration>
</plugin>
这就是创建我的片段修复的方法:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId};singleton:=true</Bundle-SymbolicName>
<Bundle-Name>Websocket API OSGi Fix</Bundle-Name>
<Fragment-Host>javax.websocket-api</Fragment-Host>
<Require-Capability>
osgi.serviceloader;osgi.serviceloader="javax.websocket.server.ServerEndpointConfig$Configurator"
</Require-Capability>
</instructions>
</configuration>
</plugin>
这不是答案,但我们认为它可能会帮助 运行 遇到与我们相同问题的其他用户:我们遇到了与 OP 描述的完全相同的问题,但 "accepted answer" 没修好。也就是说,我们将所描述的条目精确地添加到指定 jar 中的清单中,并且我们继续得到相同的异常(与 OP 列出的异常相同)。
我们设法解决了如下问题。在我们的 Dropwizard initialize() 方法中,我们有这样的代码:
@Override
public void initialize(Bootstrap<AppConfig> bootstrap) {
...
bootstrap.addBundle(new WebsocketBundle(MyWebsocketHandler.class));
...
}
跟踪 Dropwizard 代码后,我们发现我们正在调用的 WebsocketBundle 构造函数将 null 分配给默认配置器,尽管 MyWebsocketHandler class 上的 @ServerEndpoint 注释指定了一个配置器 class,如下:
@ServerEndpoint(value="/myWebsocketPath",configurator=CustomEndpointConfigurator.class)
我们将 initialize() 中的构造函数调用更改为
bootstrap.addBundle(new WebsocketBundle(new CustomEndpointConfigurator(), TeamWebsocketHandler.class));
和噗,异常消失了。 (它确实导致了一连串新的 "NoClassDefFound" 异常,但这些异常很容易找到。安装包含所有缺失 classes 的缺失库后,应用程序 websockets 开始按预期运行。)
我们完全有可能完全误解了 Dropwizard 的工作原理(或应该工作原理);我们这些参与这个项目的人在涉及到这个领域时都是认真的新手,我们欢迎任何解释为什么我们所做的是 "wrong" 或 "doesn't make sense"。但我们认为这可能会帮助其他人发现一些对我们有用的东西,而 "accepted answer" 却没有。
您可以安装 mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.javax-websocket-api/1.1_1
包,它是原始 javax.websocket-api 的重新打包,但具有适当的 OSGi 描述符。更多相关信息:http://mavi.logdown.com/posts/7813065-deploying-vaadin-app-on-karaf
在我的例子中,我使用 proguard 混淆了 javax.websocket
。以下解决了我的问题:
-keep class javax.websocket.** { *; }
我尝试在 Endpoint 中获取 http 会话。我遵循了这个建议 。这就是我这样做的原因:
public class MyConfigurator extends ServerEndpointConfig.Configurator
{
@Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request,
HandshakeResponse response)
{
HttpSession httpSession = (HttpSession)request.getHttpSession();
config.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}
和
@ServerEndpoint(value = "/foo", configurator = MyConfigurator.class)
public class MyEndpoint {
private Session wsSession;
private HttpSession httpSession;
@OnOpen
public void open(final Session session,EndpointConfig config) {
this.wsSession=session;
this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
}
}
这就是我得到的
java.lang.RuntimeException: Cannot load platform configurator
at javax.websocket.server.ServerEndpointConfig$Configurator.fetchContainerDefaultConfigurator(ServerEndpointConfig.java:123)
at javax.websocket.server.ServerEndpointConfig$Configurator.getContainerDefaultConfigurator(ServerEndpointConfig.java:128)
at javax.websocket.server.ServerEndpointConfig$Configurator.checkOrigin(ServerEndpointConfig.java:192)
at org.eclipse.jetty.websocket.jsr356.server.JsrCreator.createWebSocket(JsrCreator.java:88)
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:187)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:207)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:70)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:276)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:745)
我使用 osgi、jetty 9.3.11 和 pax-web 6.0.0。
问题是 javax.websocket-api jar 没有设置为使用 osgi 中的 ServiceLoader 机制,因此它可以找到自定义配置器实例。
为了让它在 osgi 中工作,javax.websocket-api jar 中的清单需要包含这些行:
Require-Capability: osgi.serviceloader;filter:="(osgi.serviceloader=javax.websocket.server.ServerEndpointConfig.Configurator)";resolution:=optional;cardin
ality:=multiple,osgi.extender;filter:="(osgi.extender=osgi.serviceloa
der.processor)"
因此,由于它没有这些行,因此您将需要添加另一个包,其中包含一个包含这些行的清单,并将自己声明为 javax.websocket-[=23= 的片段] 捆。
如果你使用的是 maven,你需要在 pom 中的行是这样的:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${bundle-symbolic-name};singleton:=true</Bundle-SymbolicName>
<Bundle-Name>OSGi Websocket API Fragment</Bundle-Name>
<Fragment-Host>javax.websocket-api</Fragment-Host>
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=)javax.websocket.server.ServerEndpointConfig.Configurator";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
</instructions>
</configuration>
</plugin>
这就是创建我的片段修复的方法:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId};singleton:=true</Bundle-SymbolicName>
<Bundle-Name>Websocket API OSGi Fix</Bundle-Name>
<Fragment-Host>javax.websocket-api</Fragment-Host>
<Require-Capability>
osgi.serviceloader;osgi.serviceloader="javax.websocket.server.ServerEndpointConfig$Configurator"
</Require-Capability>
</instructions>
</configuration>
</plugin>
这不是答案,但我们认为它可能会帮助 运行 遇到与我们相同问题的其他用户:我们遇到了与 OP 描述的完全相同的问题,但 "accepted answer" 没修好。也就是说,我们将所描述的条目精确地添加到指定 jar 中的清单中,并且我们继续得到相同的异常(与 OP 列出的异常相同)。
我们设法解决了如下问题。在我们的 Dropwizard initialize() 方法中,我们有这样的代码:
@Override
public void initialize(Bootstrap<AppConfig> bootstrap) {
...
bootstrap.addBundle(new WebsocketBundle(MyWebsocketHandler.class));
...
}
跟踪 Dropwizard 代码后,我们发现我们正在调用的 WebsocketBundle 构造函数将 null 分配给默认配置器,尽管 MyWebsocketHandler class 上的 @ServerEndpoint 注释指定了一个配置器 class,如下:
@ServerEndpoint(value="/myWebsocketPath",configurator=CustomEndpointConfigurator.class)
我们将 initialize() 中的构造函数调用更改为
bootstrap.addBundle(new WebsocketBundle(new CustomEndpointConfigurator(), TeamWebsocketHandler.class));
和噗,异常消失了。 (它确实导致了一连串新的 "NoClassDefFound" 异常,但这些异常很容易找到。安装包含所有缺失 classes 的缺失库后,应用程序 websockets 开始按预期运行。)
我们完全有可能完全误解了 Dropwizard 的工作原理(或应该工作原理);我们这些参与这个项目的人在涉及到这个领域时都是认真的新手,我们欢迎任何解释为什么我们所做的是 "wrong" 或 "doesn't make sense"。但我们认为这可能会帮助其他人发现一些对我们有用的东西,而 "accepted answer" 却没有。
您可以安装 mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.javax-websocket-api/1.1_1
包,它是原始 javax.websocket-api 的重新打包,但具有适当的 OSGi 描述符。更多相关信息:http://mavi.logdown.com/posts/7813065-deploying-vaadin-app-on-karaf
在我的例子中,我使用 proguard 混淆了 javax.websocket
。以下解决了我的问题:
-keep class javax.websocket.** { *; }