Bug 976786 - Creating content-based resource ends up with IndexoutOfBoundsException
Summary: Creating content-based resource ends up with IndexoutOfBoundsException
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: RHQ Project
Classification: Other
Component: REST
Version: 4.8
Hardware: Unspecified
OS: Unspecified
unspecified
high
Target Milestone: ---
: RHQ 4.9
Assignee: Heiko W. Rupp
QA Contact: Mike Foley
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2013-06-21 13:04 UTC by Libor Zoubek
Modified: 2015-11-02 00:43 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2014-03-26 08:32:08 UTC
Embargoed:


Attachments (Terms of Use)

Description Libor Zoubek 2013-06-21 13:04:08 UTC
Description of problem:


Version-Release number of selected component (if applicable):


How reproducible: always


Steps to Reproduce: Create content-based resource

1. Upload content to get file handle

2. POST /rest/resource?handle=<handle>
with body:

{'resourceName':'hello.war','parentId':<ID>,'typeName':'Deployment','pluginName':'JBossAS7','resourceConfig':{'runtimeName':'hello.war'}}

or:

{'resourceName':'hello.war','parentId':<ID>,'typeName':'Deployment','pluginName':'JBossAS7'}

NOTE: if you do not pass 'resourceConfig', new deployment would be called "default.rest.package" - which is imho another bug. Comparing it to "UI way", 'runtimeName' is optional parameter, and if not passed, name of uploaded file is taken instead. There is no file name in context of REST api, but we have resourceName ( which is on the other hand not present when creating using UI ). It makes sense to use resourceName by default.


Actual results:

Resource is successfully created (validated child history and new deployment using UI)

I get
{"message":"java.lang.IndexOutOfBoundsException: Index: 0, Size: 0"}

as a response. Server's stacktrace:

Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
        at java.util.ArrayList.rangeCheck(ArrayList.java:604) [rt.jar:1.7.0_09-icedtea]
        at java.util.ArrayList.get(ArrayList.java:382) [rt.jar:1.7.0_09-icedtea]
        at org.rhq.enterprise.server.rest.ResourceHandlerBean.findCreatedResource(ResourceHandlerBean.java:923) [rhq-enterprise-server-ejb3.jar:4.8.0-SNAPSHOT]
        at org.rhq.enterprise.server.rest.ResourceHandlerBean.getHistoryItem(ResourceHandlerBean.java:890) [rhq-enterprise-server-ejb3.jar:4.8.0-SNAPSHOT]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_09-icedtea]

It looks like server redirects me to retrieve creationStatus with wrong parameters

Expected results: ? = this is not clear from documentation. I guess I should get body with creation history


Additional info:

Comment 1 Heiko W. Rupp 2013-06-24 16:09:44 UTC
Libor, there is an example of such a resource creation at 
org.rhq.modules.integrationTests.restApi.ContentTest#testCreatePackageBasedResource
can you tell me the difference to your case above?
Perhaps even add your failure to the above test class as an additional test?

Comment 2 Libor Zoubek 2013-06-24 21:58:00 UTC
I am sending same data as your test, in fact I've been looking at it when writing my example.

I probably found out. I am using requests python client library, which by default follows server redirects. So client immediately follows (because server sends 302 and redirects it to creationStatus). 

I tried to forbid following redirects by client, and I got empty response with Location header pointing to creationStatus. This url returns new resource after some time (I didn't catch it when it was returning status . so not sure if that really happens)

It looks like a findCreatedResource method expects that resource to exist.

Weird enough, because calling findCreatedResource happens only when:

if (status== CreateResourceStatus.SUCCESS) {

            ResourceWithType rwt = findCreatedResource(history.getParentResource().getId(),history.getCreatedResourceName(),uriInfo);

            builder = Response.ok();
            setCachingHeader(builder, 600);
            builder.entity(rwt);

        }

This means then even if creationStatus becomes SUCCESS, there might be a timeslot, when new resource is not yet imported.

As an example you can run https://github.com/rhq-project/samples/blob/master/rest-api/python/create_as7_deployment.py

Btw, I am not sure, if it is a good idea for GET /rest/creationStatus/<ID> to send 302 when creation is in progress, some clients may be "smart" and detect infinite loop redirects (browsers do that afaik)

Comment 3 Heiko W. Rupp 2013-07-24 10:05:30 UTC
master 1ceae7f adds a check for SUCCESS status to see if the resource is really there (*1). If not it returns IN_PROGRESS.

Sending a 302 is a common pattern to tell a client to return back with a GET request to check for the results of a POST (*2). A 303 code would have been better I guess, but a 302 is ok. See http://en.wikipedia.org/wiki/HTTP_status_code#3xx_Redirection

In fact we pause a bit until we respond, so the user should not run into endless recursion with the 302 code.

1) looks like there are timing issues that don't matter when the user is in the UI, as a human is slower than a script
2) Our BZ instance violates that pattern.

Comment 4 Heiko W. Rupp 2014-03-26 08:32:08 UTC
Bulk closing now that 4.10 is out.

If you think an issue is not resolved, please open a new BZ and link to the existing one.


Note You need to log in before you can comment on or make changes to this bug.