You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@chemistry.apache.org by "Florian Müller (JIRA)" <ji...@apache.org> on 2015/03/06 16:16:38 UTC

[jira] [Resolved] (CMIS-896) Improve how JSON response of CMIS query function is built

     [ https://issues.apache.org/jira/browse/CMIS-896?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Florian Müller resolved CMIS-896.
---------------------------------
       Resolution: Fixed
    Fix Version/s: OpenCMIS 0.13.0

The improvement covers this specific case:
A server response contains at least one object and the client requested the cmis:objectId property but not the cmis:objectTypeId property and/or the object has secondary type properties that the client also requested. Although, queries are the mostly likely candidates for this scenario, other operations are also affected (getObject(), getChildren(), etc.).

Two things have changed:
- getObject() is not called for each returned object, but only if it is necessary. That is, it is only called if a property should be returned and its property definition has not been fetched before for this response. That reduces the number of getObject() calls in many cases to one per response. No server implementation code change is necessary to benefit from this change.
- To avoid even the last getObject() call, server implementations can attach a property definition to their PropertyData objects. The Property*Impl classes got new constructors that take the property definition instead of the property ID. Server implementations that use their own PropertyData implementations have also to implement the PropertyDataWithDefinition interface if they want to use this new optimization. 

> Improve how JSON response of CMIS query function is built
> ---------------------------------------------------------
>
>                 Key: CMIS-896
>                 URL: https://issues.apache.org/jira/browse/CMIS-896
>             Project: Chemistry
>          Issue Type: Improvement
>          Components: opencmis-server
>    Affects Versions: OpenCMIS 0.12.0
>            Reporter: Nicolas Brandt
>            Assignee: Florian Müller
>            Priority: Minor
>             Fix For: OpenCMIS 0.13.0
>
>         Attachments: query.patch
>
>
> JSON responses of CMIS queries seems to be built in an inefficient way.
> {code:java|title=org.apache.chemistry.opencmis.commons.impl.JSONConverter.java}
>     /**
>      * Converts a bag of properties.
>      */
>     public static JSONObject convert(final Properties properties, final String objectId, final TypeCache typeCache,
>             final PropertyMode propertyMode, final boolean succinct, final DateTimeFormat dateTimeFormat) {
>         if (properties == null) {
>             return null;
>         }
>         // get the type
>         TypeDefinition type = null;
>         if (typeCache != null) {
>             PropertyData<?> typeProp = properties.getProperties().get(PropertyIds.OBJECT_TYPE_ID);
>             if (typeProp instanceof PropertyId) {
>                 String typeId = ((PropertyId) typeProp).getFirstValue();
>                 if (typeId != null) {
>                     type = typeCache.getTypeDefinition(typeId);
>                 }
>             }
>             if (type == null && objectId != null && propertyMode != PropertyMode.CHANGE) {
>                 type = typeCache.getTypeDefinitionForObject(objectId);
>             }
>         }
>         JSONObject result = new JSONObject();
>         for (PropertyData<?> property : properties.getPropertyList()) {
>             assert property != null;
>             assert property.getId() != null;
>             PropertyDefinition<?> propDef = null;
>             if (typeCache != null) {
>                 propDef = typeCache.getPropertyDefinition(property.getId());
>             }
>             if (propDef == null && type != null) {
>                 propDef = type.getPropertyDefinitions().get(property.getId());
>             }
>             if (propDef == null && typeCache != null && objectId != null && propertyMode != PropertyMode.CHANGE) {
>                 typeCache.getTypeDefinitionForObject(objectId);
>                 propDef = typeCache.getPropertyDefinition(property.getId());
>             }
>             String propId = (propertyMode == PropertyMode.QUERY ? property.getQueryName() : property.getId());
>             if (propId == null) {
>                 throw new CmisRuntimeException("No query name or alias for property '" + property.getId() + "'!");
>             }
>             result.put(propId, convert(property, propDef, succinct, dateTimeFormat));
>         }
>         return result;
>     }
> {code}
> According to the quoted source code, building the JSON response of query {{select cmis:objectId, cmis:name from cmis:document}} requires to call the function ObjectService.getObjectById per each row returned.
> When the query returns 1000 rows and the CMIS server is backed with a database it causes a significant performance slowdown.
> For example with the two following queries (each of them returns 1000 rows):
>  bq. select * from cmis:document
>  bq. select cmis:objectId, cmis:name from cmis:document
> The second one is more than 5x slower than the first one.
> A solution may be to add PropertyType and Cardinality informations into PropertyData objects, so it's no longer necessary to retrieve properties definitions.
> I have attached a svn diff file with the changes.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)