简体   繁体   中英

Simultaneous request to the same endpoint from the same session create issue in Play

It seems like simultaneous call to the same endpoint from the same session is triggering some issue on the Play side.

Although the requests have different parameters, these parameters are sometimes copied (cached?) from the previous request.

here is how I setup the test to reproduce this:

routes:

GET /api/test   @com.standup75.TestController.test(test: String ?= null)
GET /api/testPage       @com.standup75.TestController.testPage()

TestController.java

....
public Result test(String test) {
    return ok("test = " + test);
}
public Result testPage() {
    return ok(views.test.render());
}

test.html.scala

@()

<h1>Test page</h1>
<ul id="log"></ul>

<script src="//code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
  $(function(){
    var $ul = $("#log");
    for (var i = 0; i < 20; i++) {
      (function(i){
        var url = "/api/test?test="+i;
        $.ajax({
          url: url,
          dataType: 'html',
          success: function(res){
            $ul.append("<li>url: " + url + " - result: " + res + "</li>");
          }
        });
      })(i)
    }
  });
</script>

And here is the surprising output of this when I go to /api/testPage:

Test page

url: /api/test?test=3 - result: test = 4
url: /api/test?test=5 - result: test = 2
url: /api/test?test=0 - result: test = 2
url: /api/test?test=1 - result: test = 4
url: /api/test?test=4 - result: test = 4
url: /api/test?test=2 - result: test = 3
url: /api/test?test=7 - result: test = 6
url: /api/test?test=8 - result: test = 8
url: /api/test?test=6 - result: test = 6
url: /api/test?test=9 - result: test = 10
url: /api/test?test=10 - result: test = 10
url: /api/test?test=11 - result: test = 11
url: /api/test?test=13 - result: test = 13
url: /api/test?test=14 - result: test = 14
url: /api/test?test=12 - result: test = 12
url: /api/test?test=17 - result: test = 16
url: /api/test?test=15 - result: test = 16
url: /api/test?test=16 - result: test = 16
url: /api/test?test=18 - result: test = 19
url: /api/test?test=19 - result: test = 19

The test value in the result is not always the same as the test param, which does not make sense to me?

I had the same issue a while ago when using Spring beans as controllers.

I see you are using controllers instances, not static methods (from @). Do you use play.mvc.Security.AuthenticatedAction by any chance? How do you create its instance? It needs to be a new instance for each request (prototype scope in Spring bean case), otherwise play will mix the requests in a non-deterministic way.

See https://groups.google.com/forum/#!topic/play-framework/EHl9mbafUlA

I work with the OP, we eventually figured it out. The issue was similar to what frant.hartm mentioned.

The controller inherits a base class that adds a number of Play Actions in the request delegate chain for all request using @With. Some of the Action types are also Spring components and default to singletons. When Play initializes the delegate chain for a request, the instances of these Actions may end up getting shared by multiple simultaneously served requests, and the last request to set up it's delegate chain gets to set the root action. Basically, a race condition on the "delegate" member of a shared Action.

The problem was resolved by adding @Scope("prototype") to the relevant Actions. Thanks to frant for the hint.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM