REST Assured and Concurrency

4,462 views
Skip to first unread message

Clyde Tan

unread,
Jan 25, 2016, 3:28:26 AM1/25/16
to REST assured
Hello everybody,

As it is recommended to statically import the classes, are the tests written in REST assured thread safe?

Thank you

Regards,
Clyde

Johan Haleby

unread,
Jan 25, 2016, 3:40:18 AM1/25/16
to rest-a...@googlegroups.com
Currently REST Assured is not entirely thread-safe. The API is written in a way that should allow for concurrency but under the covers it's not. I would be glad if you try it out though and report issues so that we can make it thread-safe in the future. 

/Johan

--
You received this message because you are subscribed to the Google Groups "REST assured" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rest-assured...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Clyde Tan

unread,
Jan 25, 2016, 3:58:15 AM1/25/16
to REST assured
Hi Johan,

Thank you for the information. We would like to help but this is not the right time for us to explore officially

Personally, will let you know if stumble into some issues

Regards,
Clyde

JP

unread,
Feb 11, 2016, 2:27:31 PM2/11/16
to REST assured
Hello - may have identified an issue with concurrency.  Here's some context about our setup:

Technologies:
Java: 7
RA: 2.3.0
TestNG: 6.9.10

Our setup for tests:
We're using TestNG to execute TestNG annotated test cases in parallel at the method level.  Each test calls through to the RA API to make http requests, sharing a static RequestSpecBuilder object.  Here's pseudo code of how we invoke the RA apis

RequestSpecification reqSpec;
// take static RequestSpecBuilder "reqSpecBuilder" and modify it: set base uri, add filters 
reqSpec = reqSpecBuilder.build();
 
// Call appropriate HTTP Method via the following
given(reqSpec).expect().spec(ResponseSpecification).log().all().[insert HTTP method signature here](String arg0, Object... arg1); 

CallStacks (our code omitted):

Exception java.lang.ArrayIndexOutOfBoundsException

Message: 2

Stacktrace:


at java.util.ArrayList.add(ArrayList.java:441)

at org.codehaus.groovy.runtime.DefaultGroovyMethods.leftShift(DefaultGroovyMethods.java:9177)

at org.codehaus.groovy.runtime.dgm$36.invoke(Unknown Source)

at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:71)

at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)

at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)

at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:55)

at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)

at com.jayway.restassured.internal.RequestSpecificationImpl.filter(RequestSpecificationImpl.groovy:479)

at com.jayway.restassured.builder.RequestSpecBuilder.addFilter(RequestSpecBuilder.java:335)

 

Exception java.util.ConcurrentModificationException

Message: (none)

Stacktrace:

at java.util.ArrayList$Itr.next(ArrayList.java:837)

at org.codehaus.groovy.runtime.DefaultGroovyMethods.findAll(DefaultGroovyMethods.java:3237)

at org.codehaus.groovy.runtime.DefaultGroovyMethods.findAll(DefaultGroovyMethods.java:3146)

at org.codehaus.groovy.runtime.dgm$175.invoke(Unknown Source)

at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)

at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)

at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)

at com.jayway.restassured.internal.SpecificationMerger.mergeFilters(SpecificationMerger.groovy:147)

at sun.reflect.GeneratedMethodAccessor124.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:606)

at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)

at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:148)

at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:99)

at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:169)

at com.jayway.restassured.internal.SpecificationMerger.merge(SpecificationMerger.groovy:105)

at com.jayway.restassured.internal.SpecificationMerger$merge.call(Unknown Source)

at com.jayway.restassured.internal.RequestSpecificationImpl.spec(RequestSpecificationImpl.groovy:742)

at com.jayway.restassured.RestAssured.given(RestAssured.java:747)


What I believe to be happening...
The problem: I think in parallel we're swapping out the values of our static RequestSpecBuilder object (because we aren't copying it, and I'm not sure RA is either).  We're then supplying the RequestSpecification as an argument to the RA static given(RequestSpecification) API.  When the RA code invokes in parallel, we end up with intermittent java.util container runtime exceptions because we appear to be concurrently modifying the contents of the RequestBuilder internal containers.

Are these Solution(s)?
1.  RA's static given(RequestSpecification) API could create it's own internal copies of any internal containers of the RequestSpecification object to prevent the clients from altering the container contents while RA's iterators are iterating over the container elements (and attempting to call add, remove, next, etc).
2.  RA clients could explicitly make sure they only build a RequestSpecification with unique non static RequestBuilder objects - RA could try to prevent RequestSpecification objects from being built by static RequestSpecBuilder objects.

Thoughts?

Thanks,
JP

JP

unread,
Feb 11, 2016, 2:36:13 PM2/11/16
to REST assured
Sorry - another option is to swap out standard java.util containers in this situation with the appropriate java.util.CopyOnWrite* containers, but that may have other downsides.

Johan Haleby

unread,
Feb 17, 2016, 4:09:41 AM2/17/16
to rest-a...@googlegroups.com
Thanks JP, I've not forgotten about you! I will look into this :) (But I'm very busy atm)

Johan Haleby

unread,
Feb 22, 2016, 11:35:51 PM2/22/16
to rest-a...@googlegroups.com
Do you really need to share a static RequestSpecBuilder? That doesn't sound right to me in the first place.
 

Are these Solution(s)?
1.  RA's static given(RequestSpecification) API could create it's own internal copies of any internal containers of the RequestSpecification object to prevent the clients from altering the container contents while RA's iterators are iterating over the container elements (and attempting to call add, remove, next, etc).

Yes this is a good option imo. Unfortunately I think it'll require some work (especially when it comes to merging specifications). 
 
2.  RA clients could explicitly make sure they only build a RequestSpecification with unique non static RequestBuilder objects - RA could try to prevent RequestSpecification objects from being built by static RequestSpecBuilder objects.

That's the option right now but in a good API you shouldn't need to worry about these kinds of things. Personally I'm a big fan of immutable data structures but RA is not built this way under the covers right now. I think the API (in most cases at least) would support immutability though and some things are already immutable (for example the configuration, which is awkward to some people but I believe that should be the way to go for the entire API).
Reply all
Reply to author
Forward
0 new messages