Windchill REST Services Framework Capabilities > Processing HTTP Requests for OData URLs
Processing HTTP Requests for OData URLs
The framework provides the default processing for HTTP requests made by clients to OData URLs.
OData URLs for EDM such as, https://windchill.ptc.com/Windchill/servlet/odata/ProdMgmt/$metadata, are processed by Domain Provider, Entity Provider, and Entity Delegate classes. The Domain Provider and Entity Provider classes read and process the configuration files. The Entity Delegate classes create the metadata response for entities in the domain.
OData URLs for entities and entity sets are processed by entity processor classes. The framework provides two types of processor classes, BasicEntityProcessor and PersistableEntityProcessor.
The BasicEntityProcessor class is used to process requests for entities and entity sets that are not mapped to Windchill persistables.
The PersistableEntityProcessor class is used to process requests made to entities and entity sets that are mapped to Windchill persistables.
A GET request to the URL for an entity set is processed by the PersistableEntityProcessor class. For example, consider a GET request to the URL https://windchill.ptc.com/Windchill/servlet/odata/ProdMgmt/Parts, which is processed by the PersistableEntityProcessor. While processing a GET request, the default processing logic of the framework reads the persistable objects of the mapped type, in this case WTParts from Windchill. Each object is converted into relevant OData entity. The framework then returns the entity set in the format requested by the client.
A GET request to the URL for an entity is also processed by the PersistableEntityProcessor class. For example, consider a GET request to the URL https://windchill.ptc.com/Windchill/servlet/odata/ProdMgmt/Parts(‘OR:wt.part.WTPart:87676’), which is processed by the PersistableEntityProcessor. In this case, the default processing in the framework reads the specific persistable object identified by the object reference in the URL, converts it to an entity, and then returns the entity representation in the requested format.
While processing a POST request on an entity set URL, the framework takes the entity representation provided in the POST body in the specified format, converts it into a Windchill persistable, and saves it to Windchill.
PATCH request to an entity URL reads the persistable, changes it, and then sends the updated representation in the response based on the requested format. DELETE request works similar to the PATCH request.
The framework enables customizers to override or enhance the default processing. When processing entity requests the framework searches for JavaScript implementation of hooks in the <Entity JS> file of the entity being processed. If hooks are found, then the framework executes the code they contain. Depending on the value returned by the hooks, the framework either continues its default processing or abandons it.
The JSDoc for in-built hooks is available at the following location:
https://windchill.ptc.com/Windchill/netmarkets/html/wrs/jsdoc/index.html
The hooks available in the framework are explained below:
Object readEntityData(EntityProcessorData processorData)
The framework calls this hook when the client sends a GET request to an entity instance. The hook is used to read the backing object from the store. The backing object is converted to an entity and returned to the client.
For basic REST entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, the hook is optional. The framework layer of Windchill REST Services provides a default implementation that uses Windchill APIs to read the persistable object from Windchill. If the hook is not implemented, then framework layer uses the default implementation to read the pesistable object. When the hook is implemented, it returns the backing persistable object for the entity to the framework. If the hook sets the continueProcessing flag to true in processorData, the object returned by the hook to the framework is ignored. In this case, the framework continues reading the backing object using the default implementation.
Collection<Object> readEntitySetData(EntityProcessorData processorData)
The framework calls this hook when the client sends a GET request to an entity set. The hook is used to read the collection of backing objects that belong to an entity set. The collection of backing objects is converted to an entity set and returned to the client.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, it is recommended not to override this hook as the framework provides a default implementation, which is optimized for features and performance. In its default implementation, the framework uses Windchill search APIs to search for objects in the entity set while honouring the $filter, $top, $skip parameters and server generated paging.
If you override the hook, you must provide performant implementation that honours the OData query parameters $filter, $top, $skip and server generated paging. When the hook is implemented it returns a collection of backing persistable objects. If no objects are found, the hook returns NULL.
If the hook sets the continueProcessing flag to true in processorData, the object collection returned by the hook is ignored. In this case, the framework uses the default implementation to read backing persistables, which belong to the entity set. It converts the persistable collection to an entity set, and returns the entity set to the client.
Map<Object, Collection> getRelatedEntityCollection(NavigationProcessorData processorData)
The framework calls this hook while navigating from source to target entities.
For both the basic REST and Windchill entities, this hook must be implemented for the navigation properties, which are explicitly specified in navigations section of the JSON configuration file of an entity. You must use Windchill service APIs to perform the navigation between persistables. It is recommended not to use the lower level persistence APIs. When you use the service APIs, it ensures that the business rules implemented in Windchill are honoured.
When the hook is implemented, it returns a map. The keys of the map are the source objects. The value of each key is a collection of target backing objects, which are persistable objects for Windchill that are obtained by navigating from the source.
Entity createEntityData(Entity entityToCreate, EntityProcessorData processorData)
This hook contains the complete logic for storing a persistable object in the data store. The storage begins with the entity that is sent to Windchill REST Services in the body of a POST request.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, the hook must not be implemented. Windchil REST Services provides a default implementation of the hook which:
1. Converts the entity that is passed in the body of the POST request to a persistable object
2. Stores the persistable object in Windchill
3. Retrieves the object from Windchill
4. Converts the object to an entity
5. Returns the entity representation to the caller
During the create process, the default implementation provides more granular hooks such as, operationPreProcess, storeNewObject, and operationPostProcess. Customizers should implement these granular hooks instead of the createEntityData hook, which represents the overall create process.
If the hook is implemented, it returns the entity that was created back to the framework. If the hook sets the continueProcessing flag to true, the entity returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Entity updateEntityData(Entity entityToUpdate, EntityProcessorData processorData)
This hook contains the complete logic for updating a persistable object in the data store. The update begins with the entity that is sent to Windchill REST Services in the body of a PATCH request.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, the hook must not be implemented. Windchil REST Services provides a default implementation of the hook which:
1. Reads the backing persistable object for the entity being updated
2. Changes those properties that are specified in the PATCH request
3. Stores the persistable object in Windchill
4. Retrieves the newly saved object from Windchill
5. Converts the object to an entity
6. Returns the entity representation to the caller
During the update process, the default implementation provides more granular hooks such as, operationPreProcess, saveObject, and operationPostProcess. Customizers should implement these granular hooks instead of the updateEntityData hook, which represents the overall update process.
If the hook is implemented, it returns the entity that was updated back to the framework. If the hook sets the continueProcessing flag to true, the entity returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
void deleteEntityData(Entity entityToDelete, EntityProcessorData processorData)
This hook contains the complete logic for deleting an entity. The logic includes finding and deleting the corresponding backing object in the data store for the entity being deleted.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, the hook must not be implemented. Windchil REST Services provides a default implementation of the hook which calls other more granular hooks, such as, operationPreProcess, deleteObject, operationPostProcess, and so on, when an entity is deleted. Customizers should implement these granular hooks instead of the deleteEntityData hook.
When the hook is implemented, it does not return anything back to the framework.
If the hook sets the continueProcessing flag to true, Windchill REST Services continues the default processing as if the hook was never implemented.
Map<Entity, Object> toObjects(Collection<Collection>, entitiesToConvert, EntityProcessorData processorData)
The framework calls this hook when it is converting entities to backing objects. For example, when clients create, update, delete, navigate, or expand entities.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, the framework provides a default implementation. The implementation uses the information from the request payload to construct the objects in memory. When the hook is implemented, it returns a map. The keys of the map are entities, and the value for each key is the backing object that corresponds to the key entity. If the hook sets the continueProcessing flag to true in processorData, the map returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Map<Object, Entity> toEntities(Collection<Object>objectsToConvert, EntityProcessorData processorData)
The framework calls this hook when it is converting backing objects to entities. For example, during the read, create, and update requests, navigations or expansions.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, the framework provides a default implementation. The implementation uses the information in the entity configuration to construct the entities from the objects.
When the hook is implemented, it returns a map. The keys of the map are objects, and the value for each key is the entity that corresponds to the key object.
If the hook sets the continueProcessing flag to true in processorData, the map returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Boolean isValidEntityKey(String key, EntityProcessorData processorData)
The framework calls this hook to validate the key (generally the property ID) of the entity. It is called during read, update or delete operations of an entity.
For basic entities, the implementation of the hook is optional. If the hook is not implemented, any key is considered valid.
For Windchill entities, there is default implementation provided in case the hook is not implemented.
If the hook sets the continueProcessing flag to true in processorData, the value returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Boolean isValidNavigation(String name, Object sourceObj, String id, EntityProcessorData processorData)
The framework calls this hook when navigating from source to target entities. The implementation of this hook should check if the navigation from a source object to a target is valid. The implementation returns:
true if the navigation is valid
false if the navigation is invalid
null if the navigation is not defined in the JSON file
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, this hook must be implemented for any navigation property specified in the entity JSON file.
If the hook sets the continueProcessing flag to true in processorData, the value returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Collection<AttributeData> processAdditionalAttributes(Entity entity, Object entityObject, EntityProcessorData processorData, PersistableEntityProcessor)
This hook is called by the framework when it has built a persistable and has not committed it to the database. The hook allows customizers to add and change attribute values on the persistable before committing it.
Object operationPreProcess(Object object, Entity entity, EntityProcessorData processorData, PersistableEntityProcessor)
The framework calls this hook during the create or update operation of an entity. The hook is called when the entity is converted to an object just before the create or update operation is performed on the object. The hook contains preprocessing logic for the object before the actual operation takes place. If the hook implementation throws the exception OdataApplicationException, the operation is aborted, and an error is returned to the caller.
The implementation of the hook is optional.
When the hook is implemented, it returns the object that must be used to execute the operation. If the hook returns a null value, the operation is aborted, and an error is returned to the caller.
void operationPostProcess(Object object, Entity entity, EntityProcessorData processorData, PersistableEntityProcessor)
The framework calls this hook during the create or update operation of an entity, after the operation is complete. The hook contains postprocessing logic. This logic is called in the same transaction as the operation itself. If the hook implementation throws the exception OdataApplicationException, the transaction is rolled back, the operation is aborted, and an error is returned to the caller.
The implementation of the hook is optional.
Object storeNewObject(Object, Entity, EntityProcessorData)
This hook is called during the create operation of a new entity. It is called to store the new object to the data store after the entity has been converted to a backing object.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, if this hook is not implemented, the default implementation is used. The default implementation uses persistence manager to store the object to the data store. If you want use Windchill APIs to store the object to the data store, the hook must be implemented to override the default processing logic.
void saveObject(Object entityObject, Entity entity, EntityProcessorData processorData)
This hook is called during the update operation of an entity. It is called to save the object to the data store after the entity has been converted to a backing object.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, if this hook is not implemented, the default implementation is used. The default implementation uses persistence manager to save the object to the data store. If you want use Windchill APIs to store the object to the data store, the hook must be implemented to override the default processing logic.
If the hook implementation throws the exception OdataApplicationException, the operation is aborted, and an error is returned to the caller.
If the hook sets the continueProcessing flag to true in processorData, the value returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Collection<Object> storeNewObjects(Map<Entity, Collection> entitiesToObjects, EntityProcessorData processorData)
This hook is called during the multiple create operation of new entities. It is called to store the new objects to the data store after the entities are converted to backing objects.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, if this hook is not implemented, the default implementation is used. The default implementation uses the persistence manager to store the objects to the data store. If you want to use other Windchill APIs to store the objects to the data store, the hook must be implemented to override the default processing logic.
If the hook implementation throws the ODataApplicationException exception, the operation stops, and an error message is returned to the caller.
If the hook sets the continueProcessing flag to true in processorData, the value returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Collection<Object> saveObjects(Map<Entity, Collection> entitiesToObjects, EntityProcessorData processorData)
This hook is called during the multiple update operation of entities. It is called to save the objects to the data store after the entities are converted to backing objects.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, if this hook is not implemented, the default implementation is used. The default implementation uses persistence manager to save the objects to the data store. If you want to use other Windchill APIs to store the objects to the data store, the hook must be implemented to override the default processing logic.
If the hook implementation throws the ODataApplicationException exception, the operation stops, and an error message is returned to the caller.
If the hook sets the continueProcessing flag to true in processorData, the value returned by the hook is ignored. In this case, Windchill REST Services continues with the default processing as if the hook was never implemented.
Map<Entity, Collection> multiOperationPreProcess(Map<Entity, Collection> entitiesToObjects, EntityProcessorData processorData, PersistableEntityProcessor entityProcessor)
The framework calls this hook during the multiple create or update operation of entities. The hook is called when the entities are converted to objects just before the multiple create or update operation is performed on the objects. The hook contains preprocessing logic for the object before the actual operation takes place. If the hook implementation throws the ODataApplicationException exception, the operation is stopped, and an error message is returned to the caller.
The implementation of the hook is optional. When the hook is implemented, it returns the objects that must be used to execute the operation. If the hook returns a null value, the operation stops, and an error message is returned to the caller.
void multiOperationPostProcess(List<Persistable> objectsToDelete, EntityCollection entities, EntityProcessorData processorData, PersistableEntityProcessor entityProcessor)
The framework calls this hook during multiple delete operation of entities, after the operation is complete. The hook contains post processing logic. This logic is called in the same transaction as the operation itself. If the hook implementation throws an exception, the transaction is rolled back, the operation is aborted, and an error is returned to the caller.
The implementation of the hook is optional. When the hook is implemented, it does not return anything back to the framework.
void deleteEntities(List<Persistable> objectsToDelete, OperationProcessorData processorData)
This hook contains the complete logic to delete multiple entities. The logic includes finding and deleting the corresponding backing objects in the data store for the entities being deleted.
For basic entities, domain authors must provide implementation of this hook. The framework does not provide implementation of this hook in its default processing.
For Windchill entities, if this hook is not implemented, the default implementation is used. The default implementation uses the delete API of persistence manager to delete the objects from the data store. If you want to use other Windchill service APIs to delete multiple objects from the data store, the hook must be implemented to override the default processing logic. When the hook is implemented, it does not return anything back to the framework.
All the hooks accept either EntityProcessorData or NavigationProcessorData parameter objects as input.
NavigationProcessorData—Contains information about source objects, target entity, entity set name, and so on which are required for navigating entity associations.
EntityProcessorData—Contains information which is required for processing a request to create, read, update, and delete entities.