Please disable your adblock and script blockers to view this page

Search this blog

Showing posts with label Use. Show all posts
Showing posts with label Use. Show all posts

Saturday 8 August 2015

Set ADF Faces Component properties using custom javascript

This post is about using JavaScript in ADF Faces to change default properties , sometimes using JavaScript can make task easier and all scenarios covered in this post are based on very common requirement. One important point is - set clientComponent property of component to true when using JavaScript on that
Why this is important ? (Check what docs say)

whether a client-side component will be generated. A component may be generated whether or not this flag is set, but if client Javascript requires the component object, this must be set to true to guarantee the component's presence. Client component objects that are generated today by default may not be present in the future; setting this flag is the only way to guarantee a component's presence, and clients cannot rely on implicit behavior. However, there is a performance cost to setting this flag, so clients should avoid turning on client components unless absolutely necessary

Read more about clientComponent property - Understanding ADF Faces clientComponent attribute


Set panel group layout properties-


Use this JavaScript function to set panel group layout's layout and other properties

 <!--Function to set panelGroupLayout properties-->
              function changeGroupLayout(evt) {
                  var pgl = AdfPage.PAGE.findComponent('pgl1');
                  pgl.setProperty("layout", "vertical");
                  pgl.setProperty("inlineStyle", "background-color:red");
              }

I have called this function using client listener on a image that is inside my panel group layout

<af:panelGroupLayout id="pgl1" layout="horizontal" clientComponent="true">
                    <af:image source="#{resource['images:5-10.jpg']}" id="i1" inlineStyle="width:250px;height:200px;"/>
                    <af:image source="#{resource['images:13.jpg']}" id="i2" inlineStyle="width:250px;height:200px;">
                        <af:clientListener method="changeGroupLayout" type="dblClick"/>
                    </af:image>
                    <af:image source="#{resource['images:1.jpg']}" id="i3" inlineStyle="width:250px;height:200px;"/>
                </af:panelGroupLayout>

Initially group layout is horizontal-




After executing JavaScript on double click on second image-



Set input component property (inlineStyle, contentStyle, value etc)-


This function is same as previous one , this function sets value in input text , changes it's contentStyle

<!--Function to set af:inputText properties-->
              function changeInputText(evt) {
                  var iText = AdfPage.PAGE.findComponent('it1');
                  iText.setProperty("value", "Ashish Awasthi");
                  iText.setProperty("contentStyle", "background-color:red;color:white;font-weight:bold;");

              }

Called this function on double click event in inputText-

<af:inputText label="Label 1" id="it1" clientComponent="true" unsecure="disabled">
                        <af:clientListener method="changeInputText" type="dblClick"/>
              
                    </af:inputText>


Output is like this-
 on double click inside inputText

In same way we can set disabled property of component . It is a secure property of component , that should not be changed from a client side event normally but if this is a requirement then we have to set disabled in unsecure property of input component. Only disable property is supported as of now
Read more about this property -<af:inputText>


Set panelSplitter width according to browser window width-


This JavaScript function divides af:panelSplitter in equal parts to fit in browser

 <!--Function to set panel Splitter position-->
              function changePanelSpliterPosition(evt) {
                  var width = window.innerWidth;
                  var ps = AdfPage.PAGE.findComponent('ps1');
                  ps.setProperty("splitterPosition", width / 2);
              }

In same way try setting other properties of different components. Soon i will update this post with some more JavaScript functions and examples

Cheers :)  Happy Learning

Friday 2 January 2015

Using captcha with ADF Faces (Integrate Kaptcha project with Oracle ADF)



First of all wishing a very Happy New Year to all of you, learn more n more ADF this year :)


This post is about using captcha challenge in ADF Faces, captcha is used to determine whether user is a human or not
CAPTCHA stands for-Completely Automated Public Turing test to tell Computers and Humans Apart
Frank Nimphius posted about 'captcha with ADF Faces' using "Simple Captcha" project.
You can read complete article- http://www.oracle.com/technetwork/developer-tools/jdev/captcha-099103.html



For this post I am using modern version of simplecaptcha project called Kaptcha, project provides a servlet that is responsible for generating captcha image and there are various configuration parameters to change look n feel of captcha image
See project documentation - https://code.google.com/p/kaptcha/
Download jar file- https://code.google.com/p/kaptcha/downloads/list

Now see the steps to integrate Kaptcha project with Oracle ADF
  • Create a FusionWeb Application, attach kaptcha-2.3.2 jar to viewController project, also see How to use "Kaptcha"-https://code.google.com/p/kaptcha/wiki/HowToUse


  • Next step is to add kaptcha servlet reference in web.xml file

  •  <servlet>
            <servlet-name>Kaptcha</servlet-name>
            <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Kaptcha</servlet-name>
            <url-pattern>/kaptchaimage</url-pattern>
        </servlet-mapping>
    

  • Add an af:image on page to show captcha, image source is referenced from servlet mapping

  • <af:image id="i1" partialtriggers="l1" shortdesc="Captcha" source="/kaptchaimage">
    

  • Default configuration for captcha image is completed , I have added an af:inputText and button on page to enter captcha result .

  • <af:panelBox text="Captcha Demo- www.awasthiashish.com" id="pb1" showDisclosure="false"
                                     inlineStyle="width:350px;">
                            <f:facet name="toolbar"/>
                            <af:spacer width="0" height="10" id="s3"/>
                            <af:panelFormLayout id="pfl1">
                                <af:panelGroupLayout id="pgl1" layout="horizontal">
                                    <af:image source="/kaptchaimage" id="i1" partialTriggers="l1" shortDesc="Captcha"/>
                                    <af:spacer width="10" height="0" id="s4"/>
                                    <af:link id="l1" icon="#{resource['images:reload.png']}" shortDesc="Refresh Captcha"/>
                                </af:panelGroupLayout>
                                <af:inputText label="Enter text" id="it1" binding="#{ReadCaptchaBean.entrdCaptchaBind}"
                                              contentStyle="font-weight:bold;"/>
                                <af:button text="Submit" id="b1" actionListener="#{ReadCaptchaBean.readCaptchAction}"/>
                            </af:panelFormLayout>
                        </af:panelBox>
    

  • Run application and see how captcha image is appearing on page


  • It looks good :-), now see the managed bean code written in submit button's action. This code checks actual captcha value with entered value

  •     //Binding of inputText to get entered value
        private RichInputText entrdCaptchaBind;
    
        public void setEntrdCaptchaBind(RichInputText entrdCaptchaBind) {
            this.entrdCaptchaBind = entrdCaptchaBind;
        }
    
        public RichInputText getEntrdCaptchaBind() {
            return entrdCaptchaBind;
        }
        
        /**Method to check whether entered value is correct or not
         * @param actionEvent
         */
        public void readCaptchaAction(ActionEvent actionEvent) {
            FacesContext fctx = FacesContext.getCurrentInstance();
            ExternalContext ectx = fctx.getExternalContext();
            HttpServletRequest request = (HttpServletRequest) ectx.getRequest();
            //KAPTCHA_SESSION_KEY- The value for the kaptcha is generated and is put into the HttpSession. This is the key value for that item in the session.
            String kaptchaExpected =
                (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
            //Get entered value of captcha using inputText binding
            String kaptchaReceived = entrdCaptchaBind.getValue().toString();
            System.out.println("Entered Value-" + kaptchaReceived + " Expected Value-" + kaptchaExpected);
            if (kaptchaReceived == null || !kaptchaReceived.equalsIgnoreCase(kaptchaExpected)) {
                FacesMessage errMsg = new FacesMessage("Invalid Value");
                errMsg.setDetail("Incorrect captcha value- Not Human");
                errMsg.setSeverity(FacesMessage.SEVERITY_ERROR);
                fctx.addMessage(entrdCaptchaBind.getClientId(), errMsg);
            } else {
                FacesMessage errMsg = new FacesMessage("Correct Value");
                errMsg.setDetail("Hello this is the right guess");
                errMsg.setSeverity(FacesMessage.SEVERITY_INFO);
                fctx.addMessage(entrdCaptchaBind.getClientId(), errMsg);
            }
        }
    

  • Again run this application and enter value for captcha



  • So it is working , now to change captcha image added a link with partialSubmit=false and set partial trigger property on af:image.


  • Kaptcha integration with Oracle ADF is complete and it is working properly  now if you want to modify captcha look n feel then add some init-param (configuration parameter) in web.xml file.
    See complete list of configuration parameters- https://code.google.com/p/kaptcha/wiki/ConfigParameters
    I have changed some parameters value in web.xml , see changed source of web.xml and captcha output

  • <servlet>
            <servlet-name>Kaptcha</servlet-name>
            <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
            <init-param>
                <param-name>kaptcha.border</param-name>
                <param-value>yes</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.border.color</param-name>
                <param-value>red</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.border.thickness</param-name>
                <param-value>1</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.image.width</param-name>
                <param-value>250</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.image.height</param-name>
                <param-value>60</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.textproducer.font.size</param-name>
                <param-value>35</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.textproducer.font.color</param-name>
                <param-value>red</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.background.clear.from</param-name>
                <param-value>orange</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.textproducer.char.length</param-name>
                <param-value>7</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>Kaptcha</servlet-name>
            <url-pattern>/kaptchaimage</url-pattern>
        </servlet-mapping>
    

    again run this application and check output

    Thanks, Happy Learning :)
    Download-Sample ADF Application

Wednesday 13 August 2014

Use View Link Accessor to call aggregate functions, set attribute value , set bind variables value (Oracle ADF)


Hello All

This post is about various usage of view link accessor  , when we create viewLink between two viewObjects , destination accessor is created by default in master viewObject, there is check box to create source accessor also at same time

We can use this view link accessor for calculating attribute's sum, setting value of attributes etc



here Departments is master viewObject and Employees is it's detail, after creating viewLink you can see in viewObject xml source there accessor is present

In Departments ViewObject- 




<ViewLinkAccessor
    Name="Employees"
    ViewLink="sample.model.view.link.DeptTOEmpVL"
    Type="oracle.jbo.RowIterator"
    IsUpdateable="false"/>

In EmployeesViewObject- 
 

<ViewLinkAccessor
    Name="Departments"
    ViewLink="sample.model.view.link.DeptTOEmpVL"
    Type="oracle.jbo.Row"
    Reversed="true"
    IsUpdateable="false"/>

So what is the use of these view link accessors ?
Master accessor in detail viewObject returns current Row of master viewObject, when you generate RowImpl class for detail viewObject , it also has a method for this accessor


    /**
     * Gets the associated <code>Row</code> using master-detail link Departments.
     */
    public Row getDepartments() {
        return (Row) getAttributeInternal(DEPARTMENTS);
    }

    /**
     * Sets the master-detail link Departments between this object and <code>value</code>.
     */
    public void setDepartments(Row value) {
        setAttributeInternal(DEPARTMENTS, value);
    }

Detail accessor in master viewObject returns a row set of all row of details viewObject that are currently referenced by master record

    /**
     * Gets the associated <code>RowIterator</code> using master-detail link Employees.
     */
    public RowIterator getEmployees() {
        return (RowIterator) getAttributeInternal(EMPLOYEES);
    }

Now see what we can do with viewLink Accessor

1. Get master attribute value in detail viewObject

suppose i have to get a attribute's value from Master viewObject (Departments) in a attribute of detail viewObject (Employee)
in this example i am getting managerId from Departments ViewObject so for this just write in expression of Employee's ManagerId field
viewLinkAccesorName.AttributeName


now run BC4J tester and check - create new record in Employee and see managerId from Departments is auto populated

 on creating new record-


2. Call aggregate function to calculate sum of an attribute of detail viewObject

suppose now i have to calculate total salary of a Department (sum of Employees salary of that department)
for this purpose just call sum function to calculate sum of all rows of detail RowSet 
take a transient attribute in Departments ViewObject and write in it's expression
viewLinkAccesorName.sum("AttributeName")


 Run ApplicationModule and see-


3. Set bind variable value as per master viewObject's attribute (pass value from master viewObject)

This  is tricky part as we can not set bind variable value through expression as it doesn't recognize view link accessor name.
created a viewCriteria and bind variable for managerId in Employee viewObject




applied this criteria to Employees viewObject instance in Application Module (Just Shuttle criteria to selected side)


now to set bind variable's value we have to override prepareRowSetForQuery method in Employees VOImpl class

this method gets the value of managerId from currentRow of master ViewObject (Departments)and sets in bind variable of Employees viewObject


    @Override
    public void prepareRowSetForQuery(ViewRowSetImpl viewRowSetImpl) {
        RowSetIterator[] masterRows = viewRowSetImpl.getMasterRowSetIterators();
        if (masterRows != null && masterRows.length > 0 && masterRows[0].getCurrentRow() != null &&
            masterRows[0].getCurrentRow().getAttribute("ManagerId") != null) {
            Integer managerId = (Integer) masterRows[0].getCurrentRow().getAttribute("ManagerId");
            viewRowSetImpl.ensureVariableManager().setVariableValue("BindManagerId", managerId);
            System.out.println("ManagerID in bind Var-" + managerId);

        }
        super.prepareRowSetForQuery(viewRowSetImpl);
    }

now run AM and check it-

Happy Learning :)