Overlapping Resource URI Templates

It is possible for the URI Templates of Application Express Listener RESTful Services to overlap, meaning that more than one URI Template can match a single URI. For example consider these two URI Templates:

employees/{id}
employees/{id}/manager

For the following URI path: employees/7469, which URI Template (and therefore which Resource Template and Resource Handler) should Application Express Listener choose?

Let’s look at an actual example, I’ve created a RESTful Service Module (with a URI prefix of: overlaps/) on apex.oracle.com:

curl -i https://apex.oracle.com/pls/apex/resteasy/overlaps/employees/7499
HTTP/1.0 200 Connection established

HTTP/1.1 200 OK
Date: Thu, 22 Aug 2013 09:20:16 GMT
Transfer-Encoding: chunked
Content-Type: application/json

{"empno":7499,"ename":"ALLEN","job":"SALESMAN","mgr":7698,"hiredate":"1981-02-20T00:00:00Z","sal":1600,"comm":300,"deptno":30}

That looks OK, we expect that the employees/{id} URI Template would be chosen and we expect that the result would be data about employee 7499, which this seems to be.

Now which URI Template will Listener choose for the following path: employees/7499/manager? Let’s find out:

curl -i https://apex.oracle.com/pls/apex/resteasy/overlaps/employees/7499/manager
HTTP/1.0 200 Connection established

HTTP/1.1 500 Internal Server Error
Date: Thu, 22 Aug 2013 09:23:49 GMT
Error-Reason: error="resource.template.evaluation"; error_description*=UTF-8''Error%20during%20evaluation%20of%20resource%20template%3a%20GET%20overlaps%2femployees%2f%7bid%7d%2c%20SQL%20Error%20Code%3a%201%2c722%2c%20SQL%20Error%20Message%3a%20ORA-01722%3a%20invalid%20number%0a
Connection: close
Content-Type: text/html; charset=UTF-8

...HTML error page omitted for clarity...

Hmm, that’s not what we expected, it looks like there’s a problem. Here’s the actual error message displayed on screen:
overlap

It says:

Error during evaluation of resource template: GET overlaps/employees/{id}, SQL Error Code: 1,722, SQL Error Message: ORA-01722: invalid number

Notice the error message says the employees/{id} URI Template is being chosen, not employees/{id}/manager, which leads to the SQL error because the string: 7499/manager cannot be converted to a number.

Why is Listener choosing employees/{id} over employees/{id}/manager? Well the simple fact is that both URI Templates do match the employees/7499/manager path. Listener has to choose one and in the absence of any other criteria Listener will choose the shortest URI Template.

Fixing the problem

To resolve this problem we must set the ‘priority’ value associated with the employees/{id}/manager URI Template to be higher than the priority associated with the employees/{id} URI Template. You can see the ‘priority’ setting here:
priority.

Listener will always choose the URI Template with the highest priority, thus giving employees/{id}/manager a priority of 1 and employees/{id} a priority of 0 means that Listener will choose employees/{id}/manager when processing a request for: employees/7499/manager.

To demonstrate this I created two more Resource Templates in the overlaps/ RESTful Service Module, with the priorities fixed. Let’s try them out:

curl -i https://apex.oracle.com/pls/apex/resteasy/overlaps/fixed/employees/7499
HTTP/1.0 200 Connection established

HTTP/1.1 200 OK
Date: Thu, 22 Aug 2013 09:54:08 GMT
ETag: "A7rDBCEuC8pkiZrA7ifn7kkAgPUxn2ZjMTV03VhNSJ9Pl9QvCDF09UKXBa8DGE6128D5rJxjYOE2cXHp+npe0Q=="
Content-Type: application/json

{"empno":7499,"ename":"ALLEN","job":"SALESMAN","mgr":7698,"hiredate":"1981-02-20T00:00:00Z","sal":1600,"comm":300,"deptno":30}

As before the employee details for 7499 are returned as expected, now let’s try the employees/7499/manager URI:

curl -i https://apex.oracle.com/pls/apex/resteasy/overlaps/fixed/employees/7499/manager
HTTP/1.0 200 Connection established

HTTP/1.1 200 OK
Date: Thu, 22 Aug 2013 09:54:57 GMT
ETag: "Luk37RW0IusktYysyhni7hfCLAa+e2/NvuVkwjSwIe9Dc0Oa3tLeKOdC/Z9MPA7LEZhYn/CHNlLYnZ6flZmT2A=="
Content-Type: application/json

{"uri":{"$ref":"https://apex.oracle.com/pls/apex/resteasy/overlaps/fixed/employees/7698"},"ename":"BLAKE"}

Great! it’s working now.

Conclusion

The rule of thumb for assigning URI Template priorities is:

Give the most specific URI Template the highest priority, give the least specific URI Template the lowest priority.