QAFE

Tag Archives: qafe

FAQ’s about design choices for output generation

By: Raviksishnan Nair

This article is intended to provide an explanation regarding some of the design choices that were made as part of the conversion of Oracle Forms to an ADF application, using QAFE. Some of the FAQ’s related to the design choices that have been made for output generation have been listed. The information provided is of technical nature. 

There are other libray projects along with the output, why is this?
The output generated as a result of converting Oracle Forms to an ADF application contain other library projects. These advanced ADF libraries are there for the following reasons:

  • Implements reuse
    – Base classes for model
    – Taskflow templates / Page templates
    – Utility classes
    – Advanced declarative components
  • Implements best practises in a ‘forms friendly way’

Why does the output contain SQL for database view?
During the development of conversion code, scenarios were found, where data from different tables are being edited using a single UI. In terms of Oracle Forms, multiple block items were combined in a canvas and updating the data would have had effect on respective tables.

In order to maintain this behavior, database views were opted to support the operations being done on data from different tables. With this the generated ADF code stays less complex and clean. It also allows the database to manage the logic of updating the data to appropriate tables.

Another advantage is that the database views can be seen as API’s to the database itself and hence it will be easy for an application to work with a single source of data without bothering with the details of the exact source(s).

Why does the output contain SQL for instead of triggers?
The ‘instead of’ triggers are used to replace form specific triggers such as PRE and POST insert and update triggers simply because the PRE and POST triggers are forms specific and they don’t exist in an Oracle database.

What happens to the PRE and POST queries set up in forms associated with select statement?
The PRE and POST query set up in forms associated with a select statement are converted as comments and made available as part of the database view script. They are put as comments because the logic in such scenarios are found to be complex. Parsing the same can’t guarantee a solution which would be useful due to missing information at the point of conversion.

What do I have to do in order to make the application work completely?
The generated output provides hooks to couple the logic extracted from the converted form(s). The logic is provided as part of the call stack script available in the resource folder as part of the output.

The generated task flow bean classes are the ones which are referred to as hooks. In the generated output, the API’s in these classes are left empty. This is for the flexibility of the developer to choose what logic should go in there. It can be associating the trigger script or implementing the logic in the script in another efficient way.

The following example will give a clearer picture:

Figuur 1

Figure 1 shows that there is an action listener associated with a task flow bean API called: executeDetailsClick. This API is the place holder or the hook where the logic needs to be implemented by the developer to replicate the button click action in forms.

Figure 2 shows the API in a generated task flow bean class:

Figuur 2

From the forms application it would be known which trigger needs to be fired when a particular button is clicked. In this case: WHEN_BUTTON_PRESSED, SQL code is available as reference in the generated script output file as shown in Figure 3:

Figuur 3

In general, the generated output has the logic extracted and made available. It provides the flexibility, for the developer, to choose if the same needs to be applied or a more efficient way needs to be approached for achieving the result.

How do I know which form elements get converted to what?
This link provides the information about which form element gets converted to an ADF element as per the current generation process.

Please feel free to contact us at support@qafe.com for clarifications, further explanations or new queries.

Integrating QAFE with a JSP Frame using server-side processing

In previous blogs, we explained how to embed a Oracle Forms applet in a QAFE application and how to communicate between the applet and the QAFE application using Javascript. This uses the newly introduced call-script built-in and calling QAFE events from javascript. This only works using client-side processing. This blog will explain how to pass values from an embedded page back to the QAFE application using server-side processing.

Take for example this sample application including a refresh-button, a two textfields and a frame. The frame contains a textfield and a button. When the button within the frame is pressed, the value of the text field within the frame is passed to the QAFE application data store. By pressing the refresh button, the text fields will be filled in based on the value within the frame.

The image below describes the basic flow of the application. The QAFE application will embed a JSP page, which includes a text field and a button. When clicked on the button, a Javascript function is executed for storing the text field value. This function will send a request to a servlet to call the QAFE Engine storing the value into the application store.  When the value has been stored in the application store, the QAFE application can use that value for example to set that value to a text field as in the example.

Application store flow

As described above a Java servlet is used to pass information from the JSP page to the QAFE application. When opening up the QAFE application in the browser, a window session ID is generated to give the user a unique session. This window session ID should be used to store values in the application store. It is available in the HTML-code of the web page which includes the QAFE application as windowId. When passing the value through Javascript, the session ID should also be passed.

The code snippet below describes how to store the values into either the global store (application-wide) or the user store (only within a window). An ApplicationContext needs to be initiated to know which application store to use. Two dependencies (qafe-core and qafe-presentation) need to be imported. See Github for more information.

In this example, value “dummyValue” is stored in the global store with name “dummyValue”. The input variable is available in the user store with name “inputField”. These values can now be used in other events.

Thank you for reading this blog! More technical details and additional code snippets can be found on Github.

Blog by: Arvind Mohabir

Embedding Oracle Forms in your QAFE Application (Part 2)

In part 1 we discussed communication from QAFE to Oracle Forms. This blog will explain communication from Oracle Forms to QAFE. To allow for Oracle Forms integration in QAFE a few changes are needed in both the web-application and Oracle Form.

(Note: currently the following only works when client-side processing is enabled)

Prepare Web-Application & QAFE Application

Passing data from Oracle Forms to QAFE is, usually, a two step process. From Oracle Forms you will be calling a JavaScript method with the values you want to pass to QAFE. This JavaScript method in turn calls a QAFE event passing needed values.

Prepare QAFE Application

Add the event which will be invoked from the Oracle Form to the QAFE Application:

Listing 1: QAFE Application

Prepare Web-Application

Add a JavaScript function to the Web Application that contains the Oracle Forms applet. This function will call the QAFE provided JavaScript function invokeQafeEvent, which invokes a QAFE event. This newly added function can also be used to handle the embedded Oracle Forms applet e.g. hide it.

The invokeQafeEvent takes the following parameters:

Parameter    Type    Description
eventId         String   Id of the QAFE event. If null, nothing will happen.
windowId     String   Id of the QAFE window. If null, QAFE will try for a global event with the given id.
appId            String   Id of the QAFE application. If null, nothing will happen.
data              Map      Data needed in the QAFE event. If null, the data in the QAFE event will be null.

Listing 2: JavaScript function to invoke a QAFE event.

Prepare Oracle Forms Application

In the Oracle Form make use of one of the two procedures available within the web Built-in package provided by Oracle to call the previously defined JavaScript function:

  • web.javascript_eval_expr is a procedure which takes two arguments: an expression and a target, both of datatype VARCHAR2. If the target argument is null, then it is executed in the page or frame in which the Forms applet is embedded.
  • web.javascript_eval_function is a function, which takes the same arguments as above, and returns a VARCHAR2 value.

Both web.javascript_eval_expr and web.javascript_eval_function have the same functionality except that web.javascript_eval_expr does not send any return value from the client to the Oracle Form. If your application does not expect a return value, use web.javascript_eval_expr. Then the additional network trip that is required to carry the return value from the client to the Oracle Form is eliminated (see figure 1 below).

Since the return value of the web.javascript_eval_function is a VARCHAR2 some syntax might need to be devised when multiple return values or return values of a different datatype are desired. For example, concatenating multiple values separated by a semicolon.

PL/SQL editor

Figure 1: Oracle Forms statement to execute JavaScript.

Conclusion

A minor disadvantages is that, due to a limitation of Oracle Forms, the return value of web.javascript_eval_function is a VARCHAR2 and some additional parsing is required when passing more complex data back to Oracle Forms.

Being able to integrate Oracle Forms and QAFE provides the option to move gradually from Oracle Forms to QAFE. This has several advantages: start using the resulting web-application as soon as the first Oracle Forms are converted; opt to only convert the most prominent Oracle Forms in your application and remove the bottlenecks in your workflow; convert Oracle Forms to the extend of your budget, with the option to convert the rest later.

References

[1] http://docs.oracle.com/cd/E23943_01/web.1111/e10240/javascript.htm

Embedding Oracle Forms in your QAFE Application (Part 1)

Source: http://docs.oracle.com/cd/E23943_01/web.1111/e10240/javascript.htm

Using our Oracle Forms Conversion tool, it is possible to convert your forms application to a QAFE web application. In some cases you might want to consider integrating your existing Oracle Forms application with your QAFE web application for a more gradual conversion process.

I assume your Oracle Forms application has been configured so it can be exposed through a Java applet. Documentation on deploying your Oracle Forms application as a Java applet is supplied by Oracle[1] and is only available to applications using Oracle Forms 11g or higher.

Communication between Oracle Forms and the QAFE application is done through JavaScript. In order to establish JavaScript communications between both applications, some additional configuration of your Oracle Forms and QAFE application is required.

This blog explains how to accomplish one-way communication, from your QAFE application to your Oracle Forms.

In a following blog, we will elaborate on two-way communication between your applications.

Setting up your Oracle Forms Application
Before your Oracle Forms application allows JavaScript calls, a new Oracle Form level trigger has to be made available, namely the WHEN-CUSTOM-JAVASCRIPT-EVENT trigger. Note that only one is allowed to be defined per Oracle Form.

The trigger PL/SQL logic, which handles incoming JavaScript calls can look similar to this:

In this case we define an event with the name “my-application-event” which, when raised, will set the value of BLOCK1.ITEM1 to the passed eventValue.

Observe the :system.javascript_event_name and :system.javascript_event_value system variables. The :system.javascript_event_name system variable can be used to differentiate between incoming events raised from JavaScript. Event related data is passed from JavaScript via the :system.javascript_event_value system variable. Data passed from JavaScript to Oracle Forms is passed as a single String, if multiple values need to be passed you could consider separating them using a semicolon or using JSON, then parsing this in your PL/SQL logic.

Modify your Oracle Forms application’s formsweb.cfg configuration file to include the following properties:

The applet_name property will decide the applet’s HTML id attribute of the embedded applet in the HTML output.

The enableJavascriptEvent property configures the Oracle Forms Service for JavaScript binding, allowing JavaScript events to be called to and from the Form.

Setting up your QAFE Application
After configuring your Oracle Forms application, you still have to configure your QAFE application in order to embed the Oracle Forms application, and then call the now exposed JavaScript functions.

To embed the Oracle Forms application, use the frame component in your QAFE application’s panel definition:

The source oracle-forms-applet.html contains your embedded Oracle Forms applet (note: this is an example, your HTML code might vary depending on your application setup. Specific Oracle Form related arguments and path variables have been masked):

Calling Oracle Forms events using JavaScript
Now that we have an Oracle Forms application embedded in QAFE, we want to be able to raise events within the Oracle Form. This can be done through the now exposed raiseEvent JavaScript method:

The raiseEvent JavaScript function is made available by the embedded Oracle Form, if JavaScript handling is enabled as explained earlier.

The first argument of this function is the event name corresponding with the event name defined in the WHEN-CUSTOM-JAVASCRIPT-EVENT trigger code.

The second argument is the payload string containing the string formatted argument(s).

It is recommended to wrap the raiseEvent method in a custom defined method, defining that in a separate JavaScript file (e.g. oracleforms.js) and including it in the head section of <qafe-application-root>/webapp/QAFEGWTWeb.jsp file:

Now, when defining your events in your QAFE application’s QAML code you can use the call-script built-in to call either the raiseEvent method directly, or your custom defined method:

If the steps above were succesfully executed, you should now be able to manipulate the embedded Oracle Forms application from your QAFE web application.

[1]http://docs.oracle.com/cd/E23943_01/web.1111/e10240/javascript.htm

Client-side handling

Traditionally, the QAFE Engine has been processing all logic on the server-side because the browsers weren’t powerful enough at the time of development. With the latest 3.3.0 version of QAFE, the logic can be processed on the client-side. What does this mean for the developer and the user?

Move towards client-side handling
In the last couple of years, there has been a tendency to move certain parts of the logic to the client-side. One of the main reasons for this is that computers and browsers have become increasingly faster and having the client’s browser do some of the calculations relieves stress from the server. Javascript has become the de-facto language of the web since the decline of Flash and the continuing push of parties like Google, who have been optimizing the Javascript engine within their browsers. Presentation logic is moved to the client-side, while calls to the server are used for purely data fetching and manipulation. Resulting in a better performing application.

Client-side event handling in QAFE
Before the introduction of client-side handling, all code was processed server-side. This included simple operations like the storing of data or setting data to an object within a QAFE application. These operations are now fully done on the client-side by the browser. The application only calls the server, when business actions are invoked on the server. The example used in the screenshots below is storing a value in the data store and setting that value from the store to a text field. Server-side handling needs a RPC call to the server, while client-side handling can handle the scenario without a call.

Figure 1: Server-side handling

 

Figure 2: Client-side handling

Figure 2: Client-side handling

Another advantage is, data being available instantly after modifying a value in a field. The modified value can be fetched directly within the same event. There is no need to fire another event afterwards or to write additional code for retrieving the value. Having said that, code written using server-side handling should still work the same way as before with the benefit of increased performance.

Enabling client-side handling
Client-side handling is available from version 3.3.0 on. It’s disabled by default. It can be enabled in the engine by adding the following line to external.properties, located in the folder {project}/src/main/webapp/WEB-INF:

Please note that client-side handling is still experimental. It will be promoted as the default option in the near future. If you encounter any bugs, do not hesitate to contact us at support@qafe.com. If you like to contribute, feel free to do so at https://github.com/qafedev/qafe-platform!

QAFE 3.3.0 & Forms Conversion 1.12.0 Released

QAFE 3.3

We’ve just released version 3.3 of the QAFE Engine.

One of the most important features in this release is the introduction of Client Side Events. Without changing any QAML code, you can make sure that the body of an event gets executed on the client-side, as in the browser (change the external.properties file and add the value “clientside.event.enabled=true”). The biggest benefit is increased performance because a server round-trip is not needed, resulting in a more responsive application. For example, Chrome Developer Tools shows that it’s far more efficient.

network-panel

Because the execution happens client-side, you can see that QAFE doesn’t use any network resources anymore.

Note: by default the value for clientside.event.enabled is false.

Another big feature is the usage of REST interface to invoke business-actions. The benefit is that other front-end technologies (such as AngularJS, Web Components, any AJAX supported UI library)  can use the same logic through REST-JSON.

  • The QAFE Engine is now less dependent on third-party software
  • We’ve done cleanup of dependencies, e.g. XML libraries
  • New and improved Forms Conversion wizards for the QAML Builder
  • Updated documentation on GitHub
  • Several bugfixes

 

Forms Conversion 1.12.0

QAFE Oracle Forms Conversion to HTML5 and QAFE Oracle Forms Conversion to ADF are also updated and now available for anyone who wants to modernize the Oracle Forms stack to JEE standard applications.

Highlights of this release:

  • Major improvements on script generation, where all the logic is collected from the Oracle Form
  • In ADF conversion, the summary page in the wizard also shows the explicit TODOs for ADF developers
  • Specific combinations of items are rendered correctly
  • Layout improvements by improving the algorithm
  • Several bugfixes

To get started with our latest release, download the software here.

QAFE Testimonial – MENTIS

MENTIS – a leading player in data masking software – received customer feedback about how their applications’ look and feel was outdated. Because the applications were based on old technology, MENTIS couldn’t update their interfaces to current standards. This was the primary reason to auto-convert their applications to HTML5 with QAFE.

Download the client case to learn how QAFE Forms conversion saved MENTIS a lot of time and money while at the same time giving the opportunity to move to a contemporary look and feel.

download_testimonial_2

Download (PDF)

Post Conversion Steps ADF – Dynamic dropdown using Record Group View Objects

In this post, I’ll explain how dynamic dropdowns using record groups are converted and how to get a dynamic dropdown working in ADF after conversion. The focus of this blog will be to fill a dropdown dynamically using a record group, which contains a query without any input variables.

Prerequisites

This post requires basic knowledge of record groups and dropdowns within Oracle Forms, and a basic knowledge of ADF including UI objects, binding and view objects.

Situation in Oracle Forms

The Oracle Form used in this example consists of a record group and a list item as a dropdown element. The dropdown is filled by a Form trigger “WHEN-NEW-FORM-INSTANCE” at startup. To populate the dropdown, the code below is used. “DROPDOWN” is the name of the dropdown, while “TESTRG” is the name of the record group.

The record group uses a simple query without input variables to find a list of countries with corresponding IDs in the database.

 

PRO-60-0

Artifacts Generated

Record groups are converted by the Oracle Forms to ADF converter to View Objects (VO), while retaining the query with minimal changes. The converter manages input parameters, if available. In the example, the query does not contain any input variables. The query is converted to a SQLQuery-attribute and the output columns are converted to viewAttributes. The record group can be found as an XML formatted file “{RecordGroupName}VO.xml”. In this case the file is called “TestrgVO.xml”, see also the code example below.

 

Post Generation Steps to use a Record Group VO in a dropdown

Make sure that the dropdown component is visible within a JSF Fragment in JDeveloper’s designer mode. Open the Data control in the Data control menu and select a View Object. Drag and drop the object itself onto the dropdown component.

PRO-60-1Dragging a View Object to a dropdown element

PRO-60-2

Assign the list binding and the display attribute of the dropdown

In the Edit List Binding pop-up, the display attribute has to be set. When clicking on OK, the binding will be added or updated. Press OK to confirm all new bindings. All underlying code including the binding, VO iterator and control elements are automatically generated. The final step is to start the application. The dropdown is now filled automatically, based on the data in the VO.

PRO-60-3Rebinding of the components

PRO-60-4

Dropdown has a successful binding to the view object.

See the result below for a dynamically populated dropdown! An example using a record group with input parameters will be the subject of a future blog.

PRO-60-5

 

Running application with a filled dropdown.

Forms Conversion Server Release 1.11.0

A brief overview of the features that are part of Forms Conversion Server release 1.11.0.

Changelog

  • PLL processing
  • Support for the Oracle Forms SYSTEM variables
  • Support for the Oracle Forms SET_WINDOW_PROPERTY, GO_BLOCK, and GO_ITEM built-in
  • Additional OLB support regarding WIDTH, HEIGHT, VISIBLE, X_POSITION, Y_POSITION, and
  • INITIALIZE_VALUE
  • The Oracle Forms FORM_TRIGGER_FAILURE built-in converts to the Oracle RETURN keyword
  • The Oracle Forms MESSAGE built-in its value is available during execution
  • Added a README to the conversion output root, to get started quickly after conversion
  • Many minor improvements
  • A few bug fixes

PLL Processing

One of the most interesting new features of this release is the improved processing of your uploaded PLLs. The improvements we’ve made allow us to convert Oracle Forms more completely, i.e. the functionalities that depend on the functionality the PLL offers.

We kept the process as simple as possible. The only thing a user of the Forms Conversion Server has to do is upload its PLLs along with the FMB’s, see figure 1. After uploading, on the next wizard page, the PLLs will be included under the Statistics tab, see figure 2.

pll_upload (1)

pll_analysis_censored (1)

Finally, after having stored the converted files, the PLLs functionality will be available under the src/main/scripts/FORM_NAME/ directory as PL/SQL code.

Note: When uploading PLLs make sure all its the dependencies are also uploaded! If this is not the case, they will not be processed during the conversion.

Declaratively set Custom Properties on View Objects

Casus: A Forms to ADF conversion with post query triggers enabled.

The QAFE Oracle Forms ADF Exporter tool implements custom properties using the declarative XML language. A declarative language, generally, describes what the program should do as opposed to how the program should do it. This property has several advantages like maintainability, reusability, smaller programs and it’s easy to use.

In ADF, you want to have as much code as possible defined in a declarative way. This way, upgrading JDeveloper and ADF happens seamlessly. This would be less straightforward if using native Java. Additionally, when using Oracle JDeveloper Studio (12.1.3), its possible to manipulate the custom properties using its graphical user interface.

For example, if you would like post query triggers from their Oracle Form, see Figure 1 and 3, to be available after conversion, you could check “Enable Post query” at the configuration page when executing the conversion wizard, see Figure 3.

figure1
Figure 1: A Forms Builder Object Navigator showing post query triggers.
figure2
Figure 2: A Forms Builder PL/SQL Editor showing the post query implementation.
figure3
Figure 3: Forms to ADF conversion configuration with post query triggers enabled.

When the conversion is finished, the PL/SQL code pertaining to the post query triggers is available as part of a PL/SQL package that should be made available in the database, i.e., the script must be run on the database, see Figure 4.

Subsequently, when the newly converted ADF project is opened in Oracle JDeveloper Studio you could open a View Object and find their post query triggers under the “Custom Properties” section, see Figure 5.

figure4
Figure 4: Generated PL/SQL after conversion, pertaining to the post query trigger.
figure5
Figure 5: A JDeveloper Studio view showing custom properties.

This approach makes it easy for developers to use the logic in ADF and start planning how to possibly rewrite this logic in native ADF (like a Groovy mechanism).