I have a requirement where we need to send 3 entity sets in the URI
e.g., {serviceRoot}/Entity1('ID')/Entity2('ID')/Entity3
I have gone through the olingo git repo and could only find for 2 segments(for 3 segments a Not Implemented Exception
is thrown.
I want to understand if the URL({serviceRoot}/Entity1('ID')/Entity2('ID')/Entity3
) is valid?
Olingo Version used is 4.5
From a OData Sepcifiion point of view its perfectly fine to have 3 level or even n level 'navigation properties', the first segment of the URL is the Entity or Entity Set, and then you will have to create Navigation Properties, which are bound to(read return) and entity set or entity.
The reason you are getting an Not Implemented Exception
exception is if you read through the code of readEntityCollection
you will find the below segment
if (segmentCount == 2){ //navigation: e.g. DemoService.svc/Categories(3)/Products
Here its checking if the segment is the 3rd part and treats it as navigation property but if you go a level deeper it just has an else condition it throws the exception.
To achieve your purpose you will have to implement this logic in your code to go one(or even more) levels deeper
Below is the complete code for reference
public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, SerializerException {
EdmEntitySet responseEdmEntitySet = null; // for building ContextURL
EntityCollection responseEntityCollection = null; // for the response body
// 1st retrieve the requested EntitySet from the uriInfo
List<UriResource> resourceParts = uriInfo.getUriResourceParts();
int segmentCount = resourceParts.size();
UriResource uriResource = resourceParts.get(0); // the first segment is the EntitySet
if (! (uriResource instanceof UriResourceEntitySet)) {
throw new ODataApplicationException("Only EntitySet is supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(),Locale.ROOT);
}
UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) uriResource;
EdmEntitySet startEdmEntitySet = uriResourceEntitySet.getEntitySet();
if(segmentCount == 1){ // this is the case for: DemoService/DemoService.svc/Categories
responseEdmEntitySet = startEdmEntitySet; // first (and only) entitySet
// 2nd: fetch the data from backend for this requested EntitySetName
responseEntityCollection = storage.readEntitySetData(startEdmEntitySet);
}else if (segmentCount == 2){ //navigation: e.g. DemoService.svc/Categories(3)/Products
UriResource lastSegment = resourceParts.get(1); // don't support more complex URIs
if(lastSegment instanceof UriResourceNavigation){
UriResourceNavigation uriResourceNavigation = (UriResourceNavigation)lastSegment;
EdmNavigationProperty edmNavigationProperty = uriResourceNavigation.getProperty();
EdmEntityType targetEntityType = edmNavigationProperty.getType();
responseEdmEntitySet = Util.getNavigationTargetEntitySet(startEdmEntitySet, edmNavigationProperty);
// 2nd: fetch the data from backend
// first fetch the entity where the first segment of the URI points to
// e.g. Categories(3)/Products first find the single entity: Category(3)
List<UriParameter> keyPredicates = uriResourceEntitySet.getKeyPredicates();
Entity sourceEntity = storage.readEntityData(startEdmEntitySet, keyPredicates);
// error handling for e.g. DemoService.svc/Categories(99)/Products
if(sourceEntity == null) {
throw new ODataApplicationException("Entity not found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
}
// then fetch the entity collection where the entity navigates to
responseEntityCollection = storage.getRelatedEntityCollection(sourceEntity, targetEntityType);
}
}else{ // this would be the case for e.g. Products(1)/Category/Products
throw new ODataApplicationException("Not supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(),Locale.ROOT);
}
// 3rd: create and configure a serializer
ContextURL contextUrl = ContextURL.with().entitySet(responseEdmEntitySet).build();
final String id = request.getRawBaseUri() + "/" + responseEdmEntitySet.getName();
EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with().contextURL(contextUrl).id(id).build();
EdmEntityType edmEntityType = responseEdmEntitySet.getEntityType();
ODataSerializer serializer = odata.createSerializer(responseFormat);
SerializerResult serializerResult = serializer.entityCollection(this.srvMetadata, edmEntityType, responseEntityCollection, opts);
// 4th: configure the response object: set the body, headers and status code
response.setContent(serializerResult.getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
}