Using Gatling for testing Vaadin

Hello, I hope you’ll forgive me for being a beginner here but I have been searching all day for an answer to this question.

I am trying to use Gatling to load test our web application built using Vaadin.

I can open a web socket connect, push the login message and get the required response, but if I then send another push message the response is not as expected.

I am doing as the tutorial suggests and copying and pasting the messages as they appear in Chrome Developer Tools.

This is my request to move to the search URL, this is generated in Chrome by clicking on a “Searches” link (is the clicking step what I am missing?)

.sendText(“”“182|{“csrfToken”:”${seckey}“, “rpc”:[[”${location}“,“blah.blah.web.frontend.navigation.circle.rpc.ClientToServerRpc”,“notifyUriChanged”,[“search”]
]], “syncId”:3}”“”)

My response is then

273|for(;;);[{“syncId”: 3, “changes” :[[“change”,{“pid”:“0”},[“0”,{“id”:“0”,“location”:“http://v217s08r2643:8080/getit/#!-”}]
]], “state”:{}, “types”:{“1”:“6”,“0”:“0”}….

But I am expecting

25891|for(;;);[{“syncId”: 3, “changes” : [[“change”,{“pid”:“0”},[“0”,{“id”:“0”,“location”:“http://v217s08r2643:8080/getit/#!-/search”}]
],[“change”,{“pid”:“23”},[“24”,{“id”:“23”}]
]…

I hope you can help because it’s driving me crazy, and I’m sure it’s a simnple thing I am overlooking.

Thanks

Hi,

Hard to say what happens without seeing the full responses, but is your application doing some sort page(/ui) change on that action? At least you seem to be receiving “location” messages from the server. I think this should somehow be handled in you gatling scipts. Probably closing the old websocket communicaiton, getting the new host page and opening new communication like with your login page.

cheers,
matti

Thanks for your help, as this is all new to me, and I’d never encountered a web socket (that I was aware of) until yesterday I’m a little lost.

I obtain my CSRF and atmosphere key, then I open a socket and push my login message.

Request

523|{“csrfToken”:“${seckey}”, “rpc”:[[“0”,“com.vaadin.shared.ui.ui.UIServerRpc”,“resize”,[“968”,“1280”,“1280”,“968”]
],[“10”,“v”,“v”,[“text”,[“s”,“jamie”]
]],[“10”,“v”,“v”,[“c”,[“i”,“5”]
]],[“11”,“v”,“v”,[“text”,[“s”,“jamie”]
]],[“11”,“v”,“v”,[“c”,[“i”,“5”]
]],[“12”,“com.vaadin.shared.ui.button.ButtonServerRpc”,“click”,[{“metaKey”:false, “altKey”:false, “ctrlKey”:false, “relativeX”:“29”, “relativeY”:“27”, “clientY”:“476”, “clientX”:“796”, “shiftKey”:false, “button”:“LEFT”, “type”:“1”}]
]], “syncId”:1}

The response that I receive is as expected, which shows that the socket is open and I can communicate through it successfully.

4452|for(;;);[{“syncId”: 2, “changes” : [[“change”,{“pid”:“0”},[“0”,{“id”:“0”,“location”:“http://v217s08r2643:8080/getit/#!-”,“v”:{“action”:“”}},[“actions”,{}]
]],[“change”,{“pid”:“23”},[“24”,{“id”:“23”}]
],[“change”,{“pid”:“10”},[“1”,{“id”:“10”}]
],[“change”,{“pid”:“11”},[“2”,{“id”:“11”}]
]], “state”:{“22”:{“id”:“org_jamie_web_frontend_navigation_containers_BreadcrumbsAndContentContainer”,“height”:“100.0%”,“width”:“100.0%”,“styles”:[“full-screen-component”,“breadcrumbs-and-content”]
,“childData”:{“31”:{“expandRatio”:1,“alignmentBitmask”:5},“23”:{“expandRatio”:0,“alignmentBitmask”:5}}},“23”:{“templateContents”:“<div location="up-arrow"></div><div location="breadcrumbs"></div><div location="user"></div>”,“childLocations”:{“25”:“breadcrumbs”,“27”:“user”},“width”:“100.0%”,“styles”:[“top-bar”,“overlying-circle”]
},“33”:{“id”:“CircleNavigation_1416301228498”,“rpcInterfaces”:{“org.jamie.web.frontend.navigation.circle.rpc.ClientToServerRpc”:[“notifyUriChanged”]
},“enabled”:true,“resources”:,“immediate”:false,“readOnly”:false,“height”:“”,“callbackNames”:,“description”:“”,“width”:“”,“styles”:[“navigation-circle”]
},“25”:{“height”:“100.0%”,“width”:“100.0%”,“styles”:[“breadcrumbs”]
},“26”:{“styles”:[“link”,“small”,“logo”]
,“caption”:“GETIT”},“27”:{“styles”:[“user”]
},“11”:{“text”:“jamie”},“28”:{“resources”:{“icon”:{“uRL”:“fonticon://FontAwesome/f007”}},“styles”:[“link”,“small”]
,“caption”:“jamie”},“29”:{“resources”:{“icon”:{“uRL”:“fonticon://FontAwesome/f013”}},“description”:“Preferences”,“styles”:[“link”,“small”]
},“10”:{“text”:“jamie”},“30”:{“resources”:{“icon”:{“uRL”:“fonticon://FontAwesome/f08b”}},“description”:“Sign Out”,“styles”:[“link”,“small”]
},“32”:{“id”:“org_jamie_web_frontend_navigation_circle_view_CircleNavigationView1416301228498”,“height”:“100.0%”,“width”:“100.0%”,“styles”:[“dynamic-view”]
,“connectorToCssPosition”:{“33”:“”}},“5”:{“styles”:[“login-panel”]
},“31”:{“height”:“100.0%”,“width”:“100.0%”,“styles”:[“view-content”]
,“childData”:{“32”:{“expandRatio”:0,“alignmentBitmask”:5}}}}, “types”:{“22”:“27”,“23”:“24”,“33”:“25”,“25”:“26”,“26”:“3”,“27”:“28”,“11”:“2”,“28”:“3”,“29”:“3”,“2”:“6”,“10”:“1”,“1”:“7”,“0”:“0”,“30”:“3”,“32”:“29”,“5”:“7”,“31”:“17”}, “hierarchy”:{“22”:[“23”,“31”]
,“23”:[“27”,“25”]
,“33”:,“25”:[“26”]
,“26”:,“27”:[“28”,“29”,“30”]
,“11”:,“28”:,“29”:,“2”:,“10”:,“1”:[“3”,“22”]
,“0”:[“1”,“2”]
,“30”:,“32”:[“33”]
,“5”:[“6”,“9”,“13”,“19”]
,“31”:[“32”]
}, “rpc” : [[“2”,“com.vaadin.shared.extension.javascriptmanager.ExecuteJavaScriptRpc”,“executeJavaScript”,[“notvitic.navigation.ViewsNavigator.leafToCircle(‘org_jamie_web_frontend_navigation_containers_BreadcrumbsAndContentContainer’);”]
],[“2”,“com.vaadin.shared.extension.javascriptmanager.ExecuteJavaScriptRpc”,“executeJavaScript”,[“notvitic.navigation.ViewsNavigator.swapContainers(‘org_jamie_web_frontend_navigation_containers_FullScreenContainer’,‘org_jamie_web_frontend_navigation_containers_BreadcrumbsAndContentContainer’);”]
],[“33”,“org.jamie.web.frontend.navigation.circle.rpc.ServerToClientRpc”,“refresh”,[{“icon”:“-”,“children”:[{“icon”:“search”,“children”:
,“label”:“Searches”,“uri”:“search”},{“icon”:“maintain”,“children”:,“label”:“Maintain”,“uri”:“maintain”},{“icon”:“admin”,“children”:,“label”:“Admin”,“uri”:“admin”},{“icon”:“dataentry”,“children”:,“label”:“Data Entry”,“uri”:“dataentry”}],“label”:null,“uri”:“-”}]]], “meta” : {}, “resources” : {}, “typeMappings” : { “org.jamie.web.frontend.navigation.circle.view.CircleNavigationView” : 29 , “org.jamie.web.frontend.navigation.breadcrumbs.Breadcrumbs” : 26 , “org.jamie.web.frontend.navigation.circle.widget.CircleNavigation” : 25 , “com.vaadin.ui.AbsoluteLayout” : 30 , “org.jamie.web.frontend.views.common.AttachableCssLayout” : 31 , “org.jamie.web.frontend.navigation.containers.BreadcrumbsAndContentContainer” : 27 , “com.vaadin.ui.AbstractJavaScriptComponent” : 32 , “org.jamie.web.frontend.views.user.menu.UserMenuCircle” : 28 , “com.vaadin.ui.CustomLayout” : 24 }, “typeInheritanceMap” : { “29” : 30 , “26” : 31 , “25” : 32 , “16” : 19 , “30” : 11 , “31” : 7 , “17” : 21 , “6” : 23 , “18” : 19 , “2” : 15 , “27” : 17 , “19” : 13 , “22” : 10 , “10” : 18 , “11” : 20 , “32” : 19 , “7” : 11 , “28” : 7 , “15” : 16 , “24” : 11 , “0” : 22 , “3” : 19 , “20” : 19 , “1” : 15 , “21” : 11 , “23” : 13 }, “scriptDependencies”: [“published:///vCircleNavigation.js”]
, “timings”:[7, 0]
}]

There then appears to be a further message sent which I am replicating

353|{“csrfToken”:“ca54d523-f529-4a31-9ad0-18487247ac2e”, “rpc”:[[“2”,“com.vaadin.ui.JavaScript$JavaScriptCallbackRpc”,“call”,[“notvitic.navigation.ViewsNavigator.containersSwapped”,[“org_jamie_web_frontend_navigation_containers_FullScreenContainer”,“org_jamie_web_frontend_navigation_containers_BreadcrumbsAndContentContainer”]
]]], “syncId”:2}

and receiving the correct response for

272|for(;;);[{“syncId”: 3, “changes” : [[“change”,{“pid”:“0”},[“0”,{“id”:“0”,“location”:“http://v217s08r2643:8080/getit/#!-”}]
]], “state”:{}, “types”:{“1”:“7”,“0”:“0”}, “hierarchy”:{“1”:[“22”]
,“0”:[“1”,“2”]
}, “rpc” : , “meta” : {}, “resources” : {}, “timings”:[151, 0]
}]

At this point, on the application I would click on the searches link, which would take me to “http://v217s08r2643:8080/getit/#!-/search”

The request I am using is the same as recorded in Chrome

182|{“csrfToken”:“ca54d523-f529-4a31-9ad0-18487247ac2e”, “rpc”:[[“33”,“org.jamie.web.frontend.navigation.circle.rpc.ClientToServerRpc”,“notifyUriChanged”,[“search”]
]], “syncId”:3}

However the response is the same as the previous 272 character response above, so I am obviously missing some method of changing to the new URL. I can’t see anything that I am missing in the Chrome log though.

I have attached my Gatling script and the Chrome log for the above navigation. I really think that if I can understand this step then I should be ok (don’t hold me to that).

Thanks for your help

Jamie
17243.txt (3.76 KB)
17244.txt (59.9 KB)

Okay I’ve been looking at the logs and how they differ between a normal browser connection and one using Gatling and it seems that my request

182|{“csrfToken”:“ca54d523-f529-4a31-9ad0-18487247ac2e”, “rpc”:[[“33”,“org.jamie.web.frontend.navigation.circle.rpc.ClientToServerRpc”,“notifyUriChanged”,[“search”]
]], “syncId”:3}

Is being received and processed (the response is recorded in the log file) but that my client is not receiving the response for some reason.

The only difference between the logs is that this appears

[Wed Nov 2014 16:14:00.414]
DEBUG (org.apache.http.impl.conn.DefaultClientConnection:169) - Connection 0.0.0.0:49420<->192.168.5.82:8080 closed
[Wed Nov 2014 16:14:00.414]
DEBUG (org.apache.http.impl.conn.DefaultClientConnection:169) - Connection 0.0.0.0:49420<->192.168.5.82:8080 closed

In the log of the Gatling connection but not in the browser connection. This appears immediately after my response is produced.

So the question now is, how do I prevent this connection from closing?

Turns out that’s not the issue

It seems to be the # characters that are appearing on all of the Vaadin urls. Gatling doesn’t seem to be able to handle these easily :frowning:

Hi,

The fragment/anchor part of the url, the part that starts with #, is actually never communicated to the server by default. Vaadin, like many other modern web libraries, use that though to implement “back button support” for “ajax” apps. If you need to simulate a change from e.g. app.com/myapp/#!foo to app.com/myapp/#!bar, you can on both “page entries” just load app.com/myapp/. Vaadins server side gets the full url with the fragment part with the XHR/websocket communication with the subsequent request.

I hope this helps you to get forward!

cheers,
matti

Thanks for that, I wasn’t lying when I said this was all new to me! :slight_smile:

I’m back to thinking that the issue lies with the connection being unexpectedly closed. I’ve enabled full logging on Gatling and the log from when I send my message is shown below. I’m not sure if this issue is on the Vaadin side or the Gatling side though (I would guess Vaadin since it’s saying that the server closed the connection)

13:33:41.186 [DEBUG]
i.g.h.a.w.WsActor - Sending message check on WebSocket ‘gatling.http.webSocket’: TextMessage(182|{“csrfToken”:“349c1459
-8fb2-49e6-b4d5-7ba893b1d5ab”, “rpc”:[[“33”,“org.jamie.web.frontend.navigation.circle.rpc.ClientToServerRpc”,“notifyUriChanged”,[“search”]
]], “syncId”:3})
13:33:41.187 [DEBUG]
o.j.n.h.c.h.w.WebSocket08FrameEncoder - Encoding WebSocket Frame opCode=1 length=186
13:33:41.191 [DEBUG]
c.n.h.c.p.n.h.Processor - Channel Closed: [id: 0xb9c51eea, /192.168.2.48:58285 :> v217s08r2643/192.168.5.27:8080]
with
attribute INSTANCE
13:33:41.192 [INFO ]
i.g.c.c.Controller - End user #3298137887111428876-0
13:33:41.218 [DEBUG]
o.j.n.h.c.h.w.WebSocket08FrameDecoder - Decoding WebSocket Frame opCode=1
13:33:41.239 [DEBUG]
c.n.h.c.p.n.h.Processor - Channel Closed: [id: 0x6ea03df5, /192.168.2.48:58287 :> v217s08r2643/192.168.5.27:8080]
with
attribute NettyResponseFuture{currentRetry=0,
isDone=true,
isCancelled=false,
asyncHandler=com.ning.http.client.websocket.WebSocketUpgradeHandler@18dacb5,
nettyRequest=com.ning.http.client.providers.netty.request.NettyRequest@45ac2e,
content=NettyWebSocket{channel=[id: 0x6ea03df5, /192.168.2.48:58287 :> v217s08r2643/192.168.5.27:8080]
},
uri=ws://v217s08r2643:8080/getit/PUSH/?v-uiId=0&v-csrfToken=349c1459-8fb2-49e6-b4d5-7ba893b1d5ab&X-Atmosphere-tracking-id=0&X-Atmosp
here-Framework=2.1.5.vaadin4-jquery&X-Atmosphere-Transport=websocket&X-Atmosphere-TrackMessageSize=true&X-Cache-Date=0&Content-Type=applicat
ion%2Fjson%3B%20charset%3DUTF-8&X-atmo-protocol=true,
keepAlive=true,
httpHeaders=org.jboss.netty.handler.codec.http.DefaultHttpHeaders@2b129c,
exEx=null,
redirectCount=0,
timeoutsHolder=null,
inAuth=false,
statusReceived=false,
touch=103427058}
Simulation finished
13:33:41.347 [TRACE]
c.n.h.c.p.n.h.WebSocketProtocol - onClose {}
13:33:41.351 [TRACE]
c.n.h.c.p.n.h.WebSocketProtocol - Connection was closed abnormally (that is, with no close frame being sent).
13:33:41.353 [DEBUG]
c.n.h.c.p.n.c.ChannelManager - Closing Channel [id: 0x6ea03df5, /192.168.2.48:58287 :> v217s08r2643/192.168.5.27:8080]

13:33:41.355 [DEBUG]
i.g.h.a.w.WsActor - Websocket ‘gatling.http.webSocket’ closed by the server
13:33:41.365 [DEBUG]
c.n.h.c.p.n.h.Processor - Unexpected I/O exception on channel [id: 0x6ea03df5, /192.168.2.48:58287 :> v217s08r2643/192.
168.5.27:8080]
org.jboss.netty.handler.codec.frame.CorruptedFrameException: Max frame length of 10240 has been exceeded.
at org.jboss.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.protocolViolation(WebSocket08FrameDecoder.java:381) ~[netty
-3.9.4.Final.jar:na]
at org.jboss.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.decode(WebSocket08FrameDecoder.java:242) ~[netty-3.9.4.Fina
l.jar:na]
at org.jboss.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.decode(WebSocket08FrameDecoder.java:71) ~[netty-3.9.4.Final
.jar:na]
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.callDecode(ReplayingDecoder.java:500) ~[netty-3.9.4.Final.jar:na]

    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.messageReceived(ReplayingDecoder.java:435) ~[netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70) ~[netty-3.9.4.Final.jar

:na]
at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:108) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) [netty-3.9.4.Final.jar:na]

    at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) [netty-3.9.4.Final.jar:na]

    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.7.0_67]

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.7.0_67]

    at java.lang.Thread.run(Unknown Source) [na:1.7.0_67]

13:33:41.531 [DEBUG]
c.n.h.c.p.n.c.ChannelManager - Closing Channel [id: 0x6ea03df5, /192.168.2.48:58287 :> v217s08r2643/192.168.5.27:8080]

Thank you for your help Matti, talking to you and Stéphane over on the Gatling forums has led me to work out what the issue was myself (it was nothing to do with Vaadin either). Had to change the maximum frame size allowed by the websocket frame decoder. Sounds simple but these things always are after you work them out!