[TYRUS-436]  Handshake response not received Created: 08/Dec/16  Updated: 08/Dec/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.13
Fix Version/s: None

Type: Bug Priority: Blocker
Reporter: hplemon Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

I tried to use the standalone client JDK as shown here https://tyrus.java.net/dependencies.html

And this is the exception I receive. But when I used javascript to connect server, it worked well.
Exception in thread "main" java.lang.RuntimeException: javax.websocket.DeploymentException: Handshake response not received.
at test.ChatClientEndpoint.<init>(ChatClientEndpoint.java:34)
at test.ChatBot.main(ChatBot.java:20)
Caused by: javax.websocket.DeploymentException: Handshake response not received.
at org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:881)
at org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:904)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:1106)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:628)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:457)
at test.ChatClientEndpoint.<init>(ChatClientEndpoint.java:32)

Java code:
public static void main(String[] args) throws Exception {
final ChatClientEndpoint clientEndPoint = new ChatClientEndpoint(new URI("ws://localhost:9000"));
clientEndPoint.addMessageHandler(new ChatClientEndpoint.MessageHandler() {
public void handleMessage(String message)

{ System.out.println(message); }

});
while (true)

{ // clientEndPoint.sendMessage(getMessage("Hi There!!")); clientEndPoint.sendMessage("Hi There!!"); Thread.sleep(30000); }

}

Server side:
bash-4.1# python server.py
No handlers could be found for logger "trollius"
WebSocket connection closed: connection was closed uncleanly (WebSocket opening handshake timeout (peer did not finish the opening handshake in time))






[TYRUS-429] Unexplainable WebSocket error Created: 09/Aug/16  Updated: 16/Aug/16

Status: Open
Project: tyrus
Component/s: server
Affects Version/s: 1.12, 1.13
Fix Version/s: None

Type: Bug Priority: Blocker
Reporter: soylomass Assignee: petrjanouch
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

RAM 8GB
Debian 7.5



 Description   

The server works perfectly fine, until at a random moment, it starts throwing hundreds of these per second:

Aug 09, 2016 10:54:08 AM org.glassfish.tyrus.container.grizzly.client.GrizzlyWriter$WriterCondition$1 onError
WARNING: Connection closed
java.io.IOException: Connection closed
at org.glassfish.grizzly.asyncqueue.TaskQueue.onClose(TaskQueue.java:331)
at org.glassfish.grizzly.nio.AbstractNIOAsyncQueueWriter.onClose(AbstractNIOAsyncQueueWriter.java:501)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.closeConnection(TCPNIOTransport.java:402)
at org.glassfish.grizzly.nio.NIOConnection.doClose(NIOConnection.java:647)
at org.glassfish.grizzly.nio.NIOConnection$6.run(NIOConnection.java:613)
at org.glassfish.grizzly.nio.DefaultSelectorHandler$RunnableTask.run(DefaultSelectorHandler.java:495)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.processPendingTaskQueue(DefaultSelectorHandler.java:301)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.processPendingTasks(DefaultSelectorHandler.java:290)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.preSelect(DefaultSelectorHandler.java:101)
at org.glassfish.grizzly.nio.SelectorRunner.doSelect(SelectorRunner.java:335)
at org.glassfish.grizzly.nio.SelectorRunner.run(SelectorRunner.java:279)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.EOFException
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.read(TCPNIOTransport.java:597)
at org.glassfish.grizzly.nio.transport.TCPNIOTransportFilter.handleRead(TCPNIOTransportFilter.java:75)
at org.glassfish.grizzly.filterchain.TransportFilter.handleRead(TransportFilter.java:173)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:526)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
... 3 more

The seconds previous were just normal:



 Comments   
Comment by soylomass [ 09/Aug/16 ]

I pressed submit by error, continue here:

The previous seconds were just normal:

ADD MASS 0.5
ADD XP 1.0
10:54:07
SERVER ID #0 COUNTS BOX 3000 TANKS 15 PERSONS 1 SOCKETS 21
OPEN SOCKETS 21ENDCOUNTS
ADD MASS 0.5
10:54:07
SERVER ID #1 COUNTS BOX 3000 TANKS 10 PERSONS 0 SOCKETS 12
OPEN SOCKETS 12ENDCOUNTS
ADD XP 1.0
ADD XP 1.0
REMOVE HEALTH
ADD XP 1.0
Close connection for client:

Unknown macro: {9de6dad0-36dc-4c4a-8a35-9aa7ac2cda7e}

ON CLOSE
ADD MASS 0.5
ADD XP 1.0
Aug 09, 2016 10:54:08 AM org.glassfish.tyrus.container.grizzly.client.GrizzlyWriter$WriterCondition$1 onError
WARNING: Connection closed
java.io.IOException: Connection closed
at org.glassfish.grizzly.asyncqueue.TaskQueue.onClose(TaskQueue.java:331)
at org.glassfish.grizzly.nio.AbstractNIOAsyncQueueWriter.onClose(AbstractNIOAsyncQueueWriter.java:501)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.closeConnection(TCPNIOTransport.java:402)
at org.glassfish.grizzly.nio.NIOConnection.doClose(NIOConnection.java:647)
at org.glassfish.grizzly.nio.NIOConnection$6.run(NIOConnection.java:613)
at org.glassfish.grizzly.nio.DefaultSelectorHandler$RunnableTask.run(DefaultSelectorHandler.java:495)

And then, 896 errors were thrown in just one second, and it continued like this for minutes.

This usually happens without consequences, as the connected users can still send and receive data, but sometimes it causes the server to stop communicating.

I am sending the data using getAsyncRemote(), and I usually send them in separate Threads too. (I have a pool of CPU cores * 2 [8] threads I use to handle incoming messages and to prepare the outcoming game data).

Comment by Pavel Bucek [ 09/Aug/16 ]

Can you share a reproducer?

Comment by soylomass [ 09/Aug/16 ]

I wish I could. It happens randomly.

I've changed the async sends for basic instances to see if it stops happening. I'll report.

Comment by soylomass [ 11/Aug/16 ]

Basic of course went even worse, as it isn't efficient to handle a lot of writes.

Pavel, do you have any idea of what could be causing hundreds of those exceptions per second at random times? Do you have any idea of something I could try? My project is stuck until I fix this, and I've tried everything.

Comment by Pavel Bucek [ 12/Aug/16 ]

You could test with different settings related to selector and worker thread pools, see https://tyrus.java.net/apidocs/1.13/org/glassfish/tyrus/container/grizzly/server/GrizzlyServerContainer.html

But I'm not sure whether that will help. The problem seems to be dropped (closed) TCP connections and also it seems like presented exceptions are only consequence, not a cause. Are you monitoring number of open files / sockets on your server? Isn't it close to limits (see ulimit -a on *nix based systems + sysctl -a, etc..).

Comment by soylomass [ 13/Aug/16 ]

Is there any equation to get the recommended number of selector/worker threads? The software is a MMO game sending and receiving from every client more than 10 times per seconds.

By the way, I've set a timeout in the threads who prepare the data for clients and then send it with getAsyncRemote().send, and while the exceptions keep ocurring, the timeout stop it and saves the server from crashing.
It's strange, as the exception should be ocurring in the grizzly thread, not in mine (which I'm terminating)

Comment by petrjanouch [ 14/Aug/16 ]

Hi,

my humble opinion is that this has nothing to do with threads.
Grizzly has a write queue whose content it feeds to a socket when the socket is ready for writing.
The logged error means that Grizzly was not able to send the queued data because the the peer (the client, a load balancer or a proxy if there is one) has closed the TCP connection (look at the java.io.EOFException in the cause).

So I think that you are looking at the wrong side of the connection and the key to solving this is finding out why the connection was closed by the other side.
Btw. By closing the connection I mean that the connection was closed on the TCP level and not gracefully using the Websocket closing handshake.

The only think that puzzles me is that you say that the server becomes unresponsive after this happens. The only reason why Grizzly can become unresponsive is when all its worker threads are blocked somewhere (the exception you posted above wouldn't cause a Grizzly thread to be blocked). When the server becomes unresponsive do a thread dump and see what are Grizzly Worker threads doing or post it here if you cannot figure out anything.

Comment by soylomass [ 14/Aug/16 ]

What puzzles me is why the exception, once it happens, repeats itself hundreds of times in a second, if I don't make that many writes to a single client.

The exception doesn't make the server crash anymore now that I've implemented a timeout in the threads where the getAsyncRemote().send occur, but the exceptions keep happening randomly.

Comment by petrjanouch [ 14/Aug/16 ]

That is strange. The exception is logged once per closed connection and it will be also returned by the future/javax.websocket.SendResult of each uncompleted asynchronously written message.

Are you sure the hundreds of logged messages belong to one connection and many connections are not closed at the same time for whatever reason?

Comment by soylomass [ 14/Aug/16 ]

I would like to check that. I should use Future.get() to know that, right? In that case, the operation will be similar in performance to sending a syncronous write, as it would wait to the write operation to complete?

Comment by soylomass [ 14/Aug/16 ]

EDIT: I've checked the logs once more, and the exceptions start to happen always after a user disconnects (as it's catched by the onClose callback):

Close connection for client:

{80c02da2-e649-4edf-9a1e-6fa70591aef0}

ON CLOSE
Aug 14, 2016 3:51:19 PM org.glassfish.tyrus.container.grizzly.client.GrizzlyWriter$WriterCondition$1 onError
WARNING: Connection closed

So I don't think it has to do with many connections being closed at the same time. But it's still strange why the exception happens more time than the quantity of writes made to that user.

Comment by petrjanouch [ 14/Aug/16 ]

I have just figured out what happened. The message can be really logged enormous amount of times per one closed connection. I will fix it tomorrow morning CET and also a snapshot with the fix should be available tomorrow.

Thanks for reporting this. I will keep you updated about the fix.

Comment by soylomass [ 14/Aug/16 ]

Nice!. I'll look forward for it. Thanks a lot for the quick responses.

Comment by petrjanouch [ 15/Aug/16 ]

OK. Fixed. You can try 1.14-SNAPSHOT or 2.0-SNAPSHOT from java.net maven repo https://maven.java.net/content/repositories/snapshots/org/glassfish/tyrus/
Please, let us know how it worked for you.

Comment by soylomass [ 16/Aug/16 ]

I've updated to 1.14 snapshot and will report the results. What's the difference in 2.0?

Comment by Pavel Bucek [ 16/Aug/16 ]

2.0 is Java 8, 1.14 is Java 7.

But in practice, they are equal - same features, same code. Please use 1.14, since we are not yet releasing 2.x and it's not clear when that will happen.

Comment by soylomass [ 16/Aug/16 ]

Ok.

Can confirm the 1.14 snapshot fixes the problem (the exception now appears only once). Thanks to both of you for the quick help and support.





[TYRUS-435] Several packets arriving at once Created: 01/Dec/16  Updated: 01/Dec/16

Status: Open
Project: tyrus
Component/s: core, server
Affects Version/s: 1.14
Fix Version/s: None

Type: Bug Priority: Major
Reporter: soylomass Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Debian 8 64bit
4GB Ram
2 Cores Xeon


Tags: websockets

 Description   

I have a websocket MMO game server, which sends packets every +/- 70ms with world info to the players.

Everything works fine until there are 130+ players playing, as the clients will receive sometimes 5 packets in 5 milliseconds, what the player sees as stuttering.

I've searched on google, and some people says it may be related to Nagle's algorith (TCP_NODELAY in Grizzly). Could it be that it's enabled in Tyrus? Or it's a client only setting?

Also, I send the packets with getAsyncRemote().sendBinary(), the packets are in average 250bytes long ( I also send other smaller packets, less that 20bytes ).

Could it be that I should first check if the message has been sent before sending another message? If so, how should I do it?



 Comments   
Comment by soylomass [ 01/Dec/16 ]

I said in 5 milliseconds, but actually they sometimes arribe at the same millisecond.





[TYRUS-431] Tyrusclient handles same 401 not authorize response twice Created: 14/Sep/16  Updated: 14/Sep/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.13
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Dmytro_Mrachkovskyi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Looks like Tyrus client handles same 401 not authorize response twice.

Socket acquisition is protected with OAuth2 on server side.

Firs time client tries to obtain web socket server returns "401 not Authorized".
Client sends another request with token.
Server returns "101 protocol change" but sometimes client handles the same 401 response that was sent previously and closes connection

See logs from client and Wirwshark capture in attach



 Comments   
Comment by Dmytro_Mrachkovskyi [ 14/Sep/16 ]

Client Logs

2016-09-14 17:42:59:451 [http-nio-7080-exec-2] INFO o.g.tyrus.client.ClientManager - Provider class loaded: org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer
2016-09-14 17:42:59:504 [http-nio-7080-exec-2] DEBUG o.g.t.c.g.client.GrizzlyClientSocket - Not using proxy for URI 'ws://10.47.114.11:8086/websocket/sample-websocket/'.
2016-09-14 17:42:59:656 [http-nio-7080-exec-2] INFO o.g.t.c.g.client.GrizzlyClientSocket - Connecting to 'ws://10.47.114.11:8086/websocket/sample-websocket/' (no proxy).
2016-09-14 17:42:59:879 [http-nio-7080-exec-2] INFO o.g.t.c.g.client.GrizzlyClientSocket - Connected to '/10.47.114.11:8086'.
2016-09-14 17:43:00:051 [Grizzly(1)] DEBUG o.g.t.c.g.client.GrizzlyClientFilter - handleRead websocket: null content-size=102 headers=
HttpResponsePacket (
status=401
reason=Unauthorized
protocol=HTTP/1.1
content-length=-1
committed=false
headers=[
date=Wed, 14 Sep 2016 14:42:59 GMT
x-content-type-options=nosniff
x-xss-protection=1; mode=block
cache-control=no-cache, no-store, max-age=0, must-revalidate
pragma=no-cache
expires=Thu, 01 Jan 1970 00:00:00 GMT
x-frame-options=SAMEORIGIN
set-cookie=JSESSIONID=qn1oo42i28l11m3xsis0daeff;Path=/
www-authenticate=Bearer realm="vos", error="unauthorized", error_description="Full authentication is required to access this resource"
content-type=application/json;charset=UTF-8
transfer-encoding=chunked
server=Jetty(9.3.z-SNAPSHOT)]
)
2016-09-14 17:43:00:059 [Grizzly(1)] DEBUG o.g.t.c.g.client.GrizzlyClientSocket - Not using proxy for URI 'ws://10.47.114.11:8086/websocket/sample-websocket/'.
2016-09-14 17:43:00:064 [Grizzly(1)] INFO o.g.t.c.g.client.GrizzlyClientSocket - Connecting to 'ws://10.47.114.11:8086/websocket/sample-websocket/' (no proxy).
2016-09-14 17:43:00:194 [Grizzly(1)] INFO o.g.t.c.g.client.GrizzlyClientSocket - Connected to '/10.47.114.11:8086'.
2016-09-14 17:43:00:196 [Grizzly(1)] DEBUG o.g.t.c.g.client.GrizzlyClientFilter - handleRead websocket: null content-size=0 headers=
HttpResponsePacket (
status=401
reason=Unauthorized
protocol=HTTP/1.1
content-length=-1
committed=false
headers=[
date=Wed, 14 Sep 2016 14:42:59 GMT
x-content-type-options=nosniff
x-xss-protection=1; mode=block
cache-control=no-cache, no-store, max-age=0, must-revalidate
pragma=no-cache
expires=Thu, 01 Jan 1970 00:00:00 GMT
x-frame-options=SAMEORIGIN
set-cookie=JSESSIONID=qn1oo42i28l11m3xsis0daeff;Path=/
www-authenticate=Bearer realm="vos", error="unauthorized", error_description="Full authentication is required to access this resource"
content-type=application/json;charset=UTF-8
transfer-encoding=chunked
server=Jetty(9.3.z-SNAPSHOT)]
)
2016-09-14 17:43:00:202 [Grizzly(1)] DEBUG o.g.tyrus.client.TyrusClientEngine - * Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [11 ms]: Redirect enabled: false
2016-09-14 17:43:00:202 [Grizzly(1)] DEBUG o.g.tyrus.client.TyrusClientEngine - > Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [22 ms]: Sending handshake request:
> GET ws://10.47.114.11:8086/websocket/sample-websocket/
> Connection: Upgrade
> Host: 10.47.114.11:8086
> Origin: 10.47.114.11:8086
> Sec-WebSocket-Key: 0xknu45JGZSHo7wCoQvOYA==
> Sec-WebSocket-Version: 13
> Upgrade: websocket

2016-09-14 17:43:00:202 [Grizzly(1)] DEBUG o.g.tyrus.client.TyrusClientEngine - < Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [574 ms]: Received handshake response:
< 401
< cache-control: no-cache, no-store, max-age=0, must-revalidate, no-store
< content-type: application/json;charset=UTF-8
< date: Wed, 14 Sep 2016 14:42:59 GMT
< expires: Thu, 01 Jan 1970 00:00:00 GMT
< pragma: no-cache, no-cache
< server: Jetty(9.3.z-SNAPSHOT)
< set-cookie: JSESSIONID=qn1oo42i28l11m3xsis0daeff;Path=/
< transfer-encoding: chunked
< www-authenticate: Bearer realm="vos", error="unauthorized", error_description="Full authentication is required to access this resource"
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block

2016-09-14 17:43:00:202 [Grizzly(1)] DEBUG o.g.tyrus.client.TyrusClientEngine - > Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [574 ms]: Using authentication config: AuthConfig

{Bearer->client.OAuthAuthenticator, Digest->org.glassfish.tyrus.client.auth.DigestAuthenticator}

2016-09-14 17:43:00:202 [Grizzly(1)] DEBUG o.g.tyrus.client.TyrusClientEngine - > Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [574 ms]: Using authentication scheme: Bearer
2016-09-14 17:43:00:202 [Grizzly(1)] INFO o.g.tyrus.client.TyrusClientEngine - > Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [577 ms]: Using authenticator: client.OAuthAuthenticator
2016-09-14 17:43:00:202 [Grizzly(1)] INFO o.g.tyrus.client.TyrusClientEngine - > Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [577 ms]: Using credentials: null
2016-09-14 17:43:00:202 [Grizzly(1)] DEBUG o.g.tyrus.client.TyrusClientEngine - > Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [577 ms]: Sending handshake request:
> GET ws://10.47.114.11:8086/websocket/sample-websocket/
> Authorization: *****
> Connection: Upgrade
> Host: 10.47.114.11:8086
> Origin: 10.47.114.11:8086
> Sec-WebSocket-Key: 0xknu45JGZSHo7wCoQvOYA==
> Sec-WebSocket-Version: 13
> Upgrade: websocket

2016-09-14 17:43:00:202 [Grizzly(1)] DEBUG o.g.tyrus.client.TyrusClientEngine - < Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [715 ms]: Received handshake response:
< 401
< cache-control: no-cache, no-store, max-age=0, must-revalidate, no-store
< content-type: application/json;charset=UTF-8
< date: Wed, 14 Sep 2016 14:42:59 GMT
< expires: Thu, 01 Jan 1970 00:00:00 GMT
< pragma: no-cache, no-cache
< server: Jetty(9.3.z-SNAPSHOT)
< set-cookie: JSESSIONID=qn1oo42i28l11m3xsis0daeff;Path=/
< transfer-encoding: chunked
< www-authenticate: Bearer realm="vos", error="unauthorized", error_description="Full authentication is required to access this resource"
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block

2016-09-14 17:43:00:205 [http-nio-7080-exec-2] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [/client] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: javax.websocket.DeploymentException: Handshake error.] with root cause
org.glassfish.tyrus.client.auth.AuthenticationException: Authentication failed.
at org.glassfish.tyrus.client.TyrusClientEngine.handleAuth(TyrusClientEngine.java:353)
at org.glassfish.tyrus.client.TyrusClientEngine.processResponse(TyrusClientEngine.java:286)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleHandshake(GrizzlyClientFilter.java:346)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleRead(GrizzlyClientFilter.java:315)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
2016-09-14 17:43:00:334 [Grizzly(2)] DEBUG o.g.t.c.g.client.GrizzlyClientFilter - handleRead websocket: null content-size=0 headers=
HttpResponsePacket (
status=101
reason=Switching Protocols
protocol=HTTP/1.1
content-length=-1
committed=false
headers=[
date=Wed, 14 Sep 2016 14:43:00 GMT
x-content-type-options=nosniff
x-xss-protection=1; mode=block
cache-control=no-cache, no-store, max-age=0, must-revalidate
pragma=no-cache
expires=Thu, 01 Jan 1970 00:00:00 GMT
x-frame-options=SAMEORIGIN
set-cookie=JSESSIONID=zp3l248c5uedr11erqoymkgi;Path=/
connection=Upgrade
sec-websocket-accept=u0hHR9I3Mt5Ye0ZA9//08ICXExw=
server=Jetty(9.3.z-SNAPSHOT)
upgrade=WebSocket]
)
2016-09-14 17:43:00:334 [Grizzly(2)] DEBUG o.g.tyrus.client.TyrusClientEngine - < Session a21a3e32-988f-44d1-b9cb-72f2423f1260 [853 ms]: Received handshake response:
< 101
< cache-control: no-cache, no-store, max-age=0, must-revalidate
< connection: Upgrade
< date: Wed, 14 Sep 2016 14:43:00 GMT
< expires: Thu, 01 Jan 1970 00:00:00 GMT
< pragma: no-cache
< sec-websocket-accept: u0hHR9I3Mt5Ye0ZA9//08ICXExw=
< server: Jetty(9.3.z-SNAPSHOT)
< set-cookie: JSESSIONID=zp3l248c5uedr11erqoymkgi;Path=/
< upgrade: WebSocket
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block

2016-09-14 17:43:00:344 [Grizzly(2)] WARN o.g.g.filterchain.DefaultFilterChain - GRIZZLY0013: Exception during FilterChain execution
java.lang.IllegalStateException: null
at org.glassfish.tyrus.client.TyrusClientEngine.processResponse(TyrusClientEngine.java:331)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleHandshake(GrizzlyClientFilter.java:346)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleRead(GrizzlyClientFilter.java:315)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)

Comment by Dmytro_Mrachkovskyi [ 14/Sep/16 ]

unable to attach Wireshrak capture but from what I see there is only one 401 response is send, when client first time tries to obtain web-socket without Authorization header.
Than 101 is returned.

This issue is not constantly reproduces





[TYRUS-430] Connections close with reason: PROTOCOL_ERROR(1002): RSV bit(s) incorrectly set.} Created: 10/Sep/16  Updated: 10/Sep/16

Status: Open
Project: tyrus
Component/s: server
Affects Version/s: 1.14
Fix Version/s: None

Type: Bug Priority: Major
Reporter: soylomass Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Debian 7.5



 Description   

Some connections close with that reason (RSV bit(s) incorrectly set), and I see them trying to reconnect with no success.

At the same time, many users report daily that they can't connect to the websocket server, most of them from non-windows OS (mainly Chromium OS).

The clients connect to the server using HTML5's Js Websocket library.

I can't reproduce the problem as it works in all my devices (Windows, Android and iOS).

What are the RSV bits? And why they may be "incorrectly set"? What can I do to track the root of the problem?

Thanks.



 Comments   
Comment by soylomass [ 10/Sep/16 ]

The users with that problem open a connection, and it's closed almost immediately:

New connection with client: 3e909765-87e5-42bb-a845-217a047f47cf
...
Close connection for client:

{3e909765-87e5-42bb-a845-217a047f47cf}

REASON

{PROTOCOL_ERROR(1002): RSV bit(s) incorrectly set.}
Comment by Pavel Bucek [ 10/Sep/16 ]

ad RSV bits: see https://tools.ietf.org/html/rfc6455#section-5.2

5.2.  Base Framing Protocol

   This wire format for the data transfer part is described by the ABNF
   [RFC5234] given in detail in this section.  (Note that, unlike in
   other sections of this document, the ABNF in this section is
   operating on groups of bits.  The length of each group of bits is
   indicated in a comment.  When encoded on the wire, the most
   significant bit is the leftmost in the ABNF).  A high-level overview
   of the framing is given in the following figure.  In a case of
   conflict between the figure below and the ABNF specified later in
   this section, the figure is authoritative.

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+

   ...

   RSV1, RSV2, RSV3:  1 bit each

      MUST be 0 unless an extension is negotiated that defines meanings
      for non-zero values.  If a nonzero value is received and none of
      the negotiated extensions defines the meaning of such a nonzero
      value, the receiving endpoint MUST _Fail the WebSocket
      Connection_.

I just checked Tyrus code and there is only single place where RSV (rsv1) bit is set - in PerMessageDeflate extension. Aren't you using that by any chance? If no, there might be something fishy in Chromium OS, I would go for tcp dump and see whether you really see any RSV bits set to anything else than 0.

Anyway, Tyrus server passes Autobahn tests suite (http://autobahn.ws/testsuite/), which covers RSV bits, so I highly doubt that this issue is originating from Tyrus...





[TYRUS-428] When java security policy is used, Tyrus requires getProxySelector permission even if no Proxy is set Created: 09/Aug/16  Updated: 09/Aug/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.12
Fix Version/s: None

Type: Bug Priority: Major
Reporter: angelhpe Assignee: Pavel Bucek
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

JVM with security policy enabled



 Description   

1. Enable java security policy
2. Send a request using Tyrus
3. The request fails with the error below.

The error would indicate that is used, however no proxy is used. It occurs because in JDKClientContainer (line 412) a proxy selector is obtained regardless whether a proxy is needed or not.

final ProxySelector proxySelector = ProxySelector.getDefault();

javax.websocket.DeploymentException: Handshake error.
	at org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:674)
	at org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:712)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:866)
	at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
	at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:511)
	at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:373)
	at com.hp.oo.connector.client.websocket.tyrus.TyrusWebSocketClientNetConnector.lambda$connect$0(TyrusWebSocketClientNetConnector.java:146)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.security.AccessControlException: access denied ("java.net.NetPermission" "getProxySelector")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
	at java.security.AccessController.checkPermission(AccessController.java:884)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
	at java.net.ProxySelector.getDefault(ProxySelector.java:94)
	at org.glassfish.tyrus.container.jdk.client.JdkClientContainer.processProxy(JdkClientContainer.java:411)
	at org.glassfish.tyrus.container.jdk.client.JdkClientContainer.access$100(JdkClientContainer.java:80)
	at org.glassfish.tyrus.container.jdk.client.JdkClientContainer$1.call(JdkClientContainer.java:139)
	at org.glassfish.tyrus.container.jdk.client.JdkClientContainer$1.call(JdkClientContainer.java:126)
	at org.glassfish.tyrus.container.jdk.client.ClientFilter.processRead(ClientFilter.java:205)
	at org.glassfish.tyrus.container.jdk.client.Filter.onRead(Filter.java:134)
	at org.glassfish.tyrus.container.jdk.client.Filter.onRead(Filter.java:136)
	at org.glassfish.tyrus.container.jdk.client.Filter.onRead(Filter.java:136)
	at org.glassfish.tyrus.container.jdk.client.TransportFilter$4.completed(TransportFilter.java:299)
	at org.glassfish.tyrus.container.jdk.client.TransportFilter$4.completed(TransportFilter.java:283)
	at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126)
	at sun.nio.ch.Invoker$2.run(Invoker.java:218)
	at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
	... 3 more

What's even more curious about this error is that it is thrown when a response is received. Additionally, even if the permission is added, the problem still persists.



 Comments   
Comment by Pavel Bucek [ 09/Aug/16 ]

How do you suggest we get the information about the proxy setting of running JVM?

ProxySelector can return Proxy.NO_PROXY, which suggest that there is no proxy, but Tyrus needs to ask anyway..

Comment by angelhpe [ 09/Aug/16 ]

the problem is a bit different and is two fold:

1) Tyrus asks JVM for a proxy selector even if the end user has not specified any proxy. This can quickly be fixed by getting a proxySelector only if a proxy is in clientProperties. However this is more of a workaround for the actual root cause - see below

2) apparently the thread that is created to handle responses runs into its own security domain; because of this the configuration from java.security policy is not read hence the error above. (even if the getProxySelector permission is added, the error still persists)

Comment by Pavel Bucek [ 09/Aug/16 ]

ad 1) Actually, its the opposite way - when there is no proxy set in ClientProperties, we need to check for proxies defined on JVM level, since Tyrus should honor JVM-wide settings.

ad 2) I'm not sure why the new thread shouldn't have the same security domain - can you please elaborate? Reproducer could be handy..





[TYRUS-427] sending message from Closed Session on Tyrus Client component throw java.lang.IllegalStateException BUT onError is Not called Created: 14/Jul/16  Updated: 14/Jul/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.13
Fix Version/s: None

Type: Bug Priority: Major
Reporter: haducloc13 Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

I tried to send a message from Closed Session (ClientEndpoint). onError was NOT called.

I tried to send a message from Closed Session (ServerEndpoint). onError was called --> Worked.






[TYRUS-408] Gradually Increasing Memory Usage with Tyrus Standalone Client 1.11 Created: 31/Aug/15  Updated: 15/Feb/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.11
Fix Version/s: None

Type: Bug Priority: Major
Reporter: spstur Assignee: petrjanouch
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Tyrus Standalone Client 1.11
Java 8 (-Xmx40M)
Debian Jessie
Tomcat 7


Sprint: Triaged

 Description   

Setup: I have a long running Java 8 service that establishes several persistent websocket connections to a Tomcat 7 websocket server. Messages are sent and received at a fairly slow, consistent rate (3-15 every 15 seconds). The websocket connections disconnect and reconnect about every 10 minutes. I have set the max heap size to 40Mb, just to more efficiently troubleshoot OutOfMemory errors.

Problem: Eventually (after about 2 days), the java process begins throwing `java.lang.OutOfMemoryError: GC overhead limit exceeded`.

Monitoring the rss value of the process via the ps command shows the memory usage of the process increasing gradually (~2k/minute).

Monitoring the memory usage with jstat shows old generation usage increase gradually until it hits the limit. When it does, a full garbage collection happens and cleans up most of it, but each time it leaves a small amount. Eventually it reaches the GC limit threshold and throws the above error.

Analyzing the heap with jmap/jhat, and viewing instance counts shows 4 at the very top (in this order): org.glassfish.grizzly.http.util.BufferChunk, org.glassfish.grizzly.http.util.ByteChunk, org.glassfish.grizzly.http.util.CharChunk, org.glassfish.grizzly.http.util.DataChunk. These instances only get cleaned up when a full garbage collection happens, but each time it leaves some of them.

Viewing the heap histogram shows instances of [B consuming very large amounts (~50%) of the max heap size.

This seems similar to GRIZZLY-84, but that is marked as already fixed.



 Comments   
Comment by Pavel Bucek [ 01/Sep/15 ]

Hi spstur,

thanks for filing this.. interesting issue. Can you please share the code you have for reproducing the issue (minimal reproducer would speed things up greatly). From what you see it could be issue in Grizzly layer, but we can communicate that to them when this is verified.

Also, could you try to use Tyrus JDK client transport? (that does not use Grizzly at all - minimum requirement for this is JDK 7+, which should be ok, since you've indicated that you are using JDK 8).

See https://tyrus.java.net/documentation/1.11/user-guide.html#d0e1331 for more info about using jdk client transport.

Thanks,
Pavel

Comment by spstur [ 03/Sep/15 ]

I switched it over to use the JDK client transport. When analyzing the heap I no longer see any grizzly classes (as you'd expect), but I still see the same problems with memory usage, and now the instance count from the heap shows over 10k instances of class org.glassfish.tyrus.core.coder.CoderWrapper, after running for about 20 hours.

I'm working on a minimal reproducer at the moment, I have a number of other tasks taking precendence but I hope to have that to you in a couple weeks at the most. When I do I'll also try to provide more information about what exactly I'm seeing with the JDK client transport.

Comment by thomascashman [ 24/Sep/15 ]

I have a tyrus websocket client sending 20k messages/second to a tyrus websocket server in another application. I'm experiencing the same pattern of garbage collection and pauses. YourKit showed that the method that's creating the most objects is Async#sendText - can't inspect deeper than that for some reason. The client application dies very quickly - within 1 minute.

However, I've attempted to reproduce this (https://github.com/tomcashman/tyrus-408) in a simple tyrus client/server and it does not die as quickly but can see the old generation slowly increasing.

Comment by petrjanouch [ 15/Feb/16 ]

I have went through a couple of scenarios and I cannot reproduce this. To answer to the comment:

@thomascashman: Thanks for the reproducer. I run it for half an hour, made a heap dump at the beginning and at the and compared the heap dumps (and repeated twice, to be sure). I have rarely seen heap dumps with so little difference. In my view increasing old generation does not mean a memory leak, it might mean that some cached (Grizzly loves caching) and long lived objects get promoted. I am not saying there is not memory leak in your application, just that the reproducer does not reproduce it. You can try the same using jvisualvm (part of JDK). It allows comparing heap dumps.

I have tried my own reproducer, which creates a lot of short lived connections. I have found out the following. I managed to simulate a leak of org.glassfish.grizzly.http.util.BufferChunk, org.glassfish.grizzly.http.util.ByteChunk, org.glassfish.grizzly.http.util.CharChunk, org.glassfish.grizzly.http.util.DataChunk objects if websocket Session is not closed (Either by calling Session#close locally or receiving close frame from the server) or if references to Session are kept after it has been closed. If the Session is closed and references to it not kept around everything seems OK.

I cannot do more without more information. Either the promised reproducer or a heap dump would be helpful.





[TYRUS-401] Tyrus does not provide enough info when the client endpoint cannot be instantiated. Created: 23/Jul/15  Updated: 25/Jan/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.9
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

following code completes without any exception + it can even allow to send a message. Returned session is closed (isOpen() returns false), but there is no information about why that happened.

public class Test {
    public static void main(String[] args) throws IOException, DeploymentException, IllegalAccessException,
            InstantiationException {

        WebSocketContainer client = ContainerProvider.getWebSocketContainer();


        Session s = client.connectToServer(MyEndpoint.class,
                                           URI.create("ws://something.somewhere:someport/somepath"));
        System.out.println("XXX " + s.isOpen());

        System.in.read();
    }

    @ClientEndpoint
    public class MyEndpoint {

        @OnOpen
        public void onOpen(Session session) {
            System.out.println("onOpen " + session.isOpen());
        }
    }
}





[TYRUS-416] Hostname variable is not used Created: 27/Nov/15  Updated: 12/Feb/16

Status: Open
Project: tyrus
Component/s: server
Affects Version/s: 1.12
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Christian_Schmidt Assignee: petrjanouch
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

When using Tyrus in standalone mode the provided hostname in the constructor is not passed to the created container.

-> constructior
new Server(ip, port, "/ws", properties, EndpointCom.class, EndpointData.class);

The container is created in the start() method:
server = ServerContainerFactory.createServerContainer(properties);

for (Class<?> clazz : configuration)

{ server.addEndpoint(clazz); }

server.start(contextPath, port);

And there, the IP/Hostname is not passed to the created Container.






[TYRUS-415] Async connect can not be canceled Created: 21/Nov/15  Updated: 23/Nov/15

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.12
Fix Version/s: None

Type: Bug Priority: Major
Reporter: hoschott Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: deferred
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

TyrusFuture does not fulfill java.util.concurrent.Future contract in a useful manner.

The methods cancel(boolean) and isCancelled() are not implemented. Thus this implementation of Future works more like a Promise known from other languages.






[TYRUS-425] Reconnect Handler problem Created: 01/Jun/16  Updated: 01/Jun/16

Status: Open
Project: tyrus
Component/s: core
Affects Version/s: 1.10
Fix Version/s: None

Type: Bug Priority: Major
Reporter: hugolarson Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows



 Description   

Hello,

Sometimes Tomcat (7.0.69) throw a IOException: Connection timed out sporadically. OnError is called on the server side and I close the connection but the Tyrus ReconnectHandler does not reconnect at all with this particular exception. I have set the hearbeat interval to 1 minute.

BR,
Hugo






[TYRUS-424] Error in Deployment Algorithm description. Created: 09/May/16  Updated: 09/May/16

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: 1.12
Fix Version/s: None

Type: Bug Priority: Major
Reporter: pacuk.anton Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Tyrus documentation 1.12
https://tyrus.java.net/documentation/1.12/index/deployment.html



 Description   
public class MyApplicationConfigOne implements ServerApplicationConfig {
    public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses);
        Set<Class<? extends Endpoint>> s = new HashSet<Class<? extends Endpoint>>;
        s.add(ProgrammaticEndpointOne.class);
        return s;
    }

    public Set<Class> getAnnotatedEndpointClasses(Set<Class<?>> scanned);
       Set<Class<?>> s = new HashSet<Class<?>>;
        s.add(AnnotatedEndpointOne.class);
        return s;
    }
}

Set<Class<? extends Endpoint>> is returned instead of Set<ServerEndpointConfig> in getEndpointConfigs



 Comments   
Comment by pacuk.anton [ 09/May/16 ]

Wrong class name:

If one or more classes implementing ServerApplicationConfiguration are present in the WAR file, Tyrus deploys endpoints provided by all of these classes. Tyrus doesn't deploy any other classes present in the WAR (annotated by javax.websocket.server.ServerEndpoint or extending javax.websocket.Endpoint).
If no class implementing ServerApplicationConfiguration is present, Tyrus deploys all classes annotated with @ServerEndpoint or extending Endpoint present in the WAR.





[TYRUS-423] java.nio.BufferUnderflowException when receiving gzipped Inputstream Created: 09/May/16  Updated: 09/May/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.12
Fix Version/s: None

Type: Bug Priority: Major
Reporter: hugolarson Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows



 Description   

Hello,

We have an application that connects to Tomcat for receiving and sending request.
I have moved from receiving and sending to InputStream from ByteBuffer.
I discovered that Tyrus have problem receiving Gzipped Inputstream.
I find it also strange that the exception is generated in ByteBuffer class when im working with streams.
I can receive gzipped streams in Tomcat without problem and it works without gzip.

java.nio.BufferUnderflowException
at java.nio.Buffer.nextGetIndex(Unknown Source)
at java.nio.HeapByteBuffer.get(Unknown Source)
at org.glassfish.tyrus.core.InputStreamBuffer.getNextByte(InputStreamBuffer.java:130)
at org.glassfish.tyrus.core.BufferedInputStream.read(BufferedInputStream.java:66)
at java.io.InputStream.read(Unknown Source)
at java.util.zip.InflaterInputStream.fill(Unknown Source)
at java.util.zip.InflaterInputStream.read(Unknown Source)
at java.util.zip.GZIPInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at advit.web.dxweb.DxService.handleIn(DxService.java:26)
at advit.web.dxweb.TyrusWsClient$MyMessageHandler.handleMessage(TyrusWsClient.java:293)
at advit.web.dxweb.TyrusWsClient.onMessage(TyrusWsClient.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.glassfish.tyrus.core.AnnotatedEndpoint.callMethod(AnnotatedEndpoint.java:477)
at org.glassfish.tyrus.core.AnnotatedEndpoint.access$100(AnnotatedEndpoint.java:87)
at org.glassfish.tyrus.core.AnnotatedEndpoint$WholeHandler$1.onMessage(AnnotatedEndpoint.java:573)
at org.glassfish.tyrus.core.InputStreamBuffer$1.run(InputStreamBuffer.java:180)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

----------------------------For sending from Tomcat:
WsPayLoad payl = new WsPayLoad();
try (ObjectOutputStream ous = new ObjectOutputStream(new GZIPOutputStream(sess.getBasicRemote().getSendStream()))

{ ous.writeObject(payl); ous.flush(); }

----------------------For receiving on Tyrus client:
@Override
public void handleMessage(InputStream ins)

{ ObjectInputStream in = new ObjectInputStream( new GZIPInputStream(ins);); WsPayLoad obj = in.readObject();//Exception thrown here }




[TYRUS-422] Data lost when using SSL and unconsumed data pending when socket closes Created: 29/Mar/16  Updated: 29/Mar/16

Status: Open
Project: tyrus
Component/s: protocol
Affects Version/s: 1.12
Fix Version/s: None

Type: Bug Priority: Major
Reporter: spatula Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

This behavior was observed when connecting to a RabbitMQ server running a WebStomp plugin, and the connection was forcibly closed using RabbitMQ's admin UI. There are probably other, simpler ways to duplicate it. The sequence of events is that RabbitMQ sends an ERROR stomp frame and then quickly disconnects the connection.

When connecting via SSL (ie, with a wss:// URL), the ERROR frame sent across the WebSocket prior to disconnection is never delivered (ie, through TyrusWebSocket.onMessage); however, when connecting unencrypted (ie, with a ws:// URL), the ERROR frame sent prior to disconnection does get delivered.

It appears as though this may be a timing-sensitive issue, and the fact that it takes more time to decrypt the SSL data means that the close event gets handled first, and consequently the data is dropped, rather than handled.

I'm afraid I don't know Tyrus/Grizzly's internals well enough to speculate on how a fix might be implemented to ensure that any pending data was consumed from the WebSocket prior to firing events related to the socket closure.



 Comments   
Comment by spatula [ 29/Mar/16 ]

Explicitly specifying grizzly-framework version 2.3.22 seems to cure this ailment so far.





[TYRUS-410] WebSocket as Java EE component but JAAS not include Created: 13/Sep/15  Updated: 22/Sep/15

Status: Open
Project: tyrus
Component/s: server
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: hhf Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: deferred
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Glassfish server


Issue Links:
Blocks
is blocked by WEBSOCKET_SPEC-197 Better define integration with EJB an... Open

 Description   

Websocket is part of Java EE 7 but I can't apply Jaas mecanism from bean called from websocket

I secure web application with basic auth, and define roles and group/role mapping.
Everythings works fine with Servlet.

Now with websocket
From the method onMessage,
we can check user from session argument ok

@OnMessage
public void receiveCommandMessage(Session client, String msg) {
    session.getUserPrincipal()
}

We can too check role from configurator

@ServerEndpoint(value = "/endpoint", configurator = MyConfigurator.class)
public class MyEndpoint {
public class MyConfigurator extends ServerEndpointConfig.Configurator {
	@Override
	public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
		request.isUserInRole(ROLE);
	}
}

Endpoint is java EE component but when I inject CDI Bean inside, JAAS Context is not initialized, samething for EJB

In CDI Bean the injection of Principal return an ANONYMOUS Princiapl
In EJB injection of SessionContext is not initialized
JAAS Annotations @DeclaredRole and RoleAllowed etc... of course block all call.

I understand that the Endpoint is as an Singleton. But is there a solution ?
How I can do ?
an idea ?
there is bug ?






[TYRUS-400] Improved exceptions? Created: 02/Jun/15  Updated: 02/Jun/15

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.10
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: richardburton Assignee: Pavel Bucek
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

As a developer, I'm certain you can understand the pain a poorly articulated exception causes. It's like when a user opens up a ticket and says "Hey, it doesn't work." The following exception is without meaning and serves no purpose other than spitting up blood.

Caused by: javax.websocket.DeploymentException: Handshake response not received.
at org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:655)
at org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:673)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:826)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:496)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:348)

I'm able to connect to the server using ws://localhost:8080/context/endpoint without an issue but the Tyrus client simply throws a worthless error message without any meaningful information.

e.g., can it not find the host? (In this case it should), Is it connected but not getting any response back? (Not being connected since @OnOpen isnt called), and the list goes on.

I started to look at ClientManager#connectToServer but after trying to read 200 lines of code with nested anonymous classes, inline versions of classes with different implementations, etc. I thought I was watching the assembling of Franklinstein with all the things being hacked together in a single method.



 Comments   
Comment by richardburton [ 02/Jun/15 ]

Okay, I tried to use the standalone client JDK as shown here https://tyrus.java.net/dependencies.html

And this is the exception I receive.

java.lang.RuntimeException: javax.websocket.DeploymentException: org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer

at org.glassfish.tyrus.client.ClientManager.<init>(ClientManager.java:269)
at org.glassfish.tyrus.client.ClientManager.createClient(ClientManager.java:237)
at org.glassfish.tyrus.client.ClientManager.createClient(ClientManager.java:216)

Seriously? What does this even mean?

Please update ClientManager line 269 and change this:

throw new RuntimeException(collector.composeComprehensiveException());

to something actually comprehensive like "Unable to find 'org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer'" Please make sure you include tyrus-container-grizzly-server". Why would someone include the container grizzle server when you're using just the client?

Comment by Pavel Bucek [ 02/Jun/15 ]

The first exception means what is says - Tyrus was able to send handshake request, but it did not received any response within defined timeout.

The second one is little bit cryptic and you are correct that composeComprehensiveException should take the exception type into account as well (in this case, it seems like CNFE was reduced to getMessage(), which returns just the name of the class). Feel free to submit a pull request if you want (make sure you have OCA signed) or I'll take care of it before next release.

I'm not sure what your last question is referring to - we currently provide two client transports, I don't know why are you mentioning grizzly-server module.

Thanks.

Comment by richardburton [ 02/Jun/15 ]

To resolve the second exception, I had to add that jar which contained the missing class.

In the first case, it would be very useful to state how far the library got before timing out. e.g., it was able to connect to the server but didn't receive a response.

Comment by Pavel Bucek [ 02/Jun/15 ]

ad 1) you can enable logging, that should provide that kind of information; see https://tyrus.java.net/documentation/1.10/user-guide.html#d0e1475





[TYRUS-398] Access to underlying container buffers Created: 08/May/15  Updated: 08/May/15

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.10
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: jdv Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: container, grizzly, transport

 Description   

We have a client Endpoint that happens to occasionally need to push a fair amount of data back to the peer via write(), and during performance testing we noted that the data was being chunked up into 16K buffers.

While searching for a way to tweak the buffer sizes similar to .NET/C# ClientWebSocketOptions.SetBuffer it looks like we do not have access from the Endpoint to the underlying container transport buffers. Ideally, something like exposing TCPNIOTransportBuilder.writeBuffersSize() params (perhaps via GrizzlyClientProperties?) for Grizzly to give us a way to hint at larger buffers.

If Grizzly is slowly being deprecated in favour of the NIO transport container, a way to change the send/recv buffers beyond the fixed 4K/17K sizes in 1.10 is requested.



 Comments   
Comment by jdv [ 08/May/15 ]

I suppose this should be tagged "client".





[TYRUS-396] Passing info from ServerEndpointCondig#Configurator to Endpoint instance Created: 16/Mar/15  Updated: 18/Mar/15

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: 1.10
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Pavel Bucek
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to WEBSOCKET_SPEC-235 Passing values from ServerEndpointCon... Open

 Description   

Spec issue - WEBSOCKET_SPEC-235

I believe we should try to make that work at in Tyrus; some ideas:

  • TyrusSession could expose HandshakeRequest
  • HandshakeRequest could expose `Map<String, Object>` (userProperties) which will be added to Session#getUserProperties..


 Comments   
Comment by Pavel Bucek [ 18/Mar/15 ]

there is no good solution for that issue, if we limit the change only to WebSocket API implementation; all we can do here is to introduce another ServerEndpointConfig#Configurator descendant (let's call it TyrusServerConfigurator), which would somehow provide access to any object (most likely userProperties).

Since we are extending original Configurator, we cannot change the method signatures. Also the Configurator is currently singleton, so we cannot easily set the value and let the code get it - the concurrent invocation won't be handled correctly. I see two possible approaches:

  • keep singleton, set the userProperties as ThreadLocal
  • don't keep the singleton, make new instance for each endpoint instance

Currently I don't particularly like either of those, so if anyone has better suggestion, I'm all ears.. Thanks!





[TYRUS-389] Support SSL configuration in standalone server Created: 17/Oct/14  Updated: 17/Oct/14

Status: Open
Project: tyrus
Component/s: server
Affects Version/s: 1.8.3
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: isart Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

The idea is being able to configure SSL in a standalone server similarly as it can be done to the client:
https://tyrus.java.net/documentation/1.8.3/user-guide.html#d0e1128

Probably by passing to the server the same SslEngineConfigurator with an SslContextConfigurator that is supported in the client.



 Comments   
Comment by isart [ 17/Oct/14 ]

Currently SSLEngine can be influenced by setting appropriated System properties:
System.setProperty(SslContextConfigurator.KEY_STORE_FILE, keystorePath);
System.setProperty(SslContextConfigurator.KEY_STORE_PASSWORD, keystorePassword);
...

However, using JVM global properties may not be appropriated in several scenarios.





[TYRUS-388] Support WSS in standalone server Created: 17/Oct/14  Updated: 14/Oct/16

Status: Open
Project: tyrus
Component/s: server
Affects Version/s: 1.8.3
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: isart Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

As a developer, I'd like to be able to enable WSS programmatically in a standalone server.

Currently (version 1.8.3) one has to apply following hack in order to do it:
https://java.net/projects/tyrus/lists/users/archive/2014-02/message/1



 Comments   
Comment by michaelarice [ 14/Oct/16 ]

I would very much like to see this get implemented. Unfortunately I did not see this issue before I spent a good bit of time separating an application from our WildFly server to run standalone. We operate in an SSL world, so supporting wss in the standalone server is an absolute must. I will look into the 'hack' described in the original issue, but I think a non-hack solution is certainly warranted.





[TYRUS-367] Provide a way how to get low-level info about the session. Created: 29/Aug/14  Updated: 02/Sep/14

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: 1.8
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Ondrej Kosatka
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Something similar to what ServletRequest [1] provides:

java.lang.String getLocalAddr()
java.lang.String getLocalHost()
int getLocalPort()
java.lang.String getRemoteAddr()
java.lang.String getRemoteHost()
int getRemotePort()

[1] http://docs.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html






[TYRUS-331] Support for running websocket client inside sandbox Java applet Created: 16/Jun/14  Updated: 16/Jun/14

Status: Open
Project: tyrus
Component/s: client, core
Affects Version/s: 1.6
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: mark30000 Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

WildFly 8.1.0 application server, sandbox Java applet that uses Tyrus websocket client.



 Description   

Tyrus websocket client doesn't function out of the box within sandbox applet due to its restrictions and security limitations. There were 2 major problems with the existing code base: access to system properties (restricted in
sandbox except for few specific Java properties, see http://docs.oracle.com/javase/tutorial/deployment/doingMoreWithRIA/properties.html) and some Java reflections code that behaves differently in Sandbox applet than in a standalone application.

Below is the list of changes we've implemented to resolve the issue in Tyrus project (Grizzly project has a much bigger list):

1. /containers/grizzly-client/src/main/java/org/glassfish/tyrus/container/grizzly/client/GrizzlyClientSocket.java
Made conditional access to system properties (when having no access - in sandbox applet, use predefined default).
Also made conditional access to proxy settings (not allowed in sandbox).

2. /core/src/main/java/org/glassfish/tyrus/core/ReflectionHelper.java
getParameterizedClassArguments method behaves differently in sandbox and in standalone application. Specifically,
p.genericInterface is never instance of ParameterizedType (Java reflection getGeneric... methods do not return the correct type in sandbox
for typed classes; for example, in standalone application we get MyClass.InnerClass<T> while in sandbox we get only MyClass.InnerClass
only). As a workaround resolution, we hard coded specific org.glassfish.tyrus.core.coder.X classes instead of dynamic resolution.

Probably the solution we've implemented is not the best so it is just a hint on what should be fixed and where.






[TYRUS-362] Revise userdoc Created: 12/Aug/14  Updated: 12/Aug/14

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   
  • add entities/links to javadoc
  • unify formatting across whole document





[TYRUS-349] Using system/browser (SSL) keystore when running in applet code Created: 29/Jul/14  Updated: 29/Jul/14

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.7
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: bko Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: applet, cacerts, ssl

 Description   

When using an SSL secured connection to a WebSocket server in a Java-Applet only the certificates in the keystore of the JRE (cacerts file) were checked.

If using a HttpsURLConnection in a Java-Applet it automatically uses the system keystore (Internet Explorer on Windows) or the browser keystore (Firefox).

The websocket client should behave like the HttpsURLConnection.






[TYRUS-304] Review ByteBuffer reading when sending/receiving messages (using RemoteEndpoint.sendBinary( ... )) Created: 13/Mar/14  Updated: 03/Sep/14

Status: Open
Project: tyrus
Component/s: core
Affects Version/s: 1.5
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified





[TYRUS-300] Introduce better support for QueryParams Created: 06/Mar/14  Updated: 27/Mar/14

Status: Open
Project: tyrus
Component/s: samples
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Comments   
Comment by Pavel Bucek [ 27/Mar/14 ]

(see JAX-RS @QueryParam)





[TYRUS-316] Introduce configurable write timeout (basic remote) Created: 10/Apr/14  Updated: 26/Jun/14

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: 1.5
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Pavel Bucek
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

sometimes it might happen (infra issues) that synchronous call is never completed.

Then Tyrus should have some timeout to be able to unblock itself/client/application.






[TYRUS-241] l10n - LogLevel INFO+ should be internacionalized. Created: 22/Aug/13  Updated: 25/Jan/16

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Comments   
Comment by Pavel Bucek [ 19/Feb/14 ]

done for tyrus-core





[TYRUS-231] BeanValidation integration Created: 09/Aug/13  Updated: 09/Aug/13

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   
  • BV integration (without EJB, CDI or other container)
  • improved error reporting (instanceof check in @OnError is not nice pattern)





[TYRUS-279] TyrusSession.broadcast should allow the client to provide a predicate Created: 06/Dec/13  Updated: 06/Dec/13

Status: Open
Project: tyrus
Component/s: core
Affects Version/s: 1.3.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: gdavison Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

I feel that TyrusSession.broadcast should take a Predicate filter so that messages can easily be sent to sub sections of the connected clients.

So it should be possible to do something like this:

((TyrusSession)session).broadcast(message, s -> s.getUserProperties().conains("NAME"));

Ideally the interface should be serialisable so that the same expression could be used across the cluster as per bug TYRUS-278, you do need to be a little bit careful in this case as this blog shows:

http://kingsfleet.blogspot.co.uk/2013/12/lambda-will-it-serialize.html

Obviously the code will be written in a form that will work with JDK6 but can be more pleasant to use with JDK 8.






[TYRUS-278] Tyrus should be able to broadcast over a farm using JMS of other similar technology Created: 04/Dec/13  Updated: 04/Dec/13

Status: Open
Project: tyrus
Component/s: server
Affects Version/s: 1.3.1
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: gdavison Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

It would make a look simpler if Tyrus contains features natively to support using JMS queue or similar technology such as coherence to support sending messages to multiple nodes in the farm:

@ServiceEndpoint(...)
@TyrusCluster()
@TyrusJMSQueue(... something to configure a suitable queue ... )
public class MyClusteringEndpoint
{
}

This would probably only come into play if you make use of the new broadcast method on TyrusSession:

((TyrusSession)peer).broadcast(message)

The implication here is that is we were to allow filtering on the broadcast...

((TyrusSession)peer).broadcast(message, Session::isOpen)

.... this would probably require an interface that could be serialisable:

public interface SerializablePredicate<T>
extends Predicate<T>, Serializable {
}

You would have to be careful to not allow anonymous inner classes in this case as it would end up trying to serialise the entire outer object. I am not sure Lambda would be dealt with this incase, I guess you would have to make sure it doesn't capture too much of the containing state. I would get the ObjectOutput stream would fail in these cases.






[TYRUS-267] Implement WebSocket subprotocol support Created: 01/Nov/13  Updated: 01/Nov/13

Status: Open
Project: tyrus
Component/s: core
Affects Version/s: 1.3
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   
  • xmpp, stomp, json, xml, ...
  • (might be implemented as more robust version of encoders/decoders)





[TYRUS-220] Implement batching support in RemoteEndpointWrapper Created: 25/Jul/13  Updated: 04/Nov/13

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major
Reporter: stepan.kopriva Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified





[TYRUS-196] Implement correct @PreDestroy calling for user provided ServerEndpointConfig.Configurator Created: 17/Jun/13  Updated: 23/Nov/15

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: stepan.kopriva Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: deferred
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
depends on WEBSOCKET_SPEC-207 ServerEndpointConfig$Configurator get... Open

 Description   

Change in API needed to be able to resolve the task, see WEBSOCKET_SPEC-207






[TYRUS-204] Improve client-side proxy support Created: 24/Jun/13  Updated: 04/Apr/14

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: 1.1
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 8
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   
  • proxy authentication
  • ProxySelector support

please vote/comment if you want this to be implemented.



 Comments   
Comment by jewel-sea [ 26/Aug/13 ]

We have an upcoming project where we would like to install a Tyrus based Websocket client behind enterprise firewalls which can only communicate to a cloud hosted service via port 443 outbound. In such a deployment, it is possible that some of our customers may use an authenticated proxy on port 443 outbound. We would like to see client-side proxy support in Tyrus improved to handle this functionality so that we can offer this deployment option to our customers.

Our deployment architecture is similar to http://cloudbees.foxweave.com/images/blog/websockets-and-transparent-proxies/images/in-house-deployment-illustration.png (note that is not our project, but the FoxWeave agent running as a websocket client operating within the enterprise firewall operates in a somewhat similar manner).

Comment by Pavel Bucek [ 27/Aug/13 ]

Thanks for your comment!

Can you please list auth schemes which you consider as must-have?

Comment by jewel-sea [ 19/Dec/13 ]

I am more familiar with http style proxy auth than websocket style proxy auth (maybe they actually end up being the same thing). But I think the required auth mechanism would be basic auth and (potentially) digest auth.

Comment by kimiy [ 10/Mar/14 ]

We have same problem. We try to connect through client-side proxy, but proxy returns "HTTP/1.1 407 Proxy Authentication Required".

Comment by Pavel Bucek [ 10/Mar/14 ]

@kimiy: can you please add information about authentication scheme(s) your proxy supports/requires? Thanks!

Comment by kimiy [ 11/Mar/14 ]

Our proxy requires Basic authentication scheme.

Comment by Pavel Bucek [ 11/Mar/14 ]

@kimiy, can you please try following branch - just to see whether it will work for you?

https://github.com/pavelbucek/tyrus/tree/proxy-headers

(clone, build using "mvn clean install -Dmaven.test.skip" and then use Tyrus libraries version 1.6-SNAPSHOT)

It adds support for changing headers of request to be used as proxy "handshake". Simple usage is present in EchoTest:

            client.getProperties().put(GrizzlyClientSocket.PROXY_URI, "http://my.proxy:8080"); // or -Dhttp.proxyHost and -

final HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Proxy-Authorization", "Basic " + Base64Utils.encodeToString("username:password".getBytes(Charset.forName("UTF-8")), false));

client.getProperties().put(GrizzlyClientSocket.PROXY_HEADERS, headers);

Please try to replace "username:password" with your credentials. (I don't have any proxy which requires authentication currently available).

Also any comments about this (low-level) solution is also welcomed. I think we can come up with better, high level solution, something similar to jersey or apache http client, but that will require more time (and we will most likely start with standard authentication rather than jump into proxies).

Thanks and regards,
Pavel

Comment by kimiy [ 12/Mar/14 ]

I tried it, and I got success to connect through client-side proxy with authentication.
In our case, its solution works well.

Thank you so much.

Comment by Pavel Bucek [ 12/Mar/14 ]

great, thanks for confirmation. I'll clean up the code and merge this workaround to master branch.

Comment by mthornton [ 04/Apr/14 ]

The proxies we see are mostly Windows IIS with domain authentication. Our users want the authentication to proceed using cached credentials (i.e. the one used to login to Windows). The authentication schemes accepted are typically Negotiate, Kerberos and NTLM. Basic is NOT permitted.

The standard Java HttpURLConnection does manage to negotiate these proxies.





[TYRUS-406] RETRY_AFTER_SERVICE_UNAVAILABLE flag prevents onDisconnect from setting a delay Created: 21/Aug/15  Updated: 25/Jan/16

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.11
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: enwiner Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

If you set client.getProperties.put(ClientProperties.RETRY_AFTER_SERVICE_UNAVAILABLE, true) and also set up a ClientProperties.RECONNECT_HANDLER, you hit some strange behavior.

When the connection is closed, the code call the user's ReconnectHandler.onDisconnect() method. If that method returns true, it then calls ReconnectHandler.getDelay() to determine when to reconnect - but that method is overridden by the internal RetryAfterReconnectHandler.getDelay() method, so it will always return 0. I don't see a way to set a user-defined delay for the onDisconnect handler.






[TYRUS-404] Client hangs if i send recoursively Created: 27/Jul/15  Updated: 25/Jan/16

Status: Reopened
Project: tyrus
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: goleon Assignee: Pavel Bucek
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Sprint: Triaged

 Description   

Server side:

@ServerEndpoint("/tests/1client")
public class Tests1Client
{

    @OnOpen
    public void open(Session client) {
        System.out.println("/websocket - open");
    }


    @OnMessage
    public void shout(String text, Session client) throws InterruptedException, IOException
    {
        System.out.println("/websocket -> " + text);
        client.getBasicRemote().sendText(text + "!!!");
    }


    @OnClose
    public void close(Session client) {
        System.out.println("/websocket - close");
    }
}

Case 1: client sends 1000 messages and received 1000 responses. Appeared result is same as expected.
Client with iteration of messages sending:

import javax.websocket.*;
import java.net.URI;
import java.util.concurrent.*;

public class Client1
{
    private static final int MESSAGES_COUNT = 1000;
    public static final String URL = "ws://localhost:8080/jsr356/tests/1client";
    private static final String MESSAGE_50_SYMBOLS = "HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld";

    private long startTime;

    private final CountDownLatch messageLatch = new CountDownLatch(MESSAGES_COUNT);
    private ExecutorService exec;

    public void start()
    {
        try
        {
            exec = Executors.newFixedThreadPool(3);
            startTime = System.currentTimeMillis();

            ClientManager client = ClientManager.createClient();
            client.connectToServer(new Endpoint()
            {
                @Override
                public void onOpen(final Session session, EndpointConfig config)
                {
                    System.out.println("Client connected in time " + ((System.currentTimeMillis() - startTime) / 1000) + "s");

                    session.addMessageHandler(new MessageHandler.Whole<String>()
                    {
                        @Override
                        public void onMessage(String message)
                        {
                            System.out.println(" Client received message " + message);

                            messageLatch.countDown();

                        }
                    });
                    sendMessage(session);
                }

                @Override
                public void onClose(Session session, CloseReason closeReason)
                {
                    System.out.println("Client disconnected");
                }

                @Override
                public void onError(Session session, Throwable thr)
                {
                    System.out.println("Client received error");
                }
            }, ClientEndpointConfig.Builder.create().build(), new URI(URL));
            messageLatch.await();
            if (messageLatch.getCount() != 0)
            {
                System.out.println("Must be sent " + MESSAGES_COUNT + " but send only " + (MESSAGES_COUNT - messageLatch.getCount()));
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private void sendMessage(Session session)
    {
        final RemoteEndpoint.Async async = session.getAsyncRemote();
        for (int i = 0; i < MESSAGES_COUNT; i++)
        {
            final int index = i;
            exec.submit(new Callable<Object>()
            {
                @Override
                public Future<Void> call() throws Exception
                {

                    System.out.println("Try to send message " + " " + index + " " + MESSAGE_50_SYMBOLS);
                    async.sendText(index + " Message " + MESSAGE_50_SYMBOLS);
                    return null;
                }
            });
        }
    }

    public static void main(String[] args)
    {
        new Client1().start();
    }
}

Case 2: client should send message and receive response 1000 times (algorithm is recursive: next message sending client will make in onMessahe handler).
Client with recursive "ping-pong" messages sending:

import org.glassfish.tyrus.client.ClientManager;

import javax.websocket.*;
import java.net.URI;
import java.util.concurrent.*;

public class Client1_recursive
{
    private static final int MESSAGES_COUNT = 1000;
    public static final String URL = "ws://localhost:8080/jsr356/tests/1client";
    private static final String MESSAGE_50_SYMBOLS = "HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld";

    private long startTime;

    private final CountDownLatch messageLatch = new CountDownLatch(MESSAGES_COUNT);
    private ExecutorService exec;

    public void start()
    {
        try
        {
            exec = Executors.newFixedThreadPool(3);
            startTime = System.currentTimeMillis();

            ClientManager client = ClientManager.createClient();
            client.connectToServer(new Endpoint()
            {
                @Override
                public void onOpen(final Session session, EndpointConfig config)
                {
                    System.out.println("Client connected in time " + ((System.currentTimeMillis() - startTime) / 1000) + "s");

                    session.addMessageHandler(new MessageHandler.Whole<String>()
                    {
                        @Override
                        public void onMessage(String message)
                        {
                            System.out.println(" Client received message " + message);

                            messageLatch.countDown();

                            sendMessage(session);
                        }
                    });
                    sendMessage(session);
                }

                @Override
                public void onClose(Session session, CloseReason closeReason)
                {
                    System.out.println("Client disconnected");
                }

                @Override
                public void onError(Session session, Throwable thr)
                {
                    System.out.println("Client received error");
                }
            }, ClientEndpointConfig.Builder.create().build(), new URI(URL));
            messageLatch.await();
            if (messageLatch.getCount() != 0)
            {
                System.out.println("Must be sent " + MESSAGES_COUNT + " but send only " + (MESSAGES_COUNT - messageLatch.getCount()));
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private int i = 0;

    private void sendMessage(Session session)
    {
        final int index = i++;

        final RemoteEndpoint.Async async = session.getAsyncRemote();
        exec.submit(new Callable<Object>()
        {
            @Override
            public Future<Void> call() throws Exception
            {

                System.out.println("Try to send message " + " " + index + " " + MESSAGE_50_SYMBOLS);
                async.sendText(index + " Message " + MESSAGE_50_SYMBOLS);
                return null;
            }
        });
    }

    public static void main(String[] args)
    {
        new Client1_recursive().start();
    }
}

In recursive algorithm about 25 (or 74, or 90...) messages was sent, but client hanged , logs for example may be that:

Try to send message  21 HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld
 Client received message 21 Message HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld!!!
Try to send message  22 HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld
 Client received message 22 Message HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld!!!
Try to send message  23 HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld
 Client received message 23 Message HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld!!!
Try to send message  24 HelloWorldHelloWorldHelloWorldHelloWorldHelloWorld

As seen client sends message 24 ant it must be received on server, but in server logs i see that message is not received on server, and client hanged. Why?



 Comments   
Comment by Pavel Bucek [ 27/Jul/15 ]

This could be a bug but for different reason.

The latter usecase should not work at all - onMessage() method shouldn't be invoked in parallel for the same client. Tyrus should make sure that next onMessage() is not invoked before previous one is finished; we cannot assure in-order message delivery otherwise.

Comment by goleon [ 27/Jul/15 ]

Thanks,
could you explain this restriction please. It is from WebSocket transport or JSR 356 standard or from JSR server side or JSR client side implementation?

Comment by goleon [ 27/Jul/15 ]

And i removed concurrent tasks executor but problem still exists...

Comment by Pavel Bucek [ 27/Jul/15 ]

the "restriction" is from the JSR 356 itself - as I already mentioned, we cannot guarantee in-order message delivery otherwise. Client/Server side does not matter, since they are equal after WebSocket handshake.

I overlooked that you are sending the message from ExecutorService - in that case, it should work; leave it there and to jstack when it "hangs" and post it here, we might be able to find something unusual.





[TYRUS-417] JDK client connector hung when reply to CONNECT not received Created: 30/Nov/15  Updated: 25/Jan/16

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: 1.12
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: petrjanouch Assignee: petrjanouch
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Sprint: Team Drosera

 Description   

If a JDK client connector sends a CONNECT to a proxy and for some reason does not receive any reply, it is stuck forever.

There is a test fort this situation (currently ignored). See ProxyTest#testConnectStuck






[TYRUS-384] Call ClientEngine#processError properly from client Created: 22/Sep/14  Updated: 22/Sep/14

Status: Open
Project: tyrus
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Minor
Reporter: Ondrej Kosatka Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

There are still some piece of code where client attempt to connect failing and ClientEngine#processError should be called to invoke ClientHandshakeListener#onError and it does not.



 Comments   
Comment by Ondrej Kosatka [ 22/Sep/14 ]

https://github.com/okosatka/tyrus/tree/tyrus-384

Comment by Ondrej Kosatka [ 22/Sep/14 ]

Fixed: When connecting to proxy fails then CleintEngine#processError is called form both client implementations.





[TYRUS-378] Revise logged errors in client containers Created: 17/Sep/14  Updated: 17/Sep/14

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.8.3
Fix Version/s: None

Type: Improvement Priority: Minor
Reporter: petrjanouch Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Because of lack of an error handling method in client SPI, some errors in client containers were just logged. Revise errors logged in client containers and consider use of processError method from client SPI.






[TYRUS-372] Revise Match class Created: 03/Sep/14  Updated: 03/Sep/14

Status: Open
Project: tyrus
Component/s: core
Affects Version/s: 1.8.2
Fix Version/s: None

Type: Improvement Priority: Minor
Reporter: petrjanouch Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Match class contains methods that are used only in tests. Move such methods directly to the tests or investigate if the tests using those methods could not be rewritten to use Tyrus directly.






[TYRUS-323] Reuse TaskProcessor from Grizzly containers in JDK container Created: 19/May/14  Updated: 19/May/14

Status: Open
Project: tyrus
Component/s: client
Affects Version/s: 1.6
Fix Version/s: None

Type: Improvement Priority: Trivial
Reporter: petrjanouch Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

TaskProcesssor used in both Grizzly server and client container uses the same logic as TaskQueueFilter in JDK client






Generated at Mon Jan 23 22:23:37 UTC 2017 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.