java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'reservationForm' available as request attribute at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE] at org.thymeleaf.spring4.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:401) ~[thymeleaf-spring4-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.thymeleaf.spring4.util.FieldUtils.getBindStatus(FieldUtils.java:328) ~[thymeleaf-spring4-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.thymeleaf.spring4.util.FieldUtils.getBindStatus(FieldUtils.java:294) ~[thymeleaf-spring4-2.1.5.RELEASE.jar:2.1.5.RELEASE] Spring徹底入門の写経をしていたら上記のエラー。 reservationFormがAttributeとしてバインドできないといっているっぽい。 見直すとコントローラーでの@ModelAttributeの設定漏れ。
「エラーパターン」タグアーカイブ
WebSocketのエンコード・デコード時のエラー
先日書いたWebsocketでJSONデータをやり取りしたブログだけど、エラー出力をきちんとしていなくてはまった。
Decoder.Text<T>のdecodeメソッド内でExceptionが発生した場合に、明示的にログ・スタックトレースの出力をしておかないと特にスタックトレース等が出力されないでdecodeメソッド(とそれから呼ばれる@OnMessage)が終了してしまう。(コンソールにエラーがつらつら出るようなことは無い。)
そのため、下みたいな感じで明示的にエラーあったことを出力してやらないとわかりにくい。
@Override public TestData decode(String inputString) throws DecodeException { try{ JsonObject jsonObject = Json.createReader(new StringReader(inputString)).readObject(); return new TestData(jsonObject); } catch(Exception e){ DecodeException de = new DecodeException(inputString,"decode失敗", (Throwable)e); Logger.getLogger(TestDecoder.class.getName()).log( Level.SEVERE, null, de); throw de; } }
Encoder.Text<T>のencodeメソッドも似たような話がある。
@Override public String encode(TestData paramData) throws EncodeException { try{ JsonObject model = Json.createObjectBuilder() .add("message", paramData.getMessage()) .add("sessionId",paramData.getSessionId()) .add("messageTime", formatDate(paramData.getMessageTime())) .build(); return model.toString(); } catch( Exception e ){ EncodeException ee = new EncodeException(paramData, "encode失敗", (Throwable)e); Logger.getLogger(TestEncoder.class.getName()).log( Level.SEVERE, null, ee); throw ee; } }
一応decodeでエラーを発生させたときのログサンプル
重大: javax.websocket.DecodeException: decode失敗 at jp.co.epea.first.json.TestDecoder.decode(TestDecoder.java:33) at jp.co.epea.first.json.TestDecoder.decode(TestDecoder.java:1) at org.glassfish.tyrus.core.EndpointWrapper.decodeCompleteMessage(EndpointWrapper.java:278) at org.glassfish.tyrus.core.SessionImpl.notifyMessageHandlers(SessionImpl.java:386) at org.glassfish.tyrus.core.EndpointWrapper.onMessage(EndpointWrapper.java:495) at org.glassfish.tyrus.server.TyrusEndpoint.onMessage(TyrusEndpoint.java:174) at org.glassfish.tyrus.websockets.DefaultWebSocket.onMessage(DefaultWebSocket.java:156) at org.glassfish.tyrus.websockets.frametypes.TextFrameType.respond(TextFrameType.java:66) at org.glassfish.tyrus.websockets.DataFrame.respond(DataFrame.java:102) at org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler.onDataAvailable(TyrusHttpUpgradeHandler.java:113) at org.apache.catalina.connector.InputBuffer$ReadHandlerImpl.processDataAvailable(InputBuffer.java:488) at org.apache.catalina.connector.InputBuffer$ReadHandlerImpl.onDataAvailable(InputBuffer.java:453) at org.glassfish.grizzly.http.io.InputBuffer.append(InputBuffer.java:855) at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:222) at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206) at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136) at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114) at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838) at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544) at java.lang.Thread.run(Thread.java:724) Caused by: java.lang.ClassCastException: org.glassfish.json.JsonStringImpl cannot be cast to javax.json.JsonNumber at org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl.getJsonNumber(JsonObjectBuilderImpl.java:171) at jp.co.epea.first.json.TestData.<init>(TestData.java:21) at jp.co.epea.first.json.TestDecoder.decode(TestDecoder.java:30) ... 27 more
WebSocketで@ServerEndpointが重複したときのエラー
@ServerEndpoint("/hello/") public class HelloWorld { と @ServerEndpoint("/hello/") public class HelloJson {
で起動時の
情報: Registering WebSocket filter for url pattern /*
といった次に
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:131)
… 46 more
Caused by: javax.websocket.DeploymentException: Found Equivalent paths. Added path: ‘/first/hello/’ is equivalent with ‘/first/hello/’.
とわかりやすいメッセージがでる。
一応スタックトレース
情報: Registering WebSocket filter for url pattern /* 重大: WebModule[/first]Exception starting filter WebSocket filter java.lang.InstantiationException at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:135) at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:5297) at org.apache.catalina.core.StandardContext.start(StandardContext.java:5909) at com.sun.enterprise.web.WebModule.start(WebModule.java:691) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1041) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:1024) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:747) at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2278) at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1924) at com.sun.enterprise.web.WebApplication.start(WebApplication.java:139) at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122) at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:291) at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:352) at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:497) at com.sun.enterprise.v3.server.ApplicationLoaderService.processApplication(ApplicationLoaderService.java:407) at com.sun.enterprise.v3.server.ApplicationLoaderService.postConstruct(ApplicationLoaderService.java:243) at org.jvnet.hk2.internal.ClazzCreator.postConstructMe(ClazzCreator.java:281) at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:328) at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:448) at org.glassfish.hk2.runlevel.internal.AsyncRunLevelContext.findOrCreate(AsyncRunLevelContext.java:163) at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2204) at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:93) at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.oneJob(CurrentTaskFuture.java:673) at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.run(CurrentTaskFuture.java:660) at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$UpOneJob.run(CurrentTaskFuture.java:490) at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$UpAllTheWay.go(CurrentTaskFuture.java:362) at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$UpAllTheWay.access$100(CurrentTaskFuture.java:279) at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture.go(CurrentTaskFuture.java:113) at org.glassfish.hk2.runlevel.internal.AsyncRunLevelContext.proceedTo(AsyncRunLevelContext.java:296) at org.glassfish.hk2.runlevel.internal.RunLevelControllerImpl.proceedTo(RunLevelControllerImpl.java:66) at com.sun.enterprise.v3.server.AppServerStartup.proceedTo(AppServerStartup.java:532) at com.sun.enterprise.v3.server.AppServerStartup.run(AppServerStartup.java:329) at com.sun.enterprise.v3.server.AppServerStartup.doStart(AppServerStartup.java:226) at com.sun.enterprise.v3.server.AppServerStartup.start(AppServerStartup.java:217) at com.sun.enterprise.glassfish.bootstrap.GlassFishImpl.start(GlassFishImpl.java:79) at com.sun.enterprise.glassfish.bootstrap.GlassFishDecorator.start(GlassFishDecorator.java:63) at com.sun.enterprise.glassfish.bootstrap.osgi.EmbeddedOSGiGlassFishImpl.start(EmbeddedOSGiGlassFishImpl.java:75) at com.sun.enterprise.glassfish.bootstrap.GlassFishDecorator.start(GlassFishDecorator.java:63) at com.sun.enterprise.glassfish.bootstrap.osgi.OSGiGlassFishImpl.start(OSGiGlassFishImpl.java:71) at com.sun.enterprise.glassfish.bootstrap.GlassFishMain$Launcher.launch(GlassFishMain.java:117) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.sun.enterprise.glassfish.bootstrap.GlassFishMain.main(GlassFishMain.java:97) at com.sun.enterprise.glassfish.bootstrap.ASMain.main(ASMain.java:54) Caused by: javax.servlet.ServletException: Web socket server initialization failed. at org.glassfish.tyrus.servlet.TyrusServletFilter.init(TyrusServletFilter.java:135) at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275) at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:131) ... 45 more Caused by: javax.websocket.DeploymentException: Found Equivalent paths. Added path: '/first/hello/' is equivalent with '/first/hello/'. at org.glassfish.tyrus.core.ErrorCollector.composeComprehensiveException(ErrorCollector.java:83) at org.glassfish.tyrus.server.TyrusServerContainer.start(TyrusServerContainer.java:144) at org.glassfish.tyrus.servlet.TyrusServletFilter.init(TyrusServletFilter.java:133) ... 47 more 情報: Loading application [first] at [/first] 情報: Loading application first done in 920 ms 情報: GlassFish Server Open Source Edition 4.0 (89) startup time : Felix (2,834ms), startup services(5,306ms), total(8,140ms) 情報: Initiating Jersey application, version Jersey: 2.0 2013-05-03 14:50:15... 情報: JMXStartupService has started JMXConnector on JMXService URL service:jmx:rmi://epeapc01-PC:8686/jndi/rmi://epeapc01-PC:8686/jmxrmi 情報: Grizzly Framework 2.3.1 started in: 10ms - bound to [/0.0.0.0:7,676] 情報: Registered com.sun.enterprise.glassfish.bootstrap.osgi.EmbeddedOSGiGlassFishImpl@30c2555a as OSGi service registration: org.apache.felix.framework.ServiceRegistrationImpl@19bd20.
JavaFX&Websocket連携(エラーパターン)
対向のサーバが落ちているとき。
素直にハンドシェイクできないという。まぁ、そのまんま。
7 20, 2013 5:43:29 午後 jp.co.epea.firstfxclient.SampleController$TwitterCheckService$1 call SEVERE: null javax.websocket.DeploymentException: Handshake response not received. at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:300) at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:172) at jp.co.epea.firstfxclient.SampleController$TwitterCheckService$1.call(SampleController.java:65) at jp.co.epea.firstfxclient.SampleController$TwitterCheckService$1.call(SampleController.java:1) at javafx.concurrent.Task$TaskCallable.call(Task.java:1259) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724)
URI clientURI = new URI(“ws://localhost:8080/first/hellohoge/”);
みたいにURLが間違っている場合。
Handshake errorというやつとスタックとレースにレスポンスコードが返ってくる。
この例だと存在しないパスなので404が返っているけど、WebsocketじゃないただのHTMLだとUpdate Protocolの時に失敗しているので(?)200が返ってくる。
なお、パスの指定時は最後の”/(スラッシュ)”も厳密に見る模様。
7 20, 2013 8:46:51 午後 jp.co.epea.firstfxclient.SampleController$TwitterCheckService$1 call SEVERE: null javax.websocket.DeploymentException: Handshake error. at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:285) at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:172) at jp.co.epea.firstfxclient.SampleController$TwitterCheckService$1.call(SampleController.java:65) at jp.co.epea.firstfxclient.SampleController$TwitterCheckService$1.call(SampleController.java:1) at javafx.concurrent.Task$TaskCallable.call(Task.java:1259) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724) Caused by: org.glassfish.tyrus.websockets.HandshakeException: Response code was not 101: 404 at org.glassfish.tyrus.websockets.HandShake.validateServerResponse(HandShake.java:314) at org.glassfish.tyrus.websockets.draft06.HandShake06.validateServerResponse(HandShake06.java:98) at org.glassfish.tyrus.container.grizzly.WebSocketFilter.handleClientHandShake(WebSocketFilter.java:368) at org.glassfish.tyrus.container.grizzly.WebSocketFilter.handleHandshake(WebSocketFilter.java:353) at org.glassfish.tyrus.container.grizzly.WebSocketFilter.handleRead(WebSocketFilter.java:274) at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206) at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136) at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114) at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:837) at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545) ... 1 more Connection had closed.
ちなみに、エラーログをはいているのはSampleController#createTaskの中にあるキャッチ節。
@Override protected Task createTask() { Task<Void> task = new Task<Void>() { @Override protected Void call() throws Exception { messageLatch = new CountDownLatch(1); try { URI clientURI = new URI("ws://localhost:8080/first/hellohoge/"); ClientManager cliContainer = org.glassfish.tyrus.client.ClientManager.createClient(); cliContainer.connectToServer(new TwitterClient(table), clientURI); messageLatch.await(1, TimeUnit.SECONDS); } catch (DeploymentException | URISyntaxException | InterruptedException ex) { Logger.getLogger(SampleController.class.getName()).log(Level.SEVERE, null, ex); } return null; } }; return task; }
下の@OnErrorは通らずに、@OnClose(前のログだと緑字部分)で終わるので注意。
@OnClose public void closeConnection(Session session) { System.out.println("Connection had closed."); } @OnError public void onError(Session session,Throwable t) { System.out.println("error"); t.printStackTrace(); }
javafx.concurrent.Taskの使い方次第でもっとハンドリングできそうな気がする。
とりあえず参考になりそうなサイト
JavaFXエラーパターン(FXMLLoaderのファイル名誤り)
FXMLLoader.load(getClass().getResource(“間違ったファイル名“));
としたときのエラーメッセージはロケーションが必須と若干意味が違うものが表示される。
Exception in Application start method Exception in thread "main" java.lang.RuntimeException: Exception in Application start method at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:403) at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47) at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115) at java.lang.Thread.run(Thread.java:724) Caused by: java.lang.NullPointerException: Location is required. <-ぱっと見わからない at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2739) (中略) at jp.co.epea.firstclient.test3.TestLoginFXML.start(TestLoginFXML.java:15)
FXMLLoaderの中身見るとクラスローダーで探せないからURLがnullで渡されいってこのメッセージになっているらしい。
public static <T> T load(URL paramURL) throws IOException { return load(paramURL, null); } -> if (paramURL == null) { throw new NullPointerException("Location is required."); }
JavaFXエラーパターン(Stage#setSceneの漏れ)
ITProのJavaFXサンプルを写経しつつ少しずつエラーを起こしてみる。
LoginDemoクラスにあるstage.setScene(scene);をコメントアウトしてみる。
public void start(Stage stage) {
stage.setTitle("Login Demo");
AnchorPane root = new AnchorPane();
Scene scene = new Scene(root);
//stage.setScene(scene); <-ここのコメントアウト
外枠部分だけ表示されて中が透明(背景がそのまま見える)な状態で表示されて枠ごと動かすとメモリがいっぱいいっぱいの時のような表示になる。
(枠の中に背景=Eclipseの画面が表示されている状態)
(ドラッグして表示が乱れている状態)
sceneに対して他のメソッドもコールしていなければEclipse上で”ローカル変数 scene の値は使用されていません”といわれるから多分気づく。ただ、メソッド呼んでいると警告出ないのでその時に事象を知らなかったら環境回りを疑いそう。
ちなみに、VBoxとかのコメントアウトはそのコンポーネント部分が表示されないだけなので切り分けは多分付く。
VBox vbox = new VBox();
//root.getChildren().add(vbox);
JavaFXエラーパターン(fxmlのimport漏れ)
JavaFXのimport文がもれていると以下のようなエラー
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?> <-これがあるべきなのに書かれていない
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefWidth="100" prefHeight="40" xmlns:fx="http://javafx.com/fxml">
<children>
<Label text="Hello, World!" />
</children>
</AnchorPane>
クラスを実行しようとすると項目名が不正な旨のエラーが発生する。
エラーになった行(ハローワールド)と項目名がでるのでそのインポート文を見直せばOK。
(エラーログ)
Label is not a valid type. /C:/dev/pleiades43/workspace/firstclient/bin/jp/co/epea/firstclient/Hello.fxml:7 at javafx.fxml.FXMLLoader.createElement(FXMLLoader.java:2381) at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2311) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2131)
ちなみにScene Builderだと下のようにラベルが表示されない。コンポーネント1種類だけのっていない場合は実行するまで気付かないかもしれない。
スペルミスの場合(クラスパスが通っていない場合も同じだと思う)
(エラーログ)
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.Label2?> <?import javafx.scene.layout.AnchorPane?> <AnchorPane prefWidth="100" prefHeight="40" xmlns:fx="http://javafx.com/fxml"> <children> <Label2 text="Hello, World!" /> </children> </AnchorPane> java.lang.ClassNotFoundException: javafx.scene.control.Label2 /C:/dev/pleiades43/workspace/firstclient/bin/jp/co/epea/firstclient/Hello.fxml at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2455) at javafx.fxml.FXMLLoader.processImport(FXMLLoader.java:2299)
Scene Builderで開こうとするとClassNotFoundExceptionで怒られるのでこっちは多分気づく。
ファイル'C:\dev\pleiades43\workspace\firstclient\src\jp\co\epea\firstclient\Hello.fxml'のロード中にエラーが発生しました。
C:\dev\pleiades43\workspace\firstclient\src\jp\co\epea\firstclient\Hello.fxml:0: error:
java.lang.ClassNotFoundException: javafx.scene.layout.Label2
WebSocketを使ってみる。その4
続けて@PathParamを試してみる。
APIによると
ServerEndpointに{パラメータ}で指定した値とバインドしてくれるらしい。
変数として使える型はStringかプリミティブOrそのボクシング型とのこと。
ただし、パラメータがデコードできなかったらエラーハンドラーを呼び出すらしい。
Java (zip:paramBindTest)
import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/hello/{hoge}/{fuga}") public class HelloWorld { static Set<Session> sessions = Collections .synchronizedSet(new HashSet<Session>()); @OnMessage public void onMessage(String message, @PathParam("hoge") Integer hoge,@PathParam("fuga") String fuga) { System.out.println("message[" + message + "]"); System.out.println("hoge[" + hoge + "]"); System.out.println("fuga[" + fuga + "]"); for (Session s : sessions) { s.getAsyncRemote().sendText(message); } }
JS
$(document).ready(function(){ var host="ws://localhost:8080/first/hello/12/ああ"; socket = new WebSocket(host); socket.onmessage = function(message){ $('#log').append(message.data + "<br/>"); }
結果
情報: 開始します:8ca15fe1-a79d-420e-afc6-3c5ab18a75ec 情報: message[あsdf] 情報: hoge[12] <- ボクシング型にバインドされている 情報: fuga[ああ] <- 日本語も素直にバインドされる模様
日本語もそのままうまくバインドされた。
ためしにIntegerの部分を少数にしたらNumberFormatExceptionをチェーンしたDecodeExceptionが発生。このケースは切り分け難しくない。
情報: エラーです:9366a9f2-2b24-4be3-8897-40427563d56e 重大: javax.websocket.DecodeException: Decoding failed at org.glassfish.tyrus.core.PrimitiveDecoders$IntegerDecoder.decode(PrimitiveDecoders.java:165) at org.glassfish.tyrus.core.PrimitiveDecoders$IntegerDecoder.decode(PrimitiveDecoders.java:157) at org.glassfish.tyrus.core.AnnotatedEndpoint$2.value(AnnotatedEndpoint.java:362) at org.glassfish.tyrus.core.AnnotatedEndpoint.callMethod(AnnotatedEndpoint.java:428) at org.glassfish.tyrus.core.AnnotatedEndpoint.access$100(AnnotatedEndpoint.java:83) at org.glassfish.tyrus.core.AnnotatedEndpoint$WholeHandler$1.onMessage(AnnotatedEndpoint.java:518) at org.glassfish.tyrus.core.SessionImpl.notifyMessageHandlers(SessionImpl.java:389) at org.glassfish.tyrus.core.EndpointWrapper.onMessage(EndpointWrapper.java:495) at org.glassfish.tyrus.server.TyrusEndpoint.onMessage(TyrusEndpoint.java:174) at org.glassfish.tyrus.websockets.DefaultWebSocket.onMessage(DefaultWebSocket.java:156) at org.glassfish.tyrus.websockets.frametypes.TextFrameType.respond(TextFrameType.java:66) at org.glassfish.tyrus.websockets.DataFrame.respond(DataFrame.java:102) at org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler.onDataAvailable(TyrusHttpUpgradeHandler.java:113) at org.apache.catalina.connector.InputBuffer$ReadHandlerImpl.processDataAvailable(InputBuffer.java:488) at org.apache.catalina.connector.InputBuffer$ReadHandlerImpl.onDataAvailable(InputBuffer.java:453) at org.glassfish.grizzly.http.io.InputBuffer.append(InputBuffer.java:855) at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:222) at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206) at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136) at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114) at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838) at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544) at java.lang.Thread.run(Thread.java:724) Caused by: java.lang.NumberFormatException: For input string: "1.2" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:492) at java.lang.Integer.valueOf(Integer.java:582) at org.glassfish.tyrus.core.PrimitiveDecoders$IntegerDecoder.decode(PrimitiveDecoders.java:163) ... 30 more
nullとした場合も素直にエラー
var host="ws://localhost:8080/first/hello/null/ああ"; -> Caused by: java.lang.NumberFormatException: For input string: "null"
空文字だと、予想外に素直なエラー
var host="ws://localhost:8080/first/hello//ああ"; -> Caused by: java.lang.NumberFormatException: For input string: ""
最後の文字列が空文字だと空文字としてバインドされる。
var host="ws://localhost:8080/first/hello/12/"; -> 情報: 開始します:75b4bc74-30e9-4a69-8af3-07ed67e6a296 情報: message[あ] 情報: hoge[12] 情報: fuga[]
/{空文字}/{数字}の順でも動いた。(//となるので環境次第では不具合が出る??)
@ServerEndpoint("/hello/{fuga}/{hoge}")と最初を文字列にする -> var host="ws://localhost:8080/first/hello//12"; -> 情報: 開始します:028c5db1-a60f-4d82-970f-8933058b2bfb 情報: message[あああ] 情報: hoge[12] 情報: fuga[]
{変数名}と@PathParamで誤記をするとバインドされない(null)。
@ServerEndpoint("/hello/{fuga}/{hoge}") -> public void onMessage(String message, @PathParam("hoge") Integer hoge, @PathParam("fuga2") String fuga) -> 情報: 開始します:49d01de4-4a6b-4b81-8c71-d6d48d9f0600 情報: message[あ] 情報: hoge[12] 情報: fuga[null]
URLパラーンの違いによっては呼び出されない。
一つ前のnullがバインドされる事象はバインド対象が不整合でも動いていたけど、そっちが中途半端に動いているだけで、呼び出されないのが正しいのかな??
@ServerEndpoint("/hello/{hoge}") <-fuga2はない -> public void onMessage(String message, @PathParam("hoge") Integer hoge,] @PathParam("fuga2") String fuga) { -> 23:27:25.244[23ms][total 23ms] Status: 404[Not Found] GET http://localhost:8080/first/hello/12/nasi Load Flags[LOAD_BYPASS_CACHE LOAD_BACKGROUND INHIBIT_CACHING ] Content Size[-1] Mime Type[application/x-unknown-content-type] Request Headers: Host[localhost:8080] User-Agent[Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0] Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8] Accept-Language[ja,en-us;q=0.7,en;q=0.3] Accept-Encoding[gzip, deflate] Sec-WebSocket-Version[13] Origin[http://localhost:8080] Sec-WebSocket-Key[gq8u2S2nXT2xpIagf7qPaQ==] Cookie[JSESSIONID=e1e94c1a637e58c7ccaa61c6f17e] Connection[keep-alive, Upgrade] Pragma[no-cache] Cache-Control[no-cache] Upgrade[websocket] Response Headers: X-Powered-By[Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)] Server[GlassFish Server Open Source Edition 4.0] Set-Cookie[JSESSIONID=e2121d0c30e627004af713703b3d; Path=/first; HttpOnly]