Showing posts with label java bean. Show all posts
Showing posts with label java bean. Show all posts

Sunday, November 7, 2010

ADF UI - Getting all pagedef attributes of a particular VO iterator programatically (find transients among them as well :) )

This might be rare requirement to get handle on pagedef attributes of a particular VO iterator. But, it would be quite useful for some scenarios like when you want to get the values of attributes of a particular iterator present in the current jsff page (not each and every VO attribute) and compare them with the original values to know if the user has changed the attribute through the UI. It would be waste of effort to check all VO attributes if they're changed as the user can only change the attributes present in the UI jsff pages.

But, it's not as easy as getting a reference to bindings (DCBindingContainer) and call the method getAttributeBindngs() on it. Even though it returns all the pagedef attribute bindings, they'll include attributes of all VO iterators in the pagedef. The tricky part is to get attributes of only a particular VO iterator in the pagedef. Here, in this post, I'll explain how to do that.

I did some research and wrote the a method to retrieve all the pagedef attributes of the VO iterator specified by 'VOName' as a parameter. This method also has the logic to find out the transient attributes present the VO. This would be quite useful when you want to find out the transient attributes of a VOIterator in the pagedef and to do logic on them (like skipping them for comparision, etc.,).

Method code in the bean:
public void storePageDefAttrs(String VOName) { DCBindingContainer binding = (DCBindingContainer)ADFUtil.evaluateEL("#{bindings}"); //getting the attribute bindings in the pagedef, it'll contain all pagedef attribute bindings of all VO iterators in pagedef List attrBindings = binding.getAttributeBindings(); //getting iterator for attribute bindings Iterator itr = attrBindings.iterator(); //getting the current row for the VOName ViewRowImpl row = (ViewRowImpl)ADFUtil.evaluateEL("#{bindings." + VOName + "Iterator.currentRow}"); //pageDefAttrs will store pageDef attribute names for the given VO specified by 'VOName' List pageDefAttrs = new ArrayList(); //transientAttrs will store trasient attribute names added in the pagedef for the given VO specified by 'VOName' List transientAttrs = new ArrayList(); //iterating through all attribute bindings while (itr.hasNext()) { AttributeBinding attrBinding = (AttributeBinding)itr.next(); //getting the attribute name String attrName = attrBinding.getName(); //getting the iterator binding for the attribute DCIteratorBinding attrIterBinding = (DCIteratorBinding)ADFUtil.evaluateEL("#{bindings." + attrName + ".iteratorBinding}"); //getting the iterator name for the iterator binding String attrIterBidningName = attrIterBinding.getVOName(); //checking if this attribute's iterator name is equal to the passed VOName if (VOName.equals(attrIterBidningName)) { //if the attributes' iterator name is equal to passed VOName, this attributes belongs to the VO specified by 'VOName'. So adding it to pageDefAttrs. pageDefAttrs.add(attrName); //getting the attribute index int attrIndex = row.getAttributeIndexOf(attrName); //getting the view attribute definition ViewAttributeDefImpl vDef = (ViewAttributeDefImpl)row.getViewDef().getAttributeDef(attrIndex); //checking if it's a transient attribute. boolean transientPageDefAttr = (vDef.getEntityAttributeDef() == null) || (vDef.getEntityAttributeDef().getColumnName() == null); //if it's transient, adding it to transientAttrs list if (transientPageDefAttr) { transientAttrs.add(attrName); } } } //stroing the pagedef attribute names and transient attribute names for the given VOName in the pageFlowScope variables. ADFUtil.setEL("#{pageFlowScope.pageDefAttrs}", pageDefAttrs); ADFUtil.setEL("#{pageFlowScope.trasientPageDefAttrs}", transientAttrs); }

The above code is self explanatory from the comments inline. It takes 'VOName' as a parameter and finally stores all pagedef attributes(including transients) for that VO in the ArrayList 'pageDefAttrs'. It'll also store transient attributes of the VO in the ArrayList 'transientAttrs'.

I devloped a sample application that prints the all attributes and transient attributes present in the pagedef. When you download and run the application, it'll open a search page. Search for a record and select one row and click on 'Edit' button. Now, you'll goto edit page and when you click on 'Show Pagedef Attributes' button, it'll print all attributes as well as the transient attributes present in the pagedef.

Attributes in EmpDeptVO definition:

Attributes in DeptVO definition:


Pagedef file containing some of the attributes from EmpDeptVO and DeptVO:
<?xml version="1.0" encoding="UTF-8" ?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="11.1.1.56.60" id="EditEmployeePageDef" Package="com.demo.fragments"> <parameters/> <executables> <variableIterator id="variables"/> <iterator Binds="EmpDeptVO" RangeSize="25" DataControl="DemoAMDataControl" id="EmpDeptVOIterator"/> <iterator Binds="DeptVO" RangeSize="25" DataControl="DemoAMDataControl" id="DeptVOIterator"/> </executables> <bindings> <attributeValues IterBinding="EmpDeptVOIterator" id="Ename"> <AttrNames> <Item Value="Ename"/> </AttrNames> </attributeValues> <attributeValues IterBinding="EmpDeptVOIterator" id="Job"> <AttrNames> <Item Value="Job"/> </AttrNames> </attributeValues> <attributeValues IterBinding="EmpDeptVOIterator" id="Loc"> <AttrNames> <Item Value="Loc"/> </AttrNames> </attributeValues> <attributeValues IterBinding="EmpDeptVOIterator" id="Mgr"> <AttrNames> <Item Value="Mgr"/> </AttrNames> </attributeValues> <attributeValues IterBinding="DeptVOIterator" id="Dname"> <AttrNames> <Item Value="Dname"/> </AttrNames> </attributeValues> <attributeValues IterBinding="DeptVOIterator" id="Loc1"> <AttrNames> <Item Value="Loc"/> </AttrNames> </attributeValues> <attributeValues IterBinding="EmpDeptVOIterator" id="attribute1"> <AttrNames> <Item Value="attribute1"/> </AttrNames> </attributeValues> <attributeValues IterBinding="EmpDeptVOIterator" id="attribute2"> <AttrNames> <Item Value="attribute2"/> </AttrNames> </attributeValues> </bindings> </pageDefinition>



Ouptput attributes on running the sample application:


So, from the above screen shot you can see our method printed the EmpDeptVO's attributes and transient attributes present in the pagdef correctly.

Enjoy :) !

PS: In case, if you're aware of better approach than the above one, please share with me too. Thank you :)

Monday, November 1, 2010

ADF UI - Beginner: Creating data control for java bean

Sometimes, it is necessary to create java bean as a data control so that we can directly drag and drop bean methods into task flows, or add the bean properties as attributes in jsf pages. So, for those who is looking out how to generate a data control for a java bean, it's quite simple. Steps below:

For a simple java bean with the content below,


1. Right click the Java bean and select 'Create Data Control..'


2. Now, it generates an xml data control in the same package. That's it. Data control is generated for the bean.

3. If you expand 'Data Controls' pallette, you would be able to see the bean data control that you just created and you can drag and drop the data control properties and methods into your jsff pages or task flows.

Saturday, October 30, 2010

ADF UI - Navigating to next jsf page programmatically (instead of specifying 'action' declaratively)

The below code shows how to programmatically navigate to next jsf page in taskflow. Mainly this is used for conditional navigation i.e., based on some logic we can dynamically decide which page needs to be shown to the user.

public void submitClicked(ActionEvent actionEvent) { navigate(actionEvent, "submit"); }

Code for navigate() method:
protected void navigate(FacesEvent event, String outcome) { RichRegion regionComponent = null; for (UIComponent uic = event.getComponent().getParent(); uic != null; uic = uic.getParent()) { if (uic instanceof RichRegion) { regionComponent = (RichRegion) uic; break; } } if (regionComponent != null) { FacesContext fc = FacesContext.getCurrentInstance(); ExpressionFactory ef = fc.getApplication().getExpressionFactory(); ELContext elc = fc.getELContext(); MethodExpression me = ef.createMethodExpression(elc, outcome, String.class, new Class[] { }); regionComponent .queueActionEventInRegion(me, null, null, false, -1, -1, event.getPhaseId()); } }
In the above code, 'submit' is the 'action' attribute based on which the next jsff page in the flow will be decided.

ADF UI - Executing the AMImpl method in UI project's java bean which is added as methodAction in pagedef file

Once we write the methods in AMImpl class and expose them in client's interface, they are available under data controls and can be included as 'methodAction' operation bindings in the pagedef files of JSF pages. Now, the question is how to execute this method binding in java bean. The method can be simple void method without any arguments, or it can have arguments with some return type. Below is the sample code to execute AMImpl's method(which is added as methodAction in pagedef file) in java beean.

public void saveSections(ActionEvent ae) { DCBindingContainer bindings = (DCBindingContainer)ADFUtil.evaluateEL("#{bindings}"); //method without parameters OperationBinding opBinding = bindings.getOperationBinding("saveClassSections"); opBinding.execute(); if (opBinding.getErrors().size() == 0) { PopupUtil.invokePopup(confirmationPopup.getClientId(FacesContext.getCurrentInstance())); } } public void classChanged(ValueChangeEvent valueChangeEvent) { DCBindingContainer bindings = (DCBindingContainer)ADFUtil.evaluateEL("#{bindings}"); //method that takes one parameter OperationBinding opBinding = bindings.getOperationBinding("setNoOfPeriods"); opBinding.getParamsMap().put("classCode",valueChangeEvent.getNewValue()); opBinding.execute(); noOfPeriodsDisabled = false; sectionsTableRendered = false; }

Please not that the OperationBinding that we need to import for the above method code is:
import oracle.binding.OperationBinding;


The above two AM methods "saveClassSections" and "setNoOfPeriods" are be included in pagedef as methodAction bindings as below:
<methodAction id="saveClassSections" InstanceName="GreatSchoolsAMDataControl.dataProvider" DataControl="GreatSchoolsAMDataControl" RequiresUpdateModel="true" Action="invokeMethod" MethodName="saveClassSections" IsViewObjectMethod="false"/> <methodAction id="setNoOfPeriods" InstanceName="GreatSchoolsAMDataControl.dataProvider" DataControl="GreatSchoolsAMDataControl" RequiresUpdateModel="true" Action="invokeMethod" MethodName="setNoOfPeriods" IsViewObjectMethod="false"> <NamedData NDName="classCode" NDType="java.lang.String"/> </methodAction>


The actual definitions for these methods in AMImpl are as below and these are exposed in client's interface.

public void saveClassSections() { ViewObjectImpl tVO = getClassSubjectTeacherTVO(); String classCode = (String)tVO.getCurrentRow().getAttribute("ClassCode"); ViewObjectImpl csVO = getClassSectionVO(); ViewObjectImpl lookupsPVO = getLookupsPVO(); Row[] sections = lookupsPVO.getAllRowsInRange(); for (int i = 0; i < sections.length; i++) { Row section = sections[i]; if ((Boolean)section.getAttribute("selected")) { Row csRow = csVO.createRow(); csRow.setAttribute("ClassCode", classCode); csRow.setAttribute("SectionCode", section.getAttribute("LookupCode")); csVO.insertRow(csRow); } } this.getDBTransaction().commit(); } public void setNoOfPeriods(String classCode) { ViewObjectImpl tVO = getClassSubjectTeacherTVO(); ViewObjectImpl csVO = getClassSectionVO(); csVO.setApplyViewCriteriaName("findByClassCode"); csVO.setNamedWhereClauseParam("Bind_ClassCode", classCode); csVO.executeQuery(); csVO.setRangeSize(-1); if (csVO.getAllRowsInRange().length > 0) { tVO.getCurrentRow().setAttribute("NoOfPeriods", csVO.first().getAttribute("NoOfPeriods")); } else{ tVO.getCurrentRow().setAttribute("NoOfPeriods",null); } }


There is another way of invoking AMImpl's methods from Java bean using EL expressions using the util methods in ADFUtil class. ADFUtil class and using the util methods in it has been explained in this post.

Thursday, October 28, 2010

ADF UI - Accessing properties file or resource bundle in java bean

If we directly refer to resource bundle in jsf page by using 'Select text resource..' option available, the c:set tag will be added to the jsff page and we'll use the bundle properties using it's 'var' as a reference.
<?xml version='1.0' encoding='windows-1252'?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:af="http://xmlns.oracle.com/adf/faces/rich" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jsp/jstl/core"> <c:set var="demouiBundle" value="#{adfBundle['com.demo.ui.DemoUiBundle']}"/> <af:panelGroupLayout id="pgl1"> <af:showDetailHeader text="#{demouiBundle['Header.Title']}" disclosed="true" id="sdh1"> <f:facet name="context"/> <f:facet name="menuBar"/> <f:facet name="toolbar"/> <f:facet name="legend"/> <f:facet name="info"/> </af:showDetailHeader> <af:showDetailHeader text="#{pageFlowScope.ExampleBean.headerTitle}" disclosed="true" id="showDetailHeader1"> <f:facet name="context"/> <f:facet name="menuBar"/> <f:facet name="toolbar"/> <f:facet name="legend"/> <f:facet name="info"/> </af:showDetailHeader> </af:panelGroupLayout> </jsp:root>


But, some times there might be needs to refer the properties bundle from java bean to access a property.

This can be done by using the below code.
package com.demo.beans; import java.util.ResourceBundle; import oracle.javatools.resourcebundle.BundleFactory; public class ExampleBean { public String getHeaderTitle() { ResourceBundle rs = BundleFactory.getBundle("com.demo.ui.DemoUiBundle"); return rs.getString("Header.Title"); } }


Content of the sample bundle file:
# sample properties Header.Title=Employee Details EMP_NAME=Employee Name DEPT_NAME=Department Name


Running the above jsff, we'll get the same text by using java bean as well direct reference in jsff (Screen shot below).
Related Posts with Thumbnails