Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

SCL-2607 Fixed issue with FindRowWhere on server with match close to the end of the query result list

Description:

We've fixed an issue in the DataAccess FindRowWhere method that when the match was close to the end of the queries result list might have caused an invalid query string with the INDEXED-REPOSITION keyword appearing twice in the fetch query string.

SCL-2754 Resolved errors during regeneration of large Business Entity

Description:

During the regeneration of larger business entities, the error
DITEM is not large enough to hold string. (4043).
might have been raised by the AVM. We've resolved those issues by changing the way how we modify existing source code.

SCL-2760 Business Entity Designer and Generator now validate that all temp-table indexes have at least a single field

Description:

The Business Entity Designer and Generate have been enhanced to validate that all indexes have at least a single field. Indexes without fields might habe caused compile errors in the temp-table definitions and have caused duplicate signature definitions in the DatasetModel and Query constructors.

SCL-2763 Fixed an issue retrieving Object Instances using JSDO Generic Service

Description:

We have resolved an issue with the generation of the query string that might have been raised when retrieving repository data from the ObjectMasterBusinessEntity using the JSDO generic service:

No Format

Unable to prepare query: eSmartObjectInstance.ObjectMasterGuid EQ "ad7c5f60-68e4-d28e-5314-77e12cce2962" , FIRST b_SmartObjectMaster OF SmartObjectInstance
Client-Query: eSmartObjectInstance.ObjectMasterGuid EQ "ad7c5f60-68e4-d28e-5314-77e12cce2962"
Default-Query: FOR EACH SmartObjectInstance, FIRST b_SmartObjectMaster OF SmartObjectInstance

...

SCL-2769 Fixed issues with using Date values in the InputPromptHelper:ComplexInput

Description:

We've resolved issue in the ComplexInputDateControl class that might have caused the error message

No Format
** Invalid date input. (85)


when typing an incomplete date. This has been resolved now.

SCL-2772 Fixed an issue with SmartBusinessEntityAdapter adding wrong sort phrase

Description:

We have resolved an issue where the SmartBusinessEntityAdapter was adding the default sort phrase to the wrong buffer. When the QueryString property of the SmartBusinessEntityAdapter was set with queries for multiple buffers CHR(1) delimited and the QuerySort property was empty. The SmartBusinessEntityAdapter uses the temp-table's primary index sort criteria instead of the QuerySort property. However, this was added to the end of the QueryString property instead of adding it to the first entry (query string of the EntityTable). This has been fixed.

Improvement

SCL-2615 Added details about context to UnsupportedReturnTypeException exception

Description:

When the generation of a Swagger documentation for a Business Entity fails due to issues with the method's return-type, we're now adding details about the name of the method causing this issue to the Exception.

SCL-2723 Improved performance of ContextDatasetStore by using JSON instead of XML

Description:

We have implemented the class Consultingwerk.Framework.Server.JsonContextDatasetStore as an alternative IContextDatasetStore implementation. This class uses JSON to store the context dataset between HTTP requests to the PASOE. We've identified a 10% performance improvement for short HTTP requests by this change.
The XML based ContextDatasetStore is still provided for backwards compatibility.

SCL-2752 SmartHttpClient now inherits from HttpClientDecorator

Description:

The Smart HttpClient as a decorator of the HttpClient now leverage the abstract base class HttpClient Decorator. This should allow inheriting potential future enhancements made by Progress Software and is also the foundation for allowing the HttpClient Builder to use this class the default decorator of the HttpClient .

SCL-2756 protop Launcher (SmartComponent Library desktop) now reads DLC from dblist.cfg

Description:

To allow connections to DB's of various OpenEdge releases, we now retrieve the value for the DLC variable when launching protop from the Studio Desktop from the protop configuration.

SCL-2758 Improved error message when retrieving repository data for a container with an invalid instance

Description:

We now provide further details for issues with inconsistent repository data found during retrieving a container from the SmartFramework repository.

SCL-2759 Extend Factory/Builder of OpenEdge HttpClient to return SmartHttpClient by default

Description:

We have implemented the class Smart[ HttpClient Service| HttpClient Service] which should be loaded as a service via a service.xml file when the session starts (it's important that it's loaded that way so the initialize method gets called). After that class has been loaded, it registers the Smart HttpClient as a decorator to the HttpClient class so that there's no longer the need to manually load the Smart HttpClient decorator, the HttpClient Builder will take care of that. So when executing

Code Block
languageabl

oResponse = ClientBuilder:Build():Client:Execute(RequestBuilder:Get("http://www.spiegel.de":U):Request) .


the request will automatically be using the Smart[ http Client| http Client] and provide the error handling by throwing ABL errors instead of just returning an http status code.

SCL-2767 Performance improvements in the StringHelper:FirstOccurenceOf method

Description:

We have improved the performance of the StringHelper:FirstOccurenceOf method by 10 - 20%. This method is used a few times within the QueryParser implementation.

SCL-2768 Simplify handling of query flags in Data Access classes

Description:

When retrieving data through a Business Entity and Data Access class the consuming application typically provides selection criteria through a query string or mechanisms like named queries. These query conditions are typically concatenated to the source default query implemented in the data access. The source default query hereby defines the maximum set of records from the source tables the client application can retrieve. The client application can only select (filter) within this set of data. The source default query provides a means of implementing row level security in the Data Access class.
There are rare cases where it is however desired to consider the source default query as a default and allow the client application to influence the source default query through the query string. In the following we refer to the specific selection criteria which will allow customization of the source default query as query flags.
With the API’s introduced here we support two use cases for query flags:
- Removing a selection criteria from the source default query, e.g. a filter by a row status (e.g. Deleted = false, OrderStatus = Ordered)
- Providing additional options (valid values) for a field which is present in the source default query (e.g. OrderStatus = Ordered should become OrderStatus = Ordered or OrderStatus = Shipped or OrderStatus = Partially Shipped). In this case values provided by the client need to be OR’ed with the value(s) for this field specified in the source default query.
Implementation of the use-cases has been possible before the implementation of this ticket. The new API’s in introduced in this feature are however providing a simplification.
Foundation of those API’s is the QueryParser which splits the selection criteria passed by the client in the IFetchDataRequest instance into a list of QueryExpression object. The QueryParser is frequently used in the DataAccess:FetchData method in the context of query optimization (e.g. switching the buffer sequence in the DATA-SOURCE query). As the result of the QueryParser may now also be used for the handling of query flags, we have added the QueryExpression property to the IFetchDataRequest interface (the property has previously already been added to the FetchDataRequest implementation, so that this now only resolves the need for frequent CAST’ing of poFetchDataRequest to the implementing type). The parsing of the query string provided by the client application can now be achieved by calling the PROTECTED method ParseTopBufferRequestQuery() in the Consultingwerk.OERA.DataAccess class.

Code Block
languageabl

    METHOD PUBLIC OVERRIDE VOID FetchData (poFetchDataRequest AS IFetchDataRequest):

        DEFINE VARIABLE oParser AS QueryParser NO-UNDO .

        oParser = NEW QueryParser () .

        poFetchDataRequest:QueryExpression = THIS-OBJECT:ParseTopBufferRequestQuery (poFetchDataRequest) .

        SUPER:FetchData(poFetchDataRequest) .

    END METHOD.


For the first use case listed above (ability to remove a default selection criteria from the source default query, code similar to the following block of code may be implemented in the SourceDefaultQuery method of the Data Access class. In this example, the default source default query is

Code Block
languageabl

FOR EACH Order WHERE Order.OrderStatus = ‘Ordered’ INDEXED-REPOSITION


The client can pass in the following pseudo selection criteria in the client query string

Code Block
languageabl

eOrder.OnlyOrdered = FALSE 


which will cause the following sample implementation of the SourceDefaultQuery method to return just

Code Block
languageabl

FOR EACH Order INDEXED-REPOSITION


as the default selection criteria. Nether in the database table nor in any temp-table a column named OnlyOrdered exists.

Code Block
languageabl

    METHOD OVERRIDE PUBLIC CHARACTER SourceDefaultQuery (pcTable AS CHARACTER):

        /* Handle OnlyOrdered = FALSE */
        DEFINE VARIABLE oOnlyOrdered AS QueryExpression NO-UNDO .

        @SourceDefaultQueryCaseBlock.
        CASE pcTable:
            WHEN "eOrder":U THEN DO:
                IF VALID-OBJECT (THIS-OBJECT:FetchDataRequest:QueryExpression) THEN
                    oOnlyOrdered = QueryExpression:GetExpressionForField ("eOrder.OnlyOrdered",
                                                                          THIS-OBJECT:FetchDataRequest:QueryExpression) .

                IF VALID-OBJECT (oOnlyOrdered) AND oOnlyOrdered:SecondOperandAsLogical() = FALSE THEN
                    RETURN "FOR EACH Order INDEXED-REPOSITION":U .
                ELSE
                    RETURN "FOR EACH Order WHERE Order.OrderStatus = 'Ordered' INDEXED-REPOSITION":U.
            END.

        END CASE .

    END METHOD.


The implementation of the method uses the result of the QueryParser stored in the QueryExpression property of the current IFetchDataRequest instance. The static QueryExpression:GetExpressionForField (singular) method has been previously existing, the SecondOperandAsLogical() instance method of the QueryExpression class has been asses now to avoid CAST’ing the SecondOperand property of the QueryExpression instance to an ILogicalHolder or ICharacterHolder to retrieve the value of the OnlyOrdered selection in the query string.
For the second use case described above (providing additional valid values for a field already contained in the source default query), code similar to the following sample implementation of the SourceDefaultQuery method in the DataAccess class can be used. In this example, the default source default query is

Code Block
languageabl

RETURN "FOR EACH Order WHERE Order.SalesRep = 'HXM' INDEXED-REPOSITION":U.


and the client may provide additional valid salesrep’s in the query string, e.g. by providing

Code Block
languageabl

eOrder.SalesRep = ‘BBB’ or eOrder.SalesRep = ‘DOS’


in the FetchDataRequest:Queries property. The resulting source default query in this example must OR the values provided by the client query with the value in the default source default query, e.g.

Code Block
languageabl

RETURN "FOR EACH Order WHERE (Order.SalesRep = 'HXM' or Order.SalesRep = ‘BBB’ or Order.SalesRep = ‘DOS’ INDEXED-REPOSITION":U.


Code Block
languageabl

    METHOD OVERRIDE PUBLIC CHARACTER SourceDefaultQuery (pcTable AS CHARACTER):

        DEFINE VARIABLE oSalesRep AS ListQueryExpression NO-UNDO .

        @SourceDefaultQueryCaseBlock.
        CASE pcTable:
            WHEN "eOrder":U THEN DO:
                IF VALID-OBJECT (THIS-OBJECT:FetchDataRequest:QueryExpression) THEN
                    oSalesrep = QueryExpression:GetExpressionsForField ("eOrder.Salesrep",
                                                                        "Order.Salesrep",
                                                                        THIS-OBJECT:FetchDataRequest:QueryExpression) .

                IF VALID-OBJECT (oSalesrep) AND NOT oSalesRep:IsEmpty THEN
                    RETURN SUBSTITUTE ("FOR EACH Order WHERE (Order.SalesRep = 'HXM' or &1) INDEXED-REPOSITION":U,
                                       oSalesrep:GetExpression()) .

                ELSE
                    RETURN "FOR EACH Order WHERE Order.SalesRep = 'HXM' INDEXED-REPOSITION":U.
            END.

        END CASE .

    END METHOD.


The implementation of the method uses the result of the QueryParser stored in the QueryExpression property of the current IFetchDataRequest instance. The new static QueryExpression:GetExpressionsForField (plural) method has been implemented to filter the list of query expressions for a single field. This method also supports providing the required field mapping of the eOrder.Salesrep field in the temp-table to the database field Order.SalesRep required in the source default query. The GetExpresison() method of the oSalesrep instance (ListQueryExpression class) returns the selection criteria provided by the client with the OR operator.
In order to prevent the query processing of the DataAccess class (implemented in the QueryString class) from handling the SalesRep field again when merging the source default query with the FetchDataRequest:Queries, the SourceColumn method can be extended like this to return no mapping for those fields anymore:

Code Block
languageabl
     METHOD OVERRIDE PUBLIC CHARACTER SourceColumn (pcTable AS CHARACTER, pcColumn AS CHARACTER):

        DEFINE VARIABLE cMap  AS CHARACTER NO-UNDO .
        DEFINE VARIABLE iPos  AS INTEGER   NO-UNDO .

        /* When the query expression contains Salesrep, this will be handled
           in SourceDefaultQuery, so ignore the field in the client query */
        IF THIS-OBJECT:IsQueryFlagPresent (pcColumn, "eOrder.SalesRep") THEN
            RETURN ? .

        @SourceColumnCaseBlock.
        CASE pcTable:
            WHEN "eOrder":U THEN
                cMap = BUFFER eOrder:DATA-SOURCE-COMPLETE-MAP .

        END CASE .

        ASSIGN iPos = LOOKUP(pcColumn, cMap) .

        IF iPos MODULO 2 = 1 THEN
            RETURN ENTRY(LOOKUP(pcColumn,cMap) + 1,cMap).
        ELSE
            RETURN "":U .

    END METHOD.


The PROTECTED IsQueryFlagPresent() method of the DataAccess class is checking the current column name against the comma delimited list of columns interpreted as query flags (just eOrder.SalesRep in this example) and checks if that column is contained in the QueryExpression stored in the current FetchDataRequest instance. By returning ? from SourceColumn, this method indicates that the field should not mapped anymore when processing the queries.

SCL-2770 Added new Repository Attribute to control the web designer for a container type

Description:

We've added the new Attribute WebDesignerComponent to the MetaForm, MetaViewer and MetaGrid repository types. This Attribute controls the designer component to use when editing a component to that type in the Angular based repository designer..

SCL-2776 ClassHelperBusinessEntity now provides option to retrieve classes without the use of the .NET Framework

Description:

We've added a new logical argument NoDotNet to the ClassNamesInClassPath named query of the ClassHelperBusinessEntity. This argument allows to controls that the business entity does not use the .NET framework to retrieve the list of matching classes from the backend. This allows to workaround issues with using the .NET framework on PASOE in certain situations.
A sample request payload when using the method from a REST client may look like this:

Code Block
languageabl

{ "NamedQuery": 
  { "name": "ClassNamesInClassPath", 
    "parameters": [
      { "name": "BaseClassName", 
        "type": "character", 
        "value": "Consultingwerk.SmartFramework.Authorization.ISecurityRealmService"}, 
      { "name": "IncludeAbstractClasses", 
        "type": "logical", 
        "value": false},
      { "name": "NoDotNet", 
        "type": "logical", 
        "value": true}]
    }
 }

...

SCL-2777 UserBusinessEntity now populates ManagerUserName and ManagerUserFullName for new records

Description:

We've enhanced the UserBusinessEntity of the SmartFramework so that it populates the ManagerUserName and ManagerUserFullName for new user records.

SCL-2778 MetaViewer rendering (GUI and Web) now supports VIEW-AS COMBO-BOX with list-items or list-item-pairs

Description:

When rendering DataField instances in a MetaViewer the ValueListItems and ValueListItemPairs properties are now fully supported for fields using VIEW-AS COMBO-BOX.

SCL-2779 Updated JSON Rendering for MetaBusinessEntityLookup components

Description:

We have updated and completed the JSON rendering of the MetaBusinessEntityLookup to support the latest changes and enhancement of the Angular lookup component.

New Feature

SCL-2713 Added Support for Dataset Input for RESTful method invokation

Description:

Formerly the implementation of RESTful method invokation (Business Entity or Task) did only support providing an input object, not input datasets. The dataset-parameters are only used as output.
This feature has now been enhanced, so that we now also support multiple ProDatasets for input. Similar to the response we should be optionally supporting the specification of datasets used for input using the request argument of the RestMethod annotation, e.g.:

Code Block
languageabl
     @RestMethod (address="/GetCustomerAndInvoices", requestMethod="post",
                 parameterClassName="Consultingwerk.IntegerHolder",
                 request="dsCustomer,parameter")
                 response="dsCustomer,dsInvoice").


In this sample, the JSON request body of a POST, PUT, PATCH, ... request is expected to be structured like this

Code Block
languageabl

{
  "dsCustomer": {"eCustomer": [ .... ] }
  "parameter": .... 
} 


The dsCustomer will be deserialized into the appropriate dataset. The "parameter" will be deserialized into the parameter object of the method.
If the "request" is not defined as part of the annotation, the request is processed like before, interpreting the whole request payload as the parameter object.

SCL-2749 Implemented REST endpoint to store Object Master Attributes

Description:

We have implemented a REST endpoint to store object master attributes in the SmartFramework repository.
This has been implemented as a PUT request to this endpoint with the ObjectMasterGuid value in the URL http://localhost:8820/web/Entities/SmartFramework/Repository/StoreObjectMasterDesignAttributes/857872d2-4eb4-b38f-3614-2191e8c7bf07
All properties that are modified from the Object Type defaults are expected to have the IsInherited property set to FALSE.

SCL-2765 Implemented REST endpoints to fetch and update attributes of SmartObjectInstances

Description:

We have implemented the following endpoints to retrieve and store instance attribute values based on the ObjectInstanceGuid value:
GET: http://localhost:8820/web/Entities/SmartFramework/Repository/GetObjectInstanceDesignAttributes/ad238208-b49f-68b9-1c14-1fb28817ba8b
PUT: http://localhost:8820/web/Entities/SmartFramework/Repository/StoreObjectInstanceDesignAttributes/ad238208-b49f-68b9-1c14-1fb28817ba8b

Task

SCL-2751 scl-pasoe-... scripts now support retrieving DLC for OpenEdge 12.1

Description:

We've updated the scl-pasoe-... scripts to be able to determine the DLC value for OpenEdge 12.1 from the Windows registry.

SCL-2775 New API in DatasetHelper to detach the DATA-SOURCE's from all ProDataset buffers

Description:

We've implemented the new API DatasetHelper:DetachDataSources (phDataset). This API detaches all DATA-SOURCE's from the Buffers of the given ProDataset.