Wednesday, 16 November 2016

parameterized bind iterator name as a mean to achieve reusable UI part in ADF12c

    This is a real-life use case that I'm usually hitting at the customers. There is a table which appears in the data model more than once. The business rules are the same, reusable, because they're implemented on the entity level. But to make it much more reusable, I want also to have the same front-end for them. In other words, I don't want to drag and drop each iterator from the data control and adjust the same visual rules to them each time (and change them in several places). Is there a way to do it just once per project? Well, there is.

    Lets start with preparation of the environment. I will base on REGIONS and COUNTRIES tables from HR scheme. My reusable part of the UI will be a region. There will be just one input parameter - iterator name. In the taskflow, I don't need nothing more than the view page. Just to create all needed files, structures and bindings, I'm drag and dropping one of the CountriesView iterator on it.

    And now the most important step of all. The taskflow parameter must be set in the page definition. When you select iterator binding, in the Property Inspector you get Binds attribute. It can accept EL expressions, but as I can see, in 12c you must type it manually. Another important note here, it must be evaluated with $ sign instead of #. Put ${pageFlowScope.iterName} there.

    To finish this proof of concept, create a test page, drag Regions iterator as a table. Drag and drop countriesBTF as a region and put CountriesView iterator names for both of them. After that you can run the test.

    One of the region is filtered with the view link, second is not filtered by default. First is refreshed after you'll change the current row of the Regions (master) iterator. Such behavior is an implication of shared data control scope.

    Hope you'll find it useful :)

Monday, 17 October 2016

af:form default command use-case

   Recently I've done some simple application. As usually, there was a logging page, which I have developed following rules from the documentation. The mechanisms were working fine, but there was one user who has pointed a change request - he wanted to facilitate the logging in process. Now he need to use a mouse to click the button, instead he wants the form to be submitted with Enter key. Useful change, to improve user experience with the app I should start with the login page. 

   I've been checking for <af:commandButton> properties in order to find an attribute that would solve it. Unfortunately there was nothing suitable, and, it is not a place for specifying default action. In many cases developers may set such property to more than one components. During short and temporary insanity I've thought about JavaScript function to do the work :)

   Fortunately there is a solution. Simple and quick. Similar to rendered attribute, it is not the component that should be triggered in order to present (or hide) itself. It is the container. There is an attribute, defaultCommand, which must be set in <af:form> tag. And that's it :)

   And short quick note at the end - it supports EL expressions, so the action may be parameterized.

Tuesday, 2 August 2016

how to implement tokenized messages in ADF-Faces

    Some time ago I've posted an article about customizing error messages in BC4J. Now's the time to think more about the UI. From time to time there is a requirement to write a sentence or a string concatenation on the screen which won't be static. As an example: There are XYZ rows from which ABC are shown on the screen. Of course my application must be internationalized, I'm using the bundle file. I can split my sentence into three different entries in the bundle file but I must be sure that the syntax in each language is the same. And it mustn't be like this.

    The solution is simple and, as usually, no extra Java code. ADF-Faces allows to tokenize text message. My simple use case is to display two fields and write "a+b is aANDbSUM" at the bottom of the page. For that purpose I'll use af:format3 function. It is a part of EL expression and it can be mixed with other valid EL invocations inside.

    The code snippet (it is using static text and viewScope implicit variables just to simplify the example):
<af:outputText value="#{af:format3('the sum of {0} and {1} is {2}.', viewScope.v1, viewScope.v2, viewScope.v1+viewScope.v2)}" id="ot1" partialTriggers="it2 it1"/>

    And the screenshots of the code and of the running page:

Thursday, 21 July 2016

quick way how to implement parameterized popups in ADF

    The business case is very common - there must be a popup which should be parametrized. As usually, I don't want to code it and I want to get it fast. I've done it for several times earlier, and even during this demo I've forgotten about one of the attributes.

    My popup will show a region, in my demo I've created a simple task flow with one input parameter and one view activity.

    After that I've started to work on the test page. There I've created two buttons with <af:setPropertyListener> tags to assign parameter. You can use managed beans or other ways, in my case I'm creating implicit parameters in one of ADF memory scopes. I'm using request scope or view scope because they're living for the shortest amount of the application life time. 

    I'm creating a popup with a dialog and region inside. The popup itself must have contentDelivery attribute set to lazyUncached. The tricky part is with setPropertyListener and showPopupBehavior tags under the buttons. First one must have type attribute set to action, second the triggerType attribute to click.

    It's almost everything, the final last thing that needs to be changed is in the page definition file. Because the region relies on the input parameter, to ensure that it'll refresh itself, please change refresh parameter to ifNeeded. And that's it, you can run it and check the results :)

Tuesday, 19 July 2016

transaction level validations

    Business Components for Java introduces three levels of validation:
  • attribute level
  • entity level
  • transaction level 
It is important to understand when they should be used and how to implement them.

    The attribute level should be used if some business rule applies just to it, for instance last name can't contain numbers or the phone number is mandatory. It is run for the attribute that is marked dirty in each of the entities, with an assumption that there is no other condition in the Groove implemented.

    On the entity level usually you should check for entity cross-attributes rules. For example is a person is foreigner, the passport number is required. It is run for each entity marked as dirty in the transaction, you can exclude some entities by setting a condition in Groove or by setting attributes that should be changed in order to fire validation. Because it is not needed to check for passport number if the foreigner flag attribute hasn't changed its value.

    Transaction level is on the top of the list. It is run once for all of the entities in the collection, that are marked as dirty.

    The wizard to create one is not so straight forward. First you need to start entity level validator, change it to Method like it's usually done for entity validators. But after that you need to go to the second tab and change validation level radio button. If you check previous tab then, the signature of the validation method has been changed. 
    For the test purposes I'm not putting the error message, there is no such need. Please ignore the warning popup after clicking OK. The EntityImpl class is created. I've put few lines of logging there and I've run the application module tester.
    It is not a good practice, but if you want to run the validation on whole collection, you can of course do it. By calling ((JboValidationContext)ctxList.get(0)).getSource()) you'll get EntityImpl class. On it you can call getDBTransaction().getRootApplicationModule() to find the application module instance (the root one, as the method name suggests), and then findViewObject() there.

Monday, 4 July 2016

How to access POJO data control current row's properties (using getDataProvider() method)

    I have created a POJO based data control which is returning a List<String> iterator. Because of some reasons I need to work not only with the direct binds in the page definition but also I want to access current row's properties. To give a picture of the problem, I've prepared an example:

    And now I want to put on the same page af:selectOneChoice component with all of the Strings from the list in my POJO DC. The most important thing is that the current row is not an instance of java.lang.String. It is an instance of oracle.adf.model.bean.DCDataRow class. Quick look into the JavaDoc, but no direct hint there. It is a wrapper that extends ViewRowImpl class (you may recognize it from BC4J stack). There is one method that, unfortunately, is not described in the documentation. It is called getDataProvider(), in EL it should be reffered as any other getter method. So, my choice component should look like this:

    And, to prove a point, it works also for more complex types of the data. Another example is for some artificial POJO class with two properties. After calling getDataProvider() on the current row you can call another getter method from the POJO class. In my EL for example it is #{row.dataProvider.label} to get label property. Please follow next few screens to check the solution.

Wednesday, 8 June 2016

List of Values switcher example in ADF 12c

I would like to start with a little bit of history. A long time ago, while people were still modelling ERD diagrams, there was an interesting relation, that I'm used to call an "exclusive or" but in the various sources it can be called also "exclusive arc" or "exclusive bar". I'll use an image found using Google to picture the situation:    

Such notation implies that in the logical model, the MEMBERSHIP table contains one foreign key column that can point to CUSTOMERS table or (exclusively) to COMPANY table.

In the BC4J model layer there exist an ability to define list of values. Maybe you haven't noticed that one column can have assigned more than one list of values. Moreover, such an LOV model can be switched in the runtime.

In this post I'll focus on the middleware implementation, the database is just to provide background for the demo. To complicate more, the TYPE column won't be threated directly as switching attribute. It'll be used by a Groove expression on the VO level.

Definition for the database:    

-- schema creation

-- test structure and data

I'll create an ADF Fusion Middleware application with Model created with "ADF Business Components from Tables" wizard. There is one updateable view object based on MAIN_TABLE and two dictionaries will be just for read only purposes.

In the MainTableView view object please add read only DetailTable view accessors as following. After that please go to the Attributes tab and select OneKeyColumn. There, on the List of Values tab please assign two list of values using green plus icon.

At the moment please notice few things. First of all there, one of the wizards is disabled. That's why please ensure in the view object source that the label is selected as a display attribute for the second one.

Each list of values has its own unique name. It is obvious that there must be just one default list of values.

This is the moment for add technical field to control which model of the list should be used. I'll use transient attribute based on a Groove expression. It'll be pointed as a List of Values Switcher. Key idea is that it must return the name of LOV, that's why it is String based. It is calculating return value using Type attribute (which is persisted in the database). And, because it is technical field, it won't be exposed in the DataControl (Display attribute set to Hide).

For the test page, please drag&drop MainTableView from the Data Control to the page. Please include navigation and commit buttons. The Type input field must submit its value after each change (autoSubmit set to true) and the OneKeyColumn must refresh itself after such change (partialTrigger on the Type input field). Because the SQL script doesn't contain test data, please also drag&drop CreateWithParams operation. Quick trick for setting the primary key with the row count value is used in this example.

And please take a look on the list of values model after setting Type attribute with abc and not-abc string value.