X

Recent Posts

Faces

Building Tag Cloud Declarative ADF Component

When building a website, there could a requirement to add a tag cloud to let the users know the popular tags (or terms) used in the site. In this blog, we would build a simple declarative component to be used as tag cloud in the page. To start with, we would first create the declarative component, which could display the tag cloud. We will do that by creating a new custom application from the new gallery. Give a name for the app and the project and from the new gallery, let us create a new ADF Declarative Component We need to specify the name for the declarative component, attributes in it etc. as follows For displaying the tags as cloud, we need to pass the content to this component. So, we will create an attribute to hold the values for the tag. Let us name it as "value" and make it as java.lang.String  type. Once after this, to hold the component, we need to create a tag library. This can be done by clicking on the Add Tag Library button. Clicking on OK buttons in all the open dialogs would create a declarative component for us. Now, we need to display the tag cloud based on the value passed to the component. To do that, we assume that the value is a Tree Binding and has two attributes in it, say "Name" and "Weight". To make a tag cloud, we would put together the "Name" in a loop and set it's font size based on the "Weight". After putting our logic to work, here is how the source look Attributes added to the declarative components can be retrieved by using #{attrs.<attribute_name>}. Now, we need to deploy this project as ADF Library Jar file, so that this can be distributed to the consuming applications. We'll select ADF Library Jar as type and create the profile. We would be getting the jar file after deployment. To test the functionality, we could create a simple Fusion Web Application. To add our custom component to the consuming application, we can create a file system connection pointing to the location where the jar file is and add it or, add through the project properties of the ViewController project. Now, our custom component has been added to the consuming application. We could test that by creating a VO in the model project with a query like, select 'Faces' as Name,25 as Weight from dual union all select 'ADF', 15 from dual  union all select 'ADFdi', 30 from dual union all select 'BC4J', 20 from dual union all select 'EJB', 40 from dual union all select 'WS', 35 from dual Add this VO to the AppModule, so that it would be exposed to the data control. Then, we could create a jspx page, and add a tree binding to the VO created. We can now see our Tag Cloud declarative component is available in the component palette.  It can be inserted from the component palette to our page and set it's value property to CollectionModel of the tree binding created. Now that we've created the Declarative component and added that to our page successfully, we can run the page to see how it looks. As per the query, the Tags are displayed in different fonts, based on their weight.

When building a website, there could a requirement to add a tag cloud to let the users know the popular tags (or terms) used in the site. In this blog, we would build a simple declarative component to...

Faces

How to create cascading (depending) auto suggest behavior using BC4J

In continuation to my previous blog on "How to create multilevel cascading (dependent) list of values using BC4J", i am tryingto leverage a similar usecase using af:autoSuggestBehavior inthis article. Though the usecase looks same, the implementation isslightly different for this. Let us assume a usecase where we have some text fields with autosuggest feature enabled, and their suggested items could bedependent on one other. For ex : Country, State and City. This could be modeled by having an EO and VO created based onPerson table and read-only look-up VOs created based on Country,State and City tables. Implementing the dependency between LOVs is pretty straightforward. However, implementing the dependency between the autosuggest items is not. In order to achieve the dependency, first wewould need couple of methods returning current row's CountryId andStateId. We could add them up in the AMImpl class. public NumbergetCurrentCountryId(){ return (Number)this.getPersonView1().getCurrentRow().getAttribute("CountryId"); } public Number getCurrentStateId(){ return (Number)this.getPersonView1().getCurrentRow().getAttribute("StateId"); } As we need to filter out the States based on the Country and theCity based on the Country & State, we would need to modify thequery of these two VOs to include a bind variable in the whereclause. For having the auto suggest, we need to have a view criteriadefined for all the three look-up VOs (CountryView, StateView andCityView). Generate VOImpl classes for Country, State and City VOs (withInclude bind variable accessors option checked), and then exposesetBindCountryName (in Country VO), setBindStateName (in State VO)and setBindCityName (in City VO) methods as client interfaces. And the last part on the model is to pass the current row'sCountryId and StateId to the Bind Variables defined in the Stateand City VOs. Also, we need to get the VCs created above to beexecuted by default (By editing the VO instance in the AM's datamodel), so that the auto suggest list would be filtered as and whenthe users type. Here, we specify groovy expression for the CountryId and StateIdas adf.object.applicationModule.<methodName>. For moreinformation about using groovy expressions, check out this :http://www.oracle.com/technetwork/developer-tools/jdev/introduction-to-groovy-128837.pdf. With this, we are done with setting up the model layer for theauto suggest dependency. In the View layer, we would create an ADF Form based on thePerson VO, with all the navigation buttons. In order to construct the onSuggest items, we would create TreeBindings for Country VO, State VO and City VO, along with methodaction bindings for the setBindCountryName, setBindStateName andsetBindCityName methods. Now, we could add af:autoSuggestBehavior for CountryId, StateIdand CityId fields. Then, add onSuggest methods in backing bean forpopulating the on suggest items for each fields. onSuggest method for Country field : public List onCountrySuggest(StringsearchCountryName) {ArrayList<SelectItem> selectItems = newArrayList<SelectItem>(); System.out.println(searchCountryName); //get access to thebinding context and binding container at runtime BindingContext bctx =BindingContext.getCurrent(); BindingContainerbindings = bctx.getCurrentBindingsEntry(); //set the bind variablevalue that is used to filter the View Object //query of the suggestlist. The View Object instance has a View //Criteriaassigned OperationBindingsetVariable = (OperationBinding)bindings.get("setBind_CountryName");setVariable.getParamsMap().put("value", searchCountryName);setVariable.execute(); //the data in thesuggest list is queried by a tree binding. JUCtrlHierBindinghierBinding = (JUCtrlHierBinding)bindings.get("CountryView1"); //re-query the listbased on the new bind variable valueshierBinding.executeQuery(); //The rangeSet, thelist of queries entries, is of type//JUCtrlValueBndingRef.List<JUCtrlValueBindingRef> displayDataList =hierBinding.getRangeSet(); for(JUCtrlValueBindingRef displayData : displayDataList){Row rw = displayData.getRow();//populate the SelectItem listselectItems.add(new SelectItem((Integer)rw.getAttribute("Id"),(String)rw.getAttribute("Name")));} returnselectItems; } onSuggest method for State field : public List onStateSuggest(StringsearchStateName) {ArrayList<SelectItem> selectItems = newArrayList<SelectItem>(); System.out.println(searchStateName); //get access to thebinding context and binding container at runtime BindingContext bctx =BindingContext.getCurrent(); BindingContainerbindings = bctx.getCurrentBindingsEntry(); //set the bind variablevalue that is used to filter the View Object //query of the suggestlist. The View Object instance has a View //Criteriaassigned OperationBindingsetVariable = (OperationBinding)bindings.get("setBind_StateName");setVariable.getParamsMap().put("value", searchStateName);setVariable.execute(); //the data in thesuggest list is queried by a tree binding. JUCtrlHierBindinghierBinding = (JUCtrlHierBinding) bindings.get("StateView1"); //re-query the listbased on the new bind variable valueshierBinding.executeQuery(); //The rangeSet, thelist of queries entries, is of type//JUCtrlValueBndingRef.List<JUCtrlValueBindingRef> displayDataList =hierBinding.getRangeSet(); for(JUCtrlValueBindingRef displayData : displayDataList){Row rw = displayData.getRow();//populate the SelectItem listselectItems.add(new SelectItem((Integer)rw.getAttribute("Id"),(String)rw.getAttribute("Name")));} returnselectItems; } onSuggest method for City field : public List onCitySuggest(StringsearchCityName) {ArrayList<SelectItem> selectItems = newArrayList<SelectItem>(); System.out.println(searchCityName); //get access to thebinding context and binding container at runtime BindingContext bctx =BindingContext.getCurrent(); BindingContainerbindings = bctx.getCurrentBindingsEntry(); //set the bind variablevalue that is used to filter the View Object //query of the suggestlist. The View Object instance has a View //Criteriaassigned OperationBindingsetVariable = (OperationBinding)bindings.get("setBind_CityName");setVariable.getParamsMap().put("value", searchCityName);setVariable.execute(); //the data in thesuggest list is queried by a tree binding. JUCtrlHierBindinghierBinding = (JUCtrlHierBinding) bindings.get("CityView1"); //re-query the listbased on the new bind variable valueshierBinding.executeQuery(); //The rangeSet, thelist of queries entries, is of type//JUCtrlValueBndingRef.List<JUCtrlValueBindingRef> displayDataList =hierBinding.getRangeSet(); for(JUCtrlValueBindingRef displayData : displayDataList){Row rw = displayData.getRow();//populate the SelectItem listselectItems.add(new SelectItem((Integer)rw.getAttribute("Id"),(String)rw.getAttribute("Name")));} returnselectItems; } Once after this, we could bind this to theaf:autoSuggestBehavior's suggestedItems property <af:inputText value="#{bindings.CountryId.inputValue}"label="#{bindings.CountryId.hints.label}"columns="#{bindings.CountryId.hints.displayWidth}"autoSubmit="true" shortDesc="#{bindings.CountryId.hints.tooltip}" id="it3"><af:autoSuggestBehaviorsuggestedItems="#{viewScope.AutoSuggestBean.onCountrySuggest}"/></af:inputText><af:inputText value="#{bindings.StateId.inputValue}"label="#{bindings.StateId.hints.label}"columns="#{bindings.StateId.hints.displayWidth}"autoSubmit="true" partialTriggers="it3"shortDesc="#{bindings.StateId.hints.tooltip}" id="it4"><af:autoSuggestBehaviorsuggestedItems="#{viewScope.AutoSuggestBean.onStateSuggest}"/></af:inputText><af:inputText value="#{bindings.CityId.inputValue}"label="#{bindings.CityId.hints.label}"columns="#{bindings.CityId.hints.displayWidth}"autoSubmit="true" partialTriggers="it4"shortDesc="#{bindings.CityId.hints.tooltip}" id="it5"><af:autoSuggestBehaviorsuggestedItems="#{viewScope.AutoSuggestBean.onCitySuggest}"/></af:inputText> Finally, our output would be

In continuation to my previous blog on "How to create multi level cascading (dependent) list of values using BC4J", i am trying to leverage a similar usecase using af:autoSuggestBehavior inthis...

Faces

Display Holiday Name in af:calendar

When using af:calendarcomponent in the realtime applications, there is a frequentrequirement to display the holdays in it. In this article, we willsee how to achieve that. After setting the environment, we would be expecting the outputas shown in the below image. Assuming we already have a page with calendar, the individualdate level customizations can be done by using DateCustomizer. For this, we would create a custom class that extendsDateCustomizer class. public class MyDateCustomizer extends DateCustomizer{ public String format(Date date, String key, Locale locale,TimeZone tz) { // For illustrative purpose // Hashmap holding the holiday list HashMap holidays = new HashMap(); holidays.put(new Date("25-Dec-2012"),"Christmas"); holidays.put(new Date("01-Jan-2013"), "NewYear"); if("af|calendar::month-grid-cell-header-misc".equals(key)) { returnholidays.get(date)!=null?holidays.get(date).toString():null; } return null; } } As per the tag doc, following keys are passed to the formatmethod. "af|calendar::day-header-row" "af|calendar::list-day-of-month-link"Year's Day". "af|calendar::list-day-of-week-column" "af|calendar::month-grid-cell-header-day-link" "af|calendar::month-grid-cell-header-misc" "af|calendar::week-header-day-link" So, in the above code, we return the actual holiday name for the"af|calendar::month-grid-cell-header-misc" key. In order to use the new DateCustomizer in our calendar, wecreate an instance of it in the backing bean and bind it to thecalendar's dateCustomizer property. Bean Code : public class CalendarBean { private MyDateCustomizer holidays = newMyDateCustomizer(); ; public CalendarBean() { } public void setHolidays(MyDateCustomizerholidays) { this.holidays =holidays; } public MyDateCustomizer getHolidays() { return holidays; } } Page Source : <af:calendar id="c1"dateCustomizer="#{viewScope.CalendarBean.holidays}"/> If needed, the text can be styled to be displayed in differentcolor (as shown in the image at the top). For this, we can have astyleclass in the css af|calendar::month-grid-cell-header-misc { background-color: Yellow; }

When using af:calendar component in the realtime applications, there is a frequent requirement to display the holdays in it. In this article, we will see how to achieve that. After setting the...

ADF

Restrict number of characters to be typed for af:autoSuggestBehavior

When using AutoSuggestBehavior for a UI Component, the autosuggest list is displayed as soon as the user starts typing in thefield. In this article, we will find how to restrict theautosuggest list to be displayed till the user types in couple ofcharacters. This would be more useful in the low latency networks and alsothe autosuggest list is bigger. We could display a static messageto let the user know that they need to type in more characters toget a list for picking a value from. Final output we would expectis like the below image Lets see how we can implement this. Assuming we have an inputtext for the users to enter the country name and an autosuggestbehavior is added to it. <af:inputText label="Country" id="it1"> <af:autoSuggestBehavior /> </af:inputText>Also, assuming we have a VO (we'll name it as CountryView for thisexample), with a view criteria to filter out the VO based on thebind variable passed. Now, we would generate View Impl class from the java node(including bind variables) and then expose the setter method of thebind variable to client interface. In the View layer, we would create a tree binding for the VO andthe method binding for the setter method of the bind variableexposed above, in the pagedef file As we've already added an input text and an autosuggestbehaviorfor the test, we would not need to build the suggested items forthe autosuggest list.Let us add a method in the backing bean toreturn us List of select items to be bound to the autosuggestlist. padding: 5px; background-color: #fbfbfb; min-height: 40px; width: 544px; height: 168px; overflow: auto;"> public List onSuggest(String searchTerm) { ArrayList<SelectItem> selectItems = new ArrayList<SelectItem>(); if(searchTerm.length()>1) { //get access to the binding context and binding container at runtime BindingContext bctx = BindingContext.getCurrent(); BindingContainer bindings = bctx.getCurrentBindingsEntry(); //set the bind variable value that is used to filter the View Object //query of the suggest list. The View Object instance has a View //Criteria assigned OperationBinding setVariable = (OperationBinding) bindings.get("setBind_CountryName"); setVariable.getParamsMap().put("value", searchTerm); setVariable.execute(); //the data in the suggest list is queried by a tree binding. JUCtrlHierBinding hierBinding = (JUCtrlHierBinding) bindings.get("CountryView1"); //re-query the list based on the new bind variable values hierBinding.executeQuery(); //The rangeSet, the list of queries entries, is of type //JUCtrlValueBndingRef. List<JUCtrlValueBindingRef> displayDataList = hierBinding.getRangeSet(); for (JUCtrlValueBindingRef displayData : displayDataList){ Row rw = displayData.getRow(); //populate the SelectItem list selectItems.add(new SelectItem( (String)rw.getAttribute("Name"), (String)rw.getAttribute("Name"))); } } else{ SelectItem a = new SelectItem("","Type in two or more characters..","",true); selectItems.add(a); } return selectItems; } So, what we are doing in the above method is, to check thelength of the search term and if it is more than 1 (i.e 2 or morecharacters), the return the actual suggest list. Otherwise, createa read only select item new SelectItem("","Type in two or more characters..","",true); and add it to the list of suggested items to be displayed. Thelast parameter for the SelectItem (boolean) is to make it asreadOnly, so that users would not be able to select this staticmessage from the displayed list. Finally, bind this method to the input text'sautosuggestbehavior's suggestedItems property. <af:inputText label="Country" id="it1"> <af:autoSuggestBehavior suggestedItems="#{AutoSuggestBean.onSuggest}"/> </af:inputText>

When using AutoSuggestBehavior for a UI Component, the auto suggest list is displayed as soon as the user starts typing in the field. In this article, we will find how to restrict theautosuggest list...

ADF

How to create multi level cascading (dependent) list of values using BC4J

There are quite a number of documentations / blogs on creating cascading (dependent) list of values in ADF Application using BC4J as model. Some examples 1. https://blogs.oracle.com/shay/entry/got_to_love_cascading_lovs_in 2. http://mjabr.wordpress.com/2011/04/01/cascade-list-of-values/ However, these entries talk about creating list of values for master-detail attributes. In this article, I would be explaining about creating list of values which have master-detail-grand detail relationship (though the implementation is same, the use case is different). Assuming that we've our model ready, with an VO for Person (based on Person EO), Country, State and City (read-only VOs). Now, we'll modify the query of the dependent VOs to include a bind variable in their where clause. We could then create List of Values for the CountryId, StateId and CityId attributes in the Person VO. Above image shows an example for creating LOV for the CityId attribute. LOV is created for the CountryId and StateId attributes in the similar fashion. Now that we've created LOV for all the 3 attributes, we need to pass the required values for the bind variable we created previously (in State and City VOs). That is done from the View Accessors tab of Person VO. Now we are set to go with the dependent LOV. Before running the Tester, we need to make the CountryId and StateId attributes automatically submit their values upon change (by setting Auto Submit UI Hint to true)  (Above image shows setting Auto Submit UI Hint to true for CountryId attribute. In the same manner, set the Auto Submit UI Hint to true for the StateId attribute as well). and add make StateId dependent on CountryId, CityId to depend on CountryId and StateId. We are set to go now. Run the AppModule tester to verify the values. When using this in jspx page, set the AutoSubmit properties for the CountryId and StateId components, and add the partialTriggers for StateId and CityId components with the Id of CountryId component, as shown below. Hint: Right click on the images and select View Image to view it completely if it is cropped.

There are quite a number of documentations / blogs on creating cascading (dependent) list of values in ADF Application using BC4J as model. Some examples 1. https://blogs.oracle.com/shay/entry/got_to_lov...

Faces

Interpret af:query's queryEvent and display popup to end user using QueryListener

Found an interesting question on OTN. Based on the question, wired a usecase to try out.Usecase : Show a warning to user when they try to search the records (af:query component), without specifying a criteria / a wild card "%". I.e, when the user tries to query the entire table, show a warning that querying all the records would take some time. There are three phases in implementing this usecase.1. Interpret the query event and get the query criteria.2. Show the popup.3. Process the interpreted query based on the outcome of the popup.Before proceeding with the implementation, we'll create a page for assumption.a. Page contains a af:query component with a resultant table / read-only table.b. Has a popup to be shown to the end user.c. Bound to a bean.We'll now implement it phase by phase.First of all, we'll create couple of attributes in the bean and generate accessors to them.     private RichTable empTable;    private boolean warnUser=true;   // Set the default queryListener property value of the af:query component   // for mexpr.   private String mexpr = "#{bindings.ImplicitViewCriteriaQuery.processQuery}";     private QueryEvent qEvt;    public void setEmpTable(RichTable empTable) {        this.empTable = empTable;    }    public RichTable getEmpTable() {        return empTable;    } Now, we need to trap the query event of the af:query component to perform the desired task. We can add a queryListener and bind it to the af:query component   public void processQuery(QueryEvent queryEvent) {        // store the queryEvent in a bean attribute, to be used in another method.        qEvt = queryEvent;        // Reset the flag. This flag would be used to check if the system has to         //raise the popup or not        warnUser=false;        DCBindingContainer bc =           (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();            // Get the view criteria that would be applied.         // findExecutableBinding method takes two parameters.         // id of the searchRegion executable binding         // criteria for the searchRegion executable binding         // Ex : <searchRegion Criteria="__ImplicitViewCriteria__"               // Customizer="oracle.jbo.uicli.binding.JUSearchBindingCustomizer"         //         Binds="EmpView1Iterator" id="ImplicitViewCriteriaQuery"/>        ViewCriteria vc = JUSearchBindingCustomizer.getViewCriteria((DCBindingContainer)bc.findExecutableBinding("ImplicitViewCriteriaQuery"),"__ImplicitViewCriteria__");        ViewCriteriaRow vcr = (ViewCriteriaRow)vc.get(0);        // Some logic to set the flag. Here, checking if the Ename attribute has        // no value specified / used a wildcard expression ("%").        for(int i=0;i<vcr.getAttributeNames().length;i++) {            if(vcr.getAttributeNames()[i] == "Ename" &&  ("%".equals(vcr.getAttributeValues()[i]) || vcr.getAttributeValues()[i]==null))                 warnUser=true;        }        if(warnUser)             showPopup();        else             executeQuery();    } showPopup and executeQuery are custom methods to show the popup and to process the query respectively.     public void showPopup(){        UIViewRoot root = FacesContext.getCurrentInstance().getViewRoot();        RichPopup popup = (RichPopup) root.findComponent("p1");        RichPopup.PopupHints hints = new RichPopup.PopupHints();        popup.show(hints);    } // This method invokes the method expression used by af:query component programatically    public void executeQuery(){        processMethodExpression(mexpr, new Object[] {qEvt}, new Class[] {QueryEvent.class});         AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();         adfFacesContext.addPartialTarget(empTable);     }    private Object processMethodExpression(String methodExpression, Object[] parameters, Class[] expectedParamTypes) {         FacesContext fctx = FacesContext.getCurrentInstance();         ELContext elctx = fctx.getELContext();         Application app = fctx.getApplication();         ExpressionFactory exprFactory = app.getExpressionFactory();         MethodExpression methodExpr = exprFactory.createMethodExpression(elctx, methodExpression, Object.class, expectedParamTypes);         return methodExpr.invoke(elctx, parameters);         } Now, we need to bind the custom querListener created above to the af:query component <af:query id="qryId2" headerText="Search" disclosed="true"  value="#{bindings.ImplicitViewCriteriaQuery.queryDescriptor}"      model="#{bindings.ImplicitViewCriteriaQuery.queryModel}"      queryListener="#{viewScope.QueryBean.processQuery}"..... We are almost there. Now, when we run the page and query for the records by keeping Ename as null (in the query panel), we would get the popup. Final step is to handle the user action on the popup and then proceed executing the query / to stop it.For this, we'll create a dialog listener and bind it to popup. public void onDialog(DialogEvent dialogEvent) {        Outcome o = dialogEvent.getOutcome();        if(o == Outcome.yes)             executeQuery();    }                 <af:popup childCreation="deferred" autoCancel="disabled" id="p1">                    <af:dialog id="d2" type="yesNo" title="Are you sure?"                               dialogListener="#{viewScope.QueryBean.onDialog}">                        <af:outputText value="It would be time consuming to query for all records. Are you sure you want to continue?" id="ot9"/>                        <f:facet name="buttonBar"/>                    </af:dialog>                </af:popup> Here is how the runtime would be. Enter % for Ename and hit the Search button Popup with a warning message displayed Clicking on Yes / No on the popup performs respective task (perform query / cancel query).

Found an interesting question on OTN. Based on the question, wired a usecase to try out.Usecase : Show a warning to user when they try to search the records (af:querycomponent), without specifying a...

ADF

Calculating time since last query in adf using java script

In some scenarios, we would need to calculate the time elapsed since the last query execution, without contacting the server (i.e without using af:poll component). This blog is to give an example for this scenario by using javascript.OTN question : https://forums.oracle.com/forums/thread.jspa?forumID=83&threadID=2411997Assuming that we have an application with a table in the page, and a commandButton to query the records, we will proceed further to build our usecase.The logical flow of this implementation would be like,1. Execute the query2. When the button clicked, reset the previous time3. Set the time to 0.4. Trigger the timer to increment time. Now, implementation comes. Lets add an output text to display the time lapsed <af:outputLabel value="Minutes since last query :" id="ol1"/>        <af:outputText value="" id="ot9" clientComponent="true"/> Since we would be accessing the output text from javascript, we would need to make it available to client by setting clientComponent to true. We now need to add a javascript code to our page, to count the minutes and display in the output text.         <af:resource type="javascript">         function updateTimer(){            var opTxt = AdfPage.PAGE.findComponentByAbsoluteId('ot9');            var curMins = opTxt.getProperty('value');            if(curMins == '' || curMins == null)                 opTxt.setProperty('value','0');                            else                opTxt.setProperty('value',parseInt(opTxt.getProperty('value')) + 1);        }        </af:resource> In the above code, we find the outputText component (with id ot9), get its value. If the value is blank or null, then set it to 0. If it is a non-zero number, then increment it. Now, we need to call this method every minute to update the output text. For this, we will add another JS function.         function startTimer(){            var opTxt = AdfPage.PAGE.findComponentByAbsoluteId('ot9');            opTxt.setProperty('value','');            updateTimer();            var int=window.setInterval("updateTimer()",60000);        } This function finds the outputText (with id ot9), resets its value (i.e set it to blank) and then schedules the function we've created first (updateTimer()) to be called every minute (i.e 60000 milliseconds). Assuming we have a button to execute the query, we'll add a client listener to the button to execute this function when pressed.                 <af:commandButton actionListener="#{bindings.Execute.execute}" text="Execute"                                                                                disabled="#{!bindings.Execute.enabled}"  id="cb1" partialSubmit="true">                          <af:clientListener method="startTimer" type="action" />                </af:commandButton> Ouput would be like below.

In some scenarios, we would need to calculate the time elapsed since the last query execution, without contacting the server (i.e without usingaf:poll component). This blog is to give an example for...

ADF

An Epic Question "How to call a method when the page loads"

Quite often, there comes a question in OTN, with different subjects, all meaning "How to call a method when my ADF page loads?". More often, people tend to take the approach of ADF Phase Listener by overriding before/afterPhase methods.In this blog, we will go through different options in achieving it.1. Method Call Activity as default activity in Taskflow :If the application is built with taskflows, then this is the best suited approach to take. 1.a. Calling a Data Control Method :To call a Data Control method (ex: A method in AMImpl exposed as client interface), simply Drag and Drop the method as Default Method Call Activity, then draw a control flow case from the method to your page. Once after this, drop the taskflow as region in main page. When we run the main page, the Method Call Activity would be called first, and then the page will be rendered.1.b. Calling a Method in Backing Bean:To call a method in the backing bean before pageload, we can follow the similar approach as above. Instead of binding the Method Call Activity to an action/method binding in pagedef, we bind to the method. Insert a Method Call Activity (and make it as default) from the Component Palette. Double click on to select a method to bind. This approach can also be used, to perform some action in backing bean along with calling a method Data Control (just need to add bindings code in backing bean to execute DC method). 2. Using invokeAction Executable :If the application is built with pages and no taskflows are involved, then this option can be taken into consideration.In the page definition of the page, add an invokeAction Executable and bind it to the method needed to be executed. 3. Using combination of Server and Client Listeners : If the page does not have any page definition, then to call a method in backing bean, this approach can be taken. In this, a serverListener would be added at the document level, which would be calling the method in backing bean. Along with this, a clientListener would be added with "load" type (i.e will be triggered when the page loads), which would queue a serverEvent to trigger the method. 4. Using Page Phase Listener :This should be the last resort. Care should be taken when using this approach since the Phase Listener would be called for each request sent by the client.Zeeshan Baig's blog covers this scenario.

Quite often, there comes a question in OTN, with different subjects, all meaning "How to call a method when my ADF page loads?". More often, people tend to take the approach of ADF Phase Listener by...

Webservices

Executing Put operation of REST service programatically from ADF App

In quite some cases, we would like to call the PUT method on a REST service by constructing the parameters during runtime and pass it on. In this article, we would go through how to deal with such cases when building an ADF Application. Refer this tutorial for introduction to REST service in where, GET and DELETE methods are explained. In this sample, we'll see how to implement PUT operation using a HashMap. In fact, as like in the above tutorial, we can directly execute the PUT method as well. This article is mainly concentrated on how to construct the parameters dynamically at runtime. First let us create a simple POJO to hold employee records. package project1;import javax.xml.bind.annotation.XmlRootElement;@XmlRootElementpublic class Emp { public Emp() { super(); } private String name; private int id; private int exp; private int salary; public Emp(String name, int id, int exp, int salary) { super(); this.name = name; this.id = id; this.exp = exp; this.salary = salary; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setId(int id) { this.id = id; } public int getId() { return id; } public void setExp(int exp) { this.exp = exp; } public int getExp() { return exp; } public void setSalary(int salary) { this.salary = salary; } public int getSalary() { return salary; } public String toString() { String empXml = "<name>"+getName()+"</name>"+"\n"+ "<id>"+getId()+"</id>"+"\n"+ "<experience>"+getExp()+"</experience>"+"\n"+ "<salary>"+getSalary()+"</salary>"; return empXml; }}Then, create a REST service using the for the Employee. package project1;import javax.ws.rs.Path;import java.util.*;import javax.ws.rs.Consumes;import javax.ws.rs.DELETE;import javax.ws.rs.GET;import javax.ws.rs.POST;import javax.ws.rs.PUT;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;import javax.ws.rs.QueryParam;import javax.ws.rs.core.Response;@Path("/test")public class Service { static ArrayList<Emp> emp = new ArrayList<Emp>(); public Service() { super(); } @GET @Produces("application/xml") public ArrayList<Emp> getEmps() { return emp; } @DELETE public void deleteEmp(@QueryParam("id") int id) { emp.remove(getObj(id)); } @PUT @Consumes("application/xml") public void addEmp( Emp e) { emp.add(e); } @PUT @Path("defaultEmp") public Response addEmp() { emp.add(new Emp("abc",1,5,10000)); emp.add(new Emp("xyz",2,7,15000)); emp.add(new Emp("lmn",3,5,8000)); return Response.ok().build(); } @POST public void upadteEmp(@QueryParam("id")int id,Emp e) { deleteEmp(id); addEmp(e); } public Emp getObj(int id) { Iterator i = emp.iterator(); while(i.hasNext()){ Emp emp = (Emp)i.next(); if((emp.getId())==id) { System.out.println(emp.getName()); return emp; } } return null; }}We'll come to the UI part now.After creating a Fusion Web Application from JDeveloper, create a new URL Data Control for the REST service created above (for GET and PUT Operations).DataControls.dcx looks like below Now, our aim is to have a UI, from where we can enter the employee details. Once after having the data, construct parameter object and execute loadData (PUT) method.This is done by having 4 input texts and bind them to attributes in the backing bean. Drag and Drop the loadData method from RestPut DataControl (and do not specify a value for the parameter).And the code snippet of the jspx page <af:panelFormLayout id="pfl1"> <f:facet name="footer"> <af:commandButton text="Put" disabled="#{!bindings.loadData.enabled}" id="cb1" actionListener="#{pageFlowScope.RestBean.performPut}"/> </f:facet> <af:inputText label="Id" id="it1" value="#{pageFlowScope.RestBean.id}" autoSubmit="true"/> <af:inputText label="Name" id="it2" autoSubmit="true" value="#{pageFlowScope.RestBean.name}"/> <af:inputText label="Exp" id="it3" value="#{pageFlowScope.RestBean.exp}" autoSubmit="true"/> <af:inputText label="Sal" id="it4" autoSubmit="true" value="#{pageFlowScope.RestBean.sal}"/></af:panelFormLayout> In the backing bean (RestBean), we have 4 attributes with accessors that are mapped to the Text Items. private Number id,sal,exp; private String name; public void setId(Number id) { this.id = id; } public Number getId() { return id; } public void setSal(Number sal) { this.sal = sal; } public Number getSal() { return sal; } public void setExp(Number exp) { this.exp = exp; } public Number getExp() { return exp; } public void setName(String name) { this.name = name; } public String getName() { return name; } Now, we'll add an actionListener code in the backing bean, in that, we can construct a Map with the required values and then execute the method by passing Map to it. public void performPut(ActionEvent actionEvent) { BindingContainer bindings = getBindings(); Map putParamMap = new HashMap(); putParamMap.put("id", getId()); putParamMap.put("name", getName()); putParamMap.put("exp", getExp()); putParamMap.put("sal", getSal()); OperationBinding operationBinding = bindings.getOperationBinding("loadData"); operationBinding.getParamsMap().put("emp",putParamMap); Object result = operationBinding.execute(); if (!operationBinding.getErrors().isEmpty()) { System.out.println("Error processing put operation.."); } } public BindingContainer getBindings() { return BindingContext.getCurrent().getCurrentBindingsEntry(); }In the above code, we find the loadData method from the DataBindings entry, create a Map with all the required attributes to create an Employee record, get the Parameter list for the method and pass the Map to method as parameter to execute it.

In quite some cases, we would like to call the PUT method on a REST service by constructing the parameters during runtime and pass it on. Inthis article, we would go through how to deal with such...

ADF

Refreshing One Column based on the value of Another Column in ADFdi Table

When using ADF Desktop Integration, quite frequently, we get into a situation where we would like to refresh one column based on the value of another column. In ADF Faces, we can achieve this by setting the autoSubmit property and partialTriggers property for the corresponding columns.However, in ADFdi, we do not have such option. Though we can achieve this by using LOVs and Dependent LOVs. But, in some scenarios we would like to achieve this when using an Input Text Component. In this article, we will simulate this Auto Refresh functionality in a ADFdi Table.Note : Since we would be using VBA code to achieve this, we can use this only on the Macro Enabled Excel Workbooks.Let us assume that we have a View Object based on the Emp table. We could take an example of having a transient attribute in the VO, that gives the sum of Salary and Commission attributes. In the above example, we've added a new transient attribute (SalPlusComm) to the EmpVO, that would give the sum of Sal and Comm attributes. Since we need this attribute to get refreshed when either Sal or Comm attribute changes, we set the Sal and Comm attributes as Dependencies. Also, we set the AutoSubmit property (under UI Hints tab) for the Sal and Comm attributes. Now, we are done with the model layer. We can now, create a jspx page and then Drag and Drop EmpView as ADF Table. After this, we create an Excel Workbook (macro enabled), enable ADF Desktop Integration for it, set the required Workbook Properties, and then add a Table based on the EmpView. As there are no straight forward way in ADFdi to trigger a request to server when a value of a cell is changed, we will now add a DoubleClickActionSet for the Sal and Comm columns. This DoubleClickActionSet will have the Table.RowUpSync and Table.RowDownSync actions. Above example image shows the DoubleClickActionSet for Sal column. In the same manner, we need to add the DoubleClickActionSet for the Comm column as well.Now, we have the workbook, that would fetch the SalPlusComm attribute (after recalculation in the model), when we change the Sal / Comm attribute and then double click on that column. To do this automatically when the user tabs out / presses enter key on the cells, we'll write a bit of VBA Code on the Worksheet where we've this table (Go to Developer Tab and Click on Visual Basic). Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 14 Or Target.Column = 15 Then Target.Select Application.CommandBars("Cell").Controls("Invoke Action...").Execute End IfEnd SubExcel would trigger Worksheet_Change event when a cell in the worksheet is modified. So, we would code our logic in that event. The above code assumes that Sal column is present in the N (14th) column on the worksheet and Comm column is present in O (15th) column. So, we would execute our logic only when the contents in these two columns change.ADFdi would provide a context menu (Invoke Action...) when a DoubleClickActionSet is added to a particular column. We'll make use of that context menu and invoke it programatically. We invoke that context menu programatically using the following line of code Application.CommandBars("Cell").Controls("Invoke Action...").Execute Now, we run our workbook, modify the value of Sal column for any row and tab out of that field would automatically update the value of SalPlusComm column. Here, a simple example (Transient Attribute) is taken for the explanation. In the similar fashion, we can also have a DoubleClickActionSet to contain a method in the Impl that would perform this calculation as well. Tip: If you are not able to view the image fully, right click on the image and choose View Image option to see it completely.

When using ADF Desktop Integration, quite frequently, we get into a situation where we would like to refresh one column based on the valueof another column. In ADF Faces, we can achieve this by...

ADF

Dynamic Pie Graph Generation by Drag And Drop Rows from ADF Table

In normal scenarios, we display the graph and chart to get graphical representation of data. In this article, we'll see how to create graph dynamically by dragging the contents from ADF table and dropping on the graph.Environment : JDeveloper PS5 (11.1.1.6.0)Assuming that we have a table that displays the Department's details. We'll build a dynamic pie graph to display the Employee details for the departments that are dragged from the Department's table. For our usecase, we need to drag the Departments from Table and Drop it on the Pie Chart to get the Employees details corresponding to the Depts selected.For this, we need to add DragSource in the Dept Table and DropTarget in Emp Chart. <af:table value="#{bindings.DeptView1.collectionModel}" var="row"  rows="#{bindings.DeptView1.rangeSize}"  emptyText="#{bindings.DeptView1.viewable ? 'No data to display.' : 'Access Denied.'}"  fetchSize="#{bindings.DeptView1.rangeSize}"  rowBandingInterval="0"  selectionListener="#{bindings.DeptView1.collectionModel.makeCurrent}" rowSelection="multiple" id="t1"> <af:dragSource discriminant="Dept" defaultAction="COPY"/> ....  .... <dvt:pieGraph id="pieGraph1" subType="PIE_MULTI" customLayout="CL_NONE"> <af:dropTarget> <af:dataFlavor flavorClass="org.apache.myfaces.trinidad.model.RowKeySet" discriminant="Dept"/> </af:dropTarget> .... .... Now that we've added the drag source and drop target, we need to have a method in our AM/VO's impl class, that take the department number as input and return the list of employees under it and their details as ArrayList. public ArrayList getEmpDetsForDept(int Deptno) { ArrayList empDetsAL = new ArrayList(); getEmpView1().setWhereClause("Deptno=" + Deptno); getEmpView1().executeQuery(); getEmpView1().first(); if(getEmpView1().getRowCount()>0) { empDetsAL.add(new Object[]{""+Deptno, getEmpView1().getCurrentRow().getAttribute("Ename").toString(), new Double(getEmpView1().getCurrentRow().getAttribute("Sal").toString())} ); while (getEmpView1().hasNext()){ empDetsAL.add(new Object[]{""+Deptno, getEmpView1().getCurrentRow().getAttribute("Ename").toString(), new Double(getEmpView1().getCurrentRow().getAttribute("Sal").toString())} ); getEmpView1().next(); } } return empDetsAL; } Now, the main part comes. Pie Graphs can be based on ArrayList. So, in our backing bean, we'll have an attribute of type ArrayList. Also, we'll have a variable to to bind the graph for triggering PPR. private List chartData=new ArrayList(); private UIGraph empChart; public void setChartData(List chartData) { this.chartData = chartData; } public List getChartData() { return chartData; } public void setEmpChart(UIGraph empChart) { this.empChart = empChart; } public UIGraph getEmpChart() { return empChart; }As we need to find out the Departments that are dragged from table, we'll have a method in the backing bean to get the list of dragged Departments, iterate through them, pass each to the AM / VO method created to get Emp details and then construct the ArrayList. public DnDAction dropDeptInPie(DropEvent dropEvent) { RichTable table = (RichTable) dropEvent.getDragComponent(); Transferable t = dropEvent.getTransferable(); DataFlavor<RowKeySet> df = DataFlavor.getDataFlavor(RowKeySet.class, "Dept"); RowKeySet rks = t.getData(df); Iterator iter = rks.iterator(); if(getChartData()!=null) getChartData().clear(); while (iter.hasNext()) { List key = (List)iter.next(); table.setRowKey(key); JUCtrlHierNodeBinding rowBinding = (JUCtrlHierNodeBinding) table.getRowData(); Row row = (Row) rowBinding.getRow(); String Deptno = row.getAttribute("Deptno").toString(); BindingContainer bindings = getBindings(); OperationBinding operationBinding = bindings.getOperationBinding("getEmpDetsForDept"); operationBinding.getParamsMap().put("Deptno", Deptno); ArrayList result = (ArrayList)operationBinding.execute(); if (operationBinding.getErrors().isEmpty()) { if(getChartData()!=null)getChartData().addAll(result); else setChartData(result); } } AdfFacesContext.getCurrentInstance().addPartialTarget(empChart); return DnDAction.NONE; } public BindingContainer getBindings() { return BindingContext.getCurrent().getCurrentBindingsEntry(); } In order to make the Pie Graph use the ArrayList as source, we need to bind this to the tabularData Property of the pie graph. Let us also bind the chart to the variable we created in backing bean and set its dropListener to the method created above. Now, our pieGraph's source in jspx page would look like <dvt:pieGraph id="pieGraph1" subType="PIE_MULTI" customLayout="CL_NONE" binding="#{pageFlowScope.DnDBean.empChart}" tabularData="#{pageFlowScope.DnDBean.chartData}"> <af:dropTarget dropListener="#{pageFlowScope.DnDBean.dropDeptInPie}"> <af:dataFlavor flavorClass="org.apache.myfaces.trinidad.model.RowKeySet" discriminant="Dept"/> </af:dropTarget> Now, let us run the page, select couple of Departments and Drop them on the Pie chart. Here, we've dragged the departments 10 & 30, and dropped them on the chart to get the Salary of the employees belonging to those departments as slices.

In normal scenarios, we display the graph and chart to get graphical representation of data. In this article, we'll see how to create graphdynamically by dragging the contents from ADF table and...

ADF

Passing comma separated string as bind variable for VO query's IN operator

Quite often, we want to pass a parameter to the bind variable in the VO's query with a comma separated value, for the where clause with an IN operator. However, normal SQL query that the VO contain interpret that whole comma separated value as a single String and our usecase fail to get fulfilled.Ex. question in OTN thread : https://forums.oracle.com/forums/thread.jspa?messageID=10125366To overcome this, Mohammad Jabr has written a blog entry with the help of  Steve Muench's example #126. This has been achieved by using a TYPE and CASTing it to get the list.In this article, we'll see another option to alter the query using regexp_substr, without having to use a TYPE and CAST.Let us take an example of a VO created using EMP table with the following query. SELECT Emp.EMPNO, Emp.ENAME, Emp.JOB, Emp.MGR, Emp.HIREDATE, Emp.SAL, Emp.COMM, Emp.DEPTNOFROM EMP Emp We'll add a where clause to the VO's query with a bind variable that takes comma separated string as input. Here, we would be including regexp_substr function (Oracle DB >=10g), to split the comma separated string and return them as rows.Now, our Where clause of the VO's query would be looking like WHERE Emp.ENAME in (select regexp_substr(:Bind_Ename_Comma_Sep_List,'[^,]+', 1, level) from dual connect by regexp_substr(:Bind_Ename_Comma_Sep_List, '[^,]+', 1, level) is not null)Also, we'll add a Bind Variable Bind_Ename_Comma_Sep_List of String data type. Once after modifying the Where Cluase and after adding the bind variable, our VO would be looking like To validate our query, let us run the AM tester to check the result Validate the result by entering a comma separated ENAME list to the bind variable (SMITH,ALLEN,JONES). Check out the query result Asit can be seen, we've passed 3 comma separated Enames to the bind variable, which in turn fetched only those records with the matching 3 Enames.

Quite often, we want to pass a parameter to the bind variable in the VO's query with a comma separated value, for the where clause with an INoperator. However, normal SQL query that the VO contain...

ADF

What does featureOff attribute do in af:panelCollection

Panel Collection in ADF (af:panelCollection) has an attribute - featureOff, which manages the visibility of certain controls / features of panelCollection to the end user.As per the doc guide, here are the list of valid values for this attribute. Value Turns off statusBar Status bar viewMenu 'View' menu formatMenu 'Format' menu columnsMenuItem 'Columns' sub-menu item columnsMenuItem:col1,col20 Columns with column ID: 'col1' and 'col20' inside 'Columns' sub-menu freezeMenuItem 'Freeze' menu item detachMenuItem 'Detach' menu item sortMenuItem 'Sort' menu item reorderColumnsMenuItem 'Reorder Columns' menu item resizeColumnsMenuItem 'Resize Columns' menu item wrapMenuItem 'Wrap' menu item showAsTopMenuItem Tree/TreeTable 'Show As Top' menu item scrollToFirstMenuItem Tree/TreeTable 'Scroll To First' menu item scrollToLastMenuItem Tree/TreeTable 'Scroll To Last' menu item freezeToolbarItem 'Freeze' toolbar item detachToolbarItem 'Detach' toolbar item wrapToolbarItem 'Wrap' toolbar item showAsTopToolbarItem Tree/TreeTable 'Show As Top' toolbar item wrap 'Wrap' menu and toolbar items freeze 'Freeze' menu and toolbar items detach 'Detach' menu and toolbar items In this article, we will find out what happens at runtime when different values are specified for this attribute (Note : This attribute takes a space-separated list of default features to be turned off for the panelCollection - as mentioned above)1. statusBar <af:panelCollection id="pc1" featuresOff="statusBar">When we set statusBar to the featuresOff attribute, it hides panelCollection's status bar. 2. viewMenu <af:panelCollection id="pc1" featuresOff="viewMenu">When we set viewMenu to the featuresOff attribute, it completely removes the View Menu. 3. formatMenu  <af:panelCollection id="pc1" featuresOff="formatMenu"> When we set formatMenu to the featuresOff attribute, it completely removes the Format Menu. 4. columnsMenuItem  <af:panelCollection id="pc1" featuresOff="columnsMenuItem"> When we set columnsMenuItem to the featuresOff attribute, it removes the Columns menu item under View menu. Check the next option to hide specific columns. 5. columnsMenuItem:col1,col20<af:panelCollection id="pc1" featuresOff="columnsMenuItem:col1,col2"> When we set columnsMenuItem:.. to the featuresOff attribute, it removes the specified columns from the Columns menu item under View menu. If you want to hide the entire Columns menu item, check the previous option. In the above example image, columns c3 and c4 belong to the columns Empno and Ename. 6. freezeMenuItem <af:panelCollection id="pc1" featuresOff="freezeMenuItem"> When we set freezeMenuItem to the featuresOff attribute, it removes Freeze menu item under View menu . 7. detachMenuItem <af:panelCollection id="pc1" featuresOff="detachMenuItem"> When we set detachMenuItem to the featuresOff attribute, it removes Detach menu item under View menu . 8. sortMenuItem <af:panelCollection id="pc1" featuresOff="sortMenuItem"> When we set sortMenuItem to the featuresOff attribute, it removes entire Sort menu item under View menu . 9. reorderColumnsMenuItem<af:panelCollection id="pc1" featuresOff="reorderColumnsMenuItem"> When we set reorderColumnsMenuItem to the featuresOff attribute, it removes Reorder Columns... menu item under View menu . 10. resizeColumnsMenuItem <af:panelCollection id="pc1" featuresOff="resizeColumnsMenuItem"> When we set resizeColumnsMenuItem to the featuresOff attribute, it removes Resize Columns... menu item under Format menu . 11. wrapMenuItem <af:panelCollection id="pc1" featuresOff="wrapMenuItem"> When we set wrapMenuItem to the featuresOff attribute, it removes Wrap menu item under Format menu . 12. showAsTopMenuItem <af:panelCollection id="pc1" featuresOff="showAsTopMenuItem"> When we set showAsTopMenuItem to the featuresOff attribute, it removes Show as Top and Go to Top menu items under View menu (Applicable for the tree/treeTable) . 13. scrollToFirstMenuItem <af:panelCollection id="pc1" featuresOff="scrollToFirstMenuItem"> When we set scrollToFirstMenuItem to the featuresOff attribute, it removes Scroll to First menu item under View menu (Applicable for the tree/treeTable) . 14. scrollToLastMenuItem <af:panelCollection id="pc1" featuresOff="scrollToLastMenuItem"> When we set scrollToLastMenuItem to the featuresOff attribute, it removes Scroll to Last menu item under View menu (Applicable for the tree/treeTable) . 15. freezeToolbarItem <af:panelCollection id="pc1" featuresOff="freezeToolbarItem"> When we set freezeToolbarItem to the featuresOff attribute, it removes Freeze button from the Toolbar. 16. detachToolbarItem <af:panelCollection id="pc1" featuresOff="detachToolbarItem"> When we set detachToolbarItem to the featuresOff attribute, it removes Detach button from the Toolbar. 17. wrapToolbarItem <af:panelCollection id="pc1" featuresOff="wrapToolbarItem"> When we set wrapToolbarItem to the featuresOff attribute, it removes Wrap button from the Toolbar. 18. showAsTopToolbarItem <af:panelCollection id="pc1" featuresOff="showAsTopToolbarItem"> When we set showAsTopToolbarItem to the featuresOff attribute, it removes Go Up, Go to Top and Show as Top buttons from the Toolbar (Applicable for tree/treeTable). 19. wrap <af:panelCollection id="pc1" featuresOff="wrap"> When we set wrap to the featuresOff attribute, it removes Wrap menu item from Format Menu as well as from the Toolbar. Equivalent to featuresOff="wrapMenuItem wrapToolbarItem". 20. freeze <af:panelCollection id="pc1" featuresOff="freeze"> When we set freeze to the featuresOff attribute, it removes Freeze menu item from View Menu as well as from the Toolbar. Equivalent to featuresOff="freezeMenuItem freezeToolbarItem". 21. detach <af:panelCollection id="pc1" featuresOff="detach"> When we set detach to the featuresOff attribute, it removes Detach menu item from View Menu as well as from the Toolbar. Equivalent to featuresOff="detachMenuItem detachToolbarItem". These options would be useful when using a panelCollection for customizing at end user. A separate options could be provided using these, so that end user can customize the LAF of the panelCollection.

Panel Collection in ADF (af:panelCollection) has an attribute - featureOff, which manages the visibility of certain controls / features of panelCollection to the end user.As per the doc guide, here...

BC4

Business Rules Editor for View Objects in JDeveloper 11.1.2.0.0

JDeveloper 11.1.2.0.0 has a new tab in the View Objects Editor - Business Rules. This easily tend to make people misunderstand that this Editor can be used for adding validation rules for the attributes in the View Object. However, it is not true. Lets check out what this editor is all about. As the online help for this page statesUse to create and maintain business rules based on Groovy Language expressions and declarative validation rules for this view object including: Validators for transient attributes Bind variable default value expressions for SQL queries Bind variable value mappings for view accessors Transient attribute value expressions Transient attribute value expression recalculation conditions Attribute default value expressions We'll see how we can use this editor to edit different types : Transient Attributes :  We can use this editor for a. adding validation rules, b. edit default value expression a. As like the Entity Attributes, we can add many validation rules for the transient attributes in VO as well. Ex. In the above image, EmpType is a transient attribute on Emp VO.We can see there are two rules added. First one is a validation rule (List Validator), restricting the user to enter either one of the value specified for the attribute. Second one is the default value expression for the attribute. Upon selecting the node, the default value groovy expression would become editable in the Script Expression field below, wherein we can modify it and test the syntax as well.Note : We can add the validation rule only for the transient attributes which are Updatable. Also, we can edit only the default values which are script expressions only. Not the literal values.Bind Variables :Similar to the transient attributes, we can use this editor for modifying and testing the default value expression for the Bind Variables of the VO as well.Ex : In the above example image, we can see a Bind Variable (Bind_Hiredate) added to the Query, which has the default value expression as adf.currentDate.Using this editor, we can modify this expression and test the syntax.View Accessor : If we have a bind variable to the VO and use it as List Data Source for any of the attributes in the VO, we can use this editor to change the value of the bind variable in the View Accessor.Ex : In the above example image, we have couple of Bind Variables in the View Accessors (they are used as Lists and Dependent Lists for this View Object). Using this editor, we can edit the values of those bind variables. We can also use this editor for modifying and testing the default value expression on the VO attributes and the re-calculation conditions.

JDeveloper 11.1.2.0.0 has a new tab in the View Objects Editor - Business Rules. This easily tend to make people misunderstand that this Editor can be usedfor adding validation rules for the...

Faces

Paritally restricting user entry in the ADF input text - using Java Script

Recently came across a forum post in which the OP wanted to let the users edit the content of the text field partially. https://forums.oracle.com/forums/thread.jspa?forumID=83&threadID=2259832Here is an example. Let us assume the input text contains the following text. "You can edit the content inside { this }". In this, users should be able to edit only the content inside { }. I.e Only "this" should be editable. To achieve this, we can use a java script method, that tracks the cursor position and ignore the user edits if the cursor position is not between the curly braces. After which, the method would be used in the client listener for the input text.Example code snippet.<af:inputText label="Partial Editable Text Item" id="it1" value="You can edit the content inside { this }" clientComponent="true" ><af:clientListener type="keyPress" method="validateValue" /> </af:inputText><af:resource type="javascript"> function validateValue(evt){ var inputTxt=document.getElementById('it1::content'); var startPos = inputTxt.value.indexOf("{"); var endPos = inputTxt.value.indexOf("}"); var cursorPos = inputTxt.selectionStart; if (cursorPos &lt; startPos+2 || cursorPos > endPos-1) { alert("Cannot Edit"); evt.cancel(); } }</af:resource>More complex example by Frank Nimphius http://blogs.oracle.com/jdevotnharvest/entry/get_social_security_numbers_rightNote : Tested the above snippet successfully in Mozilla Firefox and IE 9.

Recently came across a forum post in which the OP wanted to let the users edit the content of the text field partially. https://forums.oracle.com/forums/thread.jspa?forumID=83&threadID=2259832 Here is...

ADF

Adding graph in excel based on the content of ADFdi Table

Often we tend to represent the data present in the table in a graphical format to give a visual impression of the data. This article would be explaining the way to achieve it using the data we have in ADFdi table of the integrated workbook.Pre-requisites:Microsoft Office 2007JDeveloper 11.1.1.1.0 and aboveAssuming we are already having an ADFdi enabled workbook with a table based on an Employee table as shown in the image below.Also, add the table.download to the ribbon toolbar as menu item / as action for the startup event.From excel, we'll add a new 3D bar chartNow, we need to select the data range for the chart. We will take an example of chart based on the salary of the employees. So, the data for the X-Axis of the chart would be the Ename and the data for the Y-Axis being the salary. We can do that by right clicking on the Chart and selecting Select Data. We would select the Legend Entry Series name as the Sal header column in the table, and for the data, we select both the header row and the row below it (by holding Shift key).And, for the Category Axis, we select the Ename header row and the row below it (by holding Shift key).We can get the chart now, by running the Workbook and downloading the data into the table.This simple example can be enhanced for complex graphs by using the data from the ADFdi table to use the power of excel along with ADF Desktop Integration.

Often we tend to represent the data present in the table in a graphical format to give a visual impression of the data. This article would be explaining the way to achieve it using the data we have in...

ADF

Getting all selected rows in ADF Table with multiple rows selection enabled

When we build a web application which contains an ADF Table (with multiselect option), in many cases, we require to get all the selected rows to process through backing bean. This example will illustrate how to achieve that. Assuming that we already have an application, that contains an ADF Table with multi-selection enabled (i.e the web page look something like the image shown below). img empTableRT : Table based on Emp To access the table in the backing bean (through command button click, for ex.), we add an attribute with accessors in the backing bean and bind it to ADF Table RichTable empTable; public void setEmpTable(RichTable empTable) { this.empTable = empTable; } public RichTable getEmpTable() { return empTable; } code snippet of the af:table in jspx page. <af:table value="#{bindings.EmpView1.collectionModel}" var="row" rows="#{bindings.EmpView1.rangeSize}" emptyText="#{bindings.EmpView1.viewable ? 'No data to display.' : 'Access Denied.'}" fetchSize="#{bindings.EmpView1.rangeSize}" rowBandingInterval="0" selectedRowKeys="#{bindings.EmpView1.collectionModel.selectedRow}" selectionListener="#{bindings.EmpView1.collectionModel.makeCurrent}" rowSelection="multiple" id="t1" binding="#{backingBeanScope.EmpBean.empTable}"> Let us add a command button in the jspx page to print down the "Ename"s of selected rows. <af:commandButton text="Print selected Emps" id="cb1" action="#{backingBeanScope.EmpBean.printSelectedEmpNames}"/> The method printSelectedEmpNames in the backing bean gets the selected row keys from the table, gets the corresponding Enames from the iterator (on which the table is based on) and prints them. public String printSelectedEmpNames() { RowKeySet selectedEmps = getEmpTable().getSelectedRowKeys(); Iterator selectedEmpIter = selectedEmps.iterator(); DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry(); DCIteratorBinding empIter = bindings.findIteratorBinding("EmpView1Iterator"); RowSetIterator empRSIter = empIter.getRowSetIterator(); while(selectedEmpIter.hasNext()){ Key key = (Key)((List)selectedEmpIter.next()).get(0); Row currentRow = empRSIter.getRow(key); System.out.println(currentRow.getAttribute("Ename")); } return null; } We run the page and click button to check the selected rows. As we've selected 7 rows, clicking on the "Print selected Emps" button is expected to print 7 Enames. But..... It just prints only one Ename. CLARK Well, this is because of the selectedRowKeys property of the af:table. Let us try removing that and see if we get the expected output. <af:table value="#{bindings.EmpView1.collectionModel}" var="row" rows="#{bindings.EmpView1.rangeSize}" emptyText="#{bindings.EmpView1.viewable ? 'No data to display.' : 'Access Denied.'}" fetchSize="#{bindings.EmpView1.rangeSize}" rowBandingInterval="0" selectionListener="#{bindings.EmpView1.collectionModel.makeCurrent}" rowSelection="multiple" id="t1" binding="#{backingBeanScope.EmpBean.empTable}"> Now, when we run the page, select 7 rows and click on the print button, it prints out JONESALLENCLARKWARDSMITHMARTINBLAKE That is what we expected. Now, the question is why this happens?. It is because, since value of this selectedRowKeys property is #{bindings.EmpView1.collectionModel.selectedRow}, the selectedRowKeys will contain only the "row which is selected last". By unsetting this attribute, we let the table to push all the selected rows to selectedRowKeys, which will help us during getEmpTable().getSelectedRowKeys(); in the backing bean. JDeveloper automatically adds this property to the ADF Table when it is created by dragging from the data control. So, removing this property from the af:table would get us desired result.

When we build a web application which contains an ADF Table (with multiselect option), in many cases, we require to get all the selected rows to process through backing bean. This example will...

Database

How to split comma separated string and pass to IN clause of select statement

In some cases, we get a comma separated string as output (say from another select statement) that we would need to pass to the IN clause of a select statement.This article explains how to achieve that using regexp_substr (DB >=10g).For example, assume a select statement returns the following'SMITH,ALLEN,WARD,JONES'Now, we would need to pass this to another select statement as IN clause and get the output.SQL> select * from emp where ename in ('SMITH,ALLEN,WARD,JONES');no rows selectedWell, this is not our expected output. We expect the query to return 4 rows.This can be achieved by splitting the comma separated string to individual strings and pass it to the IN clause.Oracle provides regexp_substr function, which comes handy for this scenario.First, we will form a query, that splits this comma separated string and gives the individual strings as rows.SQL> select regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level) from dual 2 connect by regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) is not null;REGEXP_SUBSTR('SMITH,A----------------------SMITHALLENWARDJONESThe above query iterates through the comma separated string, searches for the comma (,) and then splits the string by treating the comma as delimiter. It returns the string as a row, whenever it hits a delimiter.We can pass this query to our select statement to get the desired output.SQL> select * from emp where ename in ( 2 select regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level) from dual 3 connect by regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) is not null ); EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO---------- ---------- --------- ---------- --------- ---------- ---------- ---------- 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7566 JONES MANAGER 7839 02-APR-81 2975 20Now, the query returns what we expected.

In some cases, we get a comma separated string as output (say from another select statement) that we would need to pass to the IN clause of a select statement.This article explains how to achieve that...