NF1.0 Web Services Improvements
Feature: Web Services Improvements
Goal: Technical improvement of Web services
Sponsor: Trek Global
Category of technology: Middle-ware Web-Services
Improvements in Brief:
- High level document process
- Run-time Validation
- Process fine-tuning
- iDempiere plug-in ready
Development in Brief:
- Converted ADempiere Web-services as iDempiere plugin
- Compatible to version iDempiere 1.0
- Migrated from XFire to CXF framework.
- Added Composite methods for singular client calls, reducing overhead of redundant calls
- Web-Service plugin for generic access to any model, process or action in iDempiere.
- Documentation content and tutorial provided by Deepak Pansheriya
- Wiki editing assistance from Red1 (talk)
- Initial prototype by 3E of Poland in 2007
- The New Web Services Window (Ruiz)
- Search Key (Ruiz)
- Web Service (Ruiz)
- Web Service Method (Ruiz)
- Table (Ruiz)
- Web Service Parameters (Ruiz)
- Web Service Field Input (Ruiz)
- DB Column Name (Pansheriya)
- Reference (Pansheriya)
- Identifier (Pansheriya)
- Allow Null Value (Pansheriya)
- Identifier logic (Pansheriya)
- Web Service Field Output (Ruiz)
- Web Service Access (Ruiz)
- Code review (HengSin)
- Web resource
The New Web Services Window
- Due to the many contributions stated above, our Web-Services has progressed much more in iDempiere master-detail layout with high-powered operational management.
- We shall go through the new feature request from the top. Below is its main window and tabs.
- The above is launched from the main menu by clicking on Web Services Security.
- The first tab is Web Service Type to define the web-services allowed on iDempiere.
- The Web Services plugin has generic implementation for users to make calls to the ERP server on any table, process or workflow actions.
- iDempiere has both Input and Output templates for external users to map the elements of their XSD (XML Schema Definitions).
- The new Composite services further reduce overhead of tasks the clients need to do as simple actions such as Create a Business Partner is now a single call instead of numerous cumbersome calls, thus reducing the work of the developer and ensure lower maintenance in future.
- The search key value maps to the serviceType tag in the web service request. This is demonstrated in the following snippet:
<web:ModelCRUD> <adin:serviceType>CreateBPartner</adin:serviceType> <adin:TableName>C_BPartner</adin:TableName> <adin:RecordID>0</adin:RecordID> <adin:Action>CreateUpdate</adin:Action> : : <web:ModelCRUD>
- This field denotes the type of web service. We now have both Model-Oriented and Composite Interfaces. The ModelADService is also improved to cover createUpdateData service.
Web Service Method
- This is for selecting an operational task during web-service implementation.
- Each web-service type has option of different tasks.
- This field is used when the web-service method needs to work with a Table.
- For example Create new record, Read existing records or Update existing records.
Web Service Parameters
- This tab used to define parameters for web service.
- Parameter can be a Constant or Free.
- If it is Constant then the value from Constant Value field is used, any value passed in from request is ignored.
- In case of Free, value from Request is used.
- Note that for _ID parameter, it will accept both Record ID and UUID value.
Web Service Field Input
- This tab is used to define the list of fields ( columns ) for web-service that creates new record or updates existing record.
- This tab controls the exposing of columns from the web-service request.
- Note the new Reference field that allows overriding of look-up type needed.
DB Column Name
- Above shows how this can be used to configure the variable name for Request Ctx.
- This field contains the string pattern used for table name.
- More on Request Ctx later.
- The idea is to allow the use of another key during look-up from another table.
- For example, to create OrderLine, we can use SKU instead of Product_ID.
- This field can thus override reference type in case of Table column and providing reference type for Ctx Variable.
- Web service uses this field to determine Data-type of variable.
- Reference key is used to override List or look-up value.
- If this flag is checked then current column is considered as part of record key.
- Multiple columns can be configured as identifier and they are combined for use as a composite key.
- Screen below shows how C_BPartner_ID is used as identifier to find existing record.
Allow Null Value
- When this field is checked then null value is considered in retrieving an existing record.
- This field add support for identifying record through the use of an SQL statement.
- Above screen shows how a C_BPartner record can be identified through AD_User.email .
Web Service Field Output
- This tab is used to configure the list of values that will be returned in response.
- Here you can choose columns from the Created/Updated record.
Web Service Access
- This tab configures the Roles that can access the defined web service.
- It gives additional layer of security as the Web-service is accessed via the open Web.
- Composite form of web-services is introduced in this iDempiere 1.0 version to support complex operations such as create BPartner, contact and location within a single request and within a single transaction.
- Another objective for this deisgn is to reduce the number of calls between client and server.
- Composite service is actually a wrapper on the model-oriented web-service.
- It allows to combine multiple atomic ModelADService operation like createData, UpdateData, createUpdateData, setDocAction etc in single request.
- Below is sample request syntax for a composite service.
<web:compositeOperation> <web:CompositeModelRequest> <web:ADLoginRequest> : : </web:ADLoginRequest> <web:serviceType>SyncOrder</web:serviceType> <web:operations> <web:operation preCommit="false" postCommit="false"> <web:TargetPort>createUpdateData</web:TargetPort> <web:ModelCRUD> : : </web:ModelCRUD> <web:TargetPort>createUpdateData</web:TargetPort> </web:operation preCommit="false" postCommit="false"> </web:operations> </web:compositeOperation>
- You can take a look at the highlighted tags.
- Operations allow to combine multiple CRUD operation or runProcess operation.
- TargetPort specify operation name of ModelADService* to be called.
- Possible value for TargetPort are createData, updateData, createUpdateData*, deleteData, readData, setDocAction and runProcess.
- All operation specified in this request share one login request and can share data with each other using requestCtx (@* variable).
*Note that createUpdateData is an improvement for the ModelADService included in this feature request.
- We can now fine-tune the management of data been replicated via iDempiere's Web-Service.
- When we synchronize data, we can use the concept of Safe-Point.
- We may not need to do re-sync if we reached or passed successfully a safe-point location.
- For example if we are synchronizing Order, creation of Sales Order Header and line atomically but once we have created all OrderLines we can save them even though we are not able to Complete or Prepare the Order.
- Composite service allow to control over transaction using preCommit and postCommit attributes on operation element.
- If preCommit is true, whatever done before current operation will be committed to the database.
- When postCommit is true, commit is performed after current operation is executed successfully.
- If any error occurs, then a transaction is rolled-back and its response indicates whether an operation is committed or rolled-back by referring to the attribute IsRolledBack on standard response element.
- isError attribute is set to true for failed operations.
Request Ctx Variable
- Request Ctx variable is available for reference during the entire request life-cycle.
- This Ctx Variable keeps track of all created records in current request by table name.
- Request can populate any custom variable name defined on Web Service Security -> Web Service Field Input tab too.
- These variables are accessible also by consecutive operations by script.
- For example if we have created a User and want to use the same on C_Order, our createOrder request can have input field parameter as below.
<adin:field column="AD_User_ID"> <adin:val>@AD_User. AD_User_ID</adin:val> </adin:field>
- Here whenever field has value starting with @, the web service will consider the consecutive string as a variable and try to resolve it from the request context.
- In above example, @AD_User. AD_User_ID will get AD_User_ID from previously created AD_User record.
- If request want to populate custom variable into Ctx, it can configure web service input field without selecting any column and use DB Column Name field to define the variable name.
- For example, below screen shows email variable set on CreateBPartner request.
- There is no column named email on C_BPartner but configuring this variable on Web Service Input tab will allow to populate the request context with email value on CreateBParner request.
- When you are configuring a DB Column, Column must be blank and reference must be selected.
- Ctx variable decides data-type for input based on Reference key.
Env Ctx Variable
- iDempiere's Env variable are accessible using script @#VariableName syntax.
- We can use this syntax in field and recordID elements to get dynamic value.
- This operation checks for existing record and perform either create or update record.
- This operation can be better than the createData or updateUpdate operation.
- createUpdateData uses record identifier(s) to check whether a record exists or not.
- Web Service Input Field has an identifier Flag which is used to decide whether an input field will be used to identify the record or not.
- More than one column can be used to identify any record.
- For example C_BPartner_ID and Email can be used to identify BPUser.
- Even custom SQL can be used in identifier logic to return its record ID.
- This operation allows explicit control creation or updating of record.
- Request can specify following value on Action.
- Create - Only create record. If record exists, return error
- Update - Only update record. If record do not exists, return error
- CreateUpdate - If record does not exists, create it otherwise update existing record
- Below is an sample request document for createUpdateData.
<_0:createUpdateData> <_0:ModelCRUDRequest> <_0:ModelCRUD> <_0:serviceType>CreateUpdateLocation</_0:serviceType> <_0:TableName>C_Location</_0:TableName> <_0:RecordID>0</_0:RecordID> <_0:Action>CreateUpdate</_0:Action> <_0:DataRow> <_0:field column="C_Country_ID" lval="United States"/> <_0:field column="Address1"> <_0:val>1625 Cowboy Chaps Place</_0:val> </_0:field> <_0:field column="C_Region_ID" lval="NV"/> <_0:field column="RegionName"> <_0:val>NV</_0:val> </_0:field> <_0:field column="Postal"> <_0:val>89002</_0:val> </_0:field> <_0:field column="City"> <_0:val>Henderson</_0:val> </_0:field> </_0:DataRow> </_0:ModelCRUD> <_0:ADLoginRequest> : : </_0:ADLoginRequest> </_0:ModelCRUDRequest> </_0:createUpdateData>
- Please take note of Action. It indicates CreateUpdate. This mean record is either created or updated based on existence.
- Newly added lVal parameter for Field will pass readable string and will be converted to ID using standard iDempiere lookup mechanism.
- For example to set Shipping Method on Order, we can retrieve M_Freight_ID through Shipping Method name.
- Below is example how we can find out Region using lookup instead of C_Region_ID. <_0:field column="C_Region_ID" lval="NV"/>
- Please note that we are using lval attribute instead of val element when we want to use lookup.
- Web-service Validator can be used to extend web-service functionality and appending additional business logic.
- Validator are added as osgi service and must implement the IWSValidator interface.
- Validator can be registered to listen to a type of web-service or all web-services.
- If Validator needs to listen to all web-service calls, then use the special value GLOBAL in WSType parameter.
- Validators are called at following timings:
- Before Parse
- After Parse
- Before Save
- After Save
- RecordIDVariable is added to override recordID field and allow support for scripting.
- Using this parameter into request, record ID can be set from variable in requestCtx.
- Usage of this is in composite service to perform setDocAction without adding any complexity to identify record.
- Below sample shows how it is used to complete a document created in previous operation inside a composite srequest.
<_0:compositeOperation> <_0:CompositeRequest> <_0:serviceType>SyncOrder</_0:serviceType> <_0:operations> <_0:operation preCommit="false" postCommit="false"> <_0:TargetPort>createUpdateData</_0:TargetPort> <_0:ModelCRUD> <_0:serviceType>createOrderRecord</_0:serviceType> <_0:TableName>C_Order</_0:TableName> : : </_0:ModelCRUD> </_0:operation> <_0:operation preCommit="true" postCommit="false"> <_0:TargetPort>createUpdateData</_0:TargetPort> <_0:ModelCRUD> <_0:serviceT ype>CreateOrderLine</_0:serviceT ype> <_0:TableName>C_OrderLine</_0:TableName> : : </_0:ModelCRUD> </_0:operation> <_0:operation preCommit="true" postCommit="true"> <_0:TargetPort>setDocAction</_0:TargetPort> <_0:ModelSetDocAction> <_0:serviceType>CompleteOrder</_0:serviceT ype> <_0:tableName>C_Order</_0:tableName> <_0:recordID>0</_0:recordID> <_0:recordIDVariable>@C_Order.C_Order_ID</_0:recordIDVariable> <_0:docAction>CO</_0:docAction> </_0:ModelSetDocAction> </_0:operation> </_0:operations> </_0:CompositeRequest> </_0:compositeOperation>
- In above request, we are creating order and then completing same using setDocAction operation.
- We use recordIDVariable to retrieve record ID for order created before this operation.
- Web-service uses Reference type from Table column as default but can also be overridden on Web Service Input field as shown below.
- We use this overriding mechanism to define custom look-up for column.
- For example, when we configure reference for M_Product table, we normally use Product Name.
- Now we can choose to use SKU to identify products in our web-service.
- In this case we can define new look-up which use display field as SKU for product.
- Below shows how we have configured M_Product_ID column on CreateUpdateOrderLine service.