Thursday, October 7, 2021

Oracle ADF-Calling Java Script/java method on page load of .jspx/.jsf

Requirement-In ADF application we often come across requirement where we want to call JavaScript method or java Method on page load or after load o  of .JSPX or .JSF page.


Solution:

First step is to add clientListener onBodyLoad method which gets called on load of page as below

    <af:clientListener method="onBodyLoad" type="load"></af:clientListener>





Java script method as below















Above you can notice I am firing the click event by finding component “main” which is panel group layout as below.

Since there is af:clientListener added inside af:panelGroupLayout onMainClick method  get called.























onMainClick javascript function i am getting OS type of client and passing it to serverListener which is getting called by queueing the event as below





In the bean method of server Listener I am just reading the OS type that is passed and putting it in sessionScope and then refresh output text to show the OS type on UI as below


    public void onTemplateLoad(ClientEvent clientEvent) {

           // Add event code here...

           String osType = (String) clientEvent.getParameters().get("osType");

          

           System.out.println("Os type-"+osType);

       

           ADFContext.getCurrent().getSessionScope().put("OSTYPE", osType);

           AdfFacesContext.getCurrentInstance().addPartialTarget(panelGroupBinding);

 

       }

When you run page it shows first the alert as below




















And then shows OS type as below



Sunday, October 3, 2021

Showing popup while switching ADF Panel tab

Requirement-

In ADF when we use adf panel tab component we often come across requirement where when user switches tabs we want to show user popup saying “Do you really want to switch Tabs? Any uncommitted changes will be lost”. In case user say No we want to keep user on the same tab. 

Solution –

My panel tab jsf/jspx code is as below 



 





Here as highlighted above you can notice that I have java script method which is getting called on disclosure event of af:showDetailItem. 

Java Script code is as below.



























  1. First declare two java script variable that are global on page one for tab to close and one for tab to open
  2. Using disclosure event initialize the two global variables (theTabToClose, theTabToOpen)and then cancel the disclosure event as we want to show popup to user which will ask for confirmation.
  3. using popup.show(); show popup to user asking for confirmation.Popup code is as below 













  1. In Popup that opens there would be two buttons Ok/Cancel. On each button click call handlePopupOkCancel java script method and pass action(Ok/Cancel) as parameter to javascript method using af:clientAttribute .
  2. In handlePopupOkCancel in case action is Ok then we close the tab using javascript as below .After this cancel button event and hide popup.

if (butPressed == 'OK') {

                  theTabToClose.setDisclosed(true);

              }

Final result when user switches tab –Here if you click cancel then tab is not switched and if you click ok tab will be switched.Please note the database rollback code you can write in disclosureListener of af:showDetailItem which would be java method in backing bean.



 

Saturday, September 25, 2021

Jdeveloper Integrated server -Importing SSL certificate for webservice call

Requirement-For local development using Jdeveloper when we call any webservice which is SSL enabled which is very common and when we call any SSL enabled service from Jdeveloper we get SSL handshake error something like pkix path building failed: sun.security.provider.certpath.suncertpathbuilderexception: unable to find valid certification path to requested target.

Solution

For this firstly we need to identify which is the trust keystore for local integrated server .For this start local weblogic server and go to default server à keystores as shown in below screenshot.

Here you can find path of trust keystore used by integrated server of Jdeveloper.


Go to trust keystore  path mentioned in above screenshot .In my case it is C:\Oracle\Middleware\wlserver_10.3\server\lib\DemoTrust.jks 

Now we need to import the SSL certificate of webservice we are calling on above JKS .So step 1 would be to download the SSL certificate of webservice we are trying to call which can be done using below command.

1.      openssl s_client -servername abc.webservicehost.ent -connect abc.webservicehost.ent:8243 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > abc.crt

certificate gets downloaded with name abc.crt

(install open ssl for windows if it is not installed)

2.      Now we need to add this certificate in DemoTrust.jks .password for this jks is “DemoTrustKeyStorePassPhrase”.This you can either do this by installing keystore explorer in windows or using command below

a.      Using keystore explorer open DemoTrust.jks it will ask for password which is DemoTrustKeyStorePassPhrase.

b.      Once open go  to tools and click import certificate and select certificate downloaded in step1 above i.e. abc.crt

c.      Using command, you can do as below. Go to JDK home in your windows and execute below command

      keytool -import -keystore C:\Oracle\Middleware\wlserver_10.3\server\lib\DemoTrust.jks -storepass DemoTrustKeyStorePassPhrase  -file abc.crt -alias webservicecertalias

 


Now restart Integrated weblogic server of Jdeveloper and run the webservice call again.You will not see any SSL handshake error. 



 

 

           


Sunday, July 25, 2021

Jdeveloper - javax.xml.ws.WebServiceException: No Handler for OWSM Security Policy found.

Frequently  when we call any webservice using Jax-WS proxy client .In this case we create jar of the proxy and consume it any other jdeveloper project .sometime when we call the any webservice method .It gives below error


javax.xml.ws.WebServiceException: No Handler for OWSM Security Policy found.


caused by 


oracle.jbo.JboException: JBO-29000: Unexpected exception caught: javax.xml.ws.WebServiceException, msg=No Handler for OWSM Security Policy found.


Solution 

Go to project properties of the consuming project-->libraries  and classpath  and add JAX-WS Client and JAX-WS Webservices in project as shown in below screenshot.

Re run application and it will work 




Wednesday, June 9, 2021

Oracle ADF: af:query hide Add Fields button

Requirement-In Oracle ADF we use af:query along with resulting table in advance mode.When use  af:query in advance mode the UI is displayed as something like below. Usually clients dont want add fields option in advance search as it has all fields that doesn't makes sense to user.

Unfortunately there is no attribute in af:query components that allows us to remove this button.

Screenshot with add field option .








Now to hide this add fields button do below steps

1.Take the Id of Add field button using inspect element in browser .In my case id was "pt1:r2:0:qryId2:adFlds".It will vary based on id of query component and page you are using.















2.At the end of jsff file create a output text that has no next and creating component  binding in backing bean as below.

Please note this need to be at the end of jsff file so that it is rendered at the last in lifecycle.





In Getter method of above created binding right code to get the add fields button component using java script by component id we got in step 1 .Once you find the component set display =none to hide the add fields button.

Backing bean code,as shown below i have written hideAddFieldSection method.


Now if you run the page again you dont see add fields button .Hope this helps






Friday, June 4, 2021

Error: [ADF security error] -while adding transient expression in ADF 12c

In ADF 12c when we want to have transient expression in entity object for example primary key of Entity object is coming from DB sequence then we declare the expression as shown in below

(new oracle.jbo.server.SequenceImpl("SEQUENCE_NAME", adf.object.getDBTransaction())).getSequenceNumber()






















After this if you compile the project you get below error

Error(10,1): [Static type checking] - [ADF security error] Calling the constructor for class oracle.jbo.server.SequenceImpl is not permitted.&#xA; @ line 10, column 1.


Which means that the entity is not trusted the expression changes. To solve this follow below steps

1.Go to the source of the entity object xml file 

2. go to  "TransientExpression" of the attribute which you are adding expression as shown in      screenshot   below 

3.Check the value of the attribute "trustMode"

4.By default  it is "untrusted", change it to "trusted" or remove it

Now recompile the project. Compiler issue doesn't occur








hope this helps

Monday, May 31, 2021

Consume Rest Service Using GSON jar

I am going to demonstrate how to consume rest API service Using Google Json jar that GSON jar .First you need to down the GSON jar .I am using gson-2.8.6.jar for my demo.

Rest service that i am is hosted at http://localhost:8080/employees .when hit GET request to this in postman or in browser i get response as below.

Response-

{

    "employeeList": [

        {

            "employeeId": "1234",

            "employeeName": "Dhiraj Shigavi",

            "departmentName": "Information technology"

        },

        {

            "employeeId": "7777",

            "employeeName": "John Den",

            "departmentName": "Electronic andtele communication"

        }

    ]

}


To Consume this in java follow below steps.
1. create java project in jdeveloper ( you can user any IDE of your choice).
2.add the GSON jar file downloaded in project properties as below



3. Create java Class and name it ConsumeRestServiceWrapper.java.
4. Now first we need to understand the response and create java equivalent classes of  it so we can parse the response using Gson jar file

In this case my response contains employeeList which is list so i will create a class which contains list object of employeeList ,now type of List object contains employeeId,employeeName,departmentName so will create another class which will have these three names of String object in as below.
So My Employee Class is as below.
 
public class Employee {
    private String employeeId;
    private String employeeName;
    private String departmentName;

    public Employee(String employeeId, String employeeName, String departmentName) {
        this.employeeId = employeeId;
        this.employeeName = employeeName;
        this.departmentName = departmentName;
    }
    public String getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(String employeeId) {
        this.employeeId = employeeId;
    }
    public String getDepartmentName() {
        return departmentName;
    }
    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }
   public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public Employee() {
        super();
    }
}
My EmployeeResponse class will contain List<Employee>  with name employeeList. 
Please note here name has to match with name in your rest response.
import java.util.List;
public class EmployeeResponse {
    List<Employee> employeeList;
    public EmployeeResponse() {
        super();
    }
    public void setEmployeeList(List<Employee> employeeList) {
        this.employeeList = employeeList;
    }
    public List<Employee> getEmployeeList() {
        return employeeList;
    }
}
















Now main part is to write method in service wrapper class which will call the service and populate the data in object of EmployeeResponse class.
I have written getEmployees method which returns me object of EmployeeResponse created above.
Please note below line which populated the String response into Object that we can use in object format

EmployeeResponse employeeResponse = new Gson().fromJson(response.toString(), EmployeeResponse.class);






























package com.service;

import com.google.gson.Gson;
import com.payload.Employee;
import com.payload.EmployeeResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class ConsumeRestServiceWrapper {
    public ConsumeRestServiceWrapper() {
        super();
    }

    public static void main(String[] args) {
        ConsumeRestServiceWrapper service = new ConsumeRestServiceWrapper();
        try {
            EmployeeResponse response = service.getEmployees();
            if (response != null) {
                if (response.getEmployeeList() != null && response.getEmployeeList().size() > 0) {
                    System.out.println("Employee  list");
                    System.out.println("*****************");
                    for (Employee e : response.getEmployeeList()) {
                        System.out.println("Employee Id-" + e.getEmployeeId());
                        System.out.println("Employee Name-" + e.getEmployeeName());
                        System.out.println("Employee Department-" + e.getDepartmentName());
                        System.out.println("*****************");
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public EmployeeResponse getEmployees() throws Exception {

        URL url = new URL(null, "http://localhost:8080/employees", new sun.net.www.protocol.http.Handler());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type", "application/json");

        int responseCode = conn.getResponseCode();
        System.out.println("URL...: " + url + "  Response Code..: " + responseCode);
        if (responseCode >= 200 && responseCode < 300) {

            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
            String line;
            StringBuffer response = new StringBuffer();
            while ((line = br.readLine()) != null) {
                response.append(line);

            }
            br.close();
            System.out.println("Rest response for employee is -" + response);

            EmployeeResponse employeeResponse = new Gson().fromJson(response.toString(), EmployeeResponse.class);


            return employeeResponse;
        } else {
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
            String line;
            StringBuffer errorResponse = new StringBuffer();

            while ((line = in.readLine()) != null) {
                errorResponse.append(line);
            }
            in.close();
            throw new RuntimeException(conn.getResponseCode() + " Invalid Response " + errorResponse);
        }

    }
}


when i run above class i get response as below















Some of rest service response just contains the list without the name as below

























In this case when you run above code ,you would get exception as com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $

so change the line in getEmployees method as below and it will directly populate in List<Employee>

List<Employee> employeeResponse = new Gson().fromJson(response.toString(), List.class);




hope this helps to know how to consume rest API using Gson jar file.

Wednesday, May 26, 2021

ADF dropdown Adjusting width with af:panelFormLayout

In ADF width of af:selectOneChoice is adjusted to fit its content and sometime we dont want that to happen specifically when we use af:panelFormLayout with multiple input components like af:inputText af:selectoneChoice.

In this example i am using below code 











My UI Looks like Below and you can see dropdown is not align with input textbox.










To align this af:selectOneChoice with af:inputText set  contentStyle="width:100%;"  of af:selectOneChoice as shown below






With this your dropdown will be aligned as below



Sunday, May 23, 2021

Call Stored procedure with Array as input parameter from java

Requirement-It is very common requirement to call stored procedure which takes array as input parameter. In below example i am calling the stored procedure from Impl class of application module.

My procedure is having String of array as second parameter.When we want to pass String of array to Stored procedure we need to convert this String of array to Sql array type.For this we need below two things 

  1. The array that we pass should be declared in data as type in database as shown in below CST_LTG_ARRAY_VARCHAR2 is declared as type in database.Same type will be used in stored procedure input parameter as shown in screenshot 2
  2. We need to convert the java.sql.Connection to oracle.jdbc.OracleConnection object as shown in code snippet
Now use this OracleConnection reference to create array reference that we need to pass to stored procedure using below line.Remember minute details here -dont forget to mention schema name dot your type name in database in all uppercase otherwise code will throw java.sql.SQLException: invalid name pattern.


       Array subSetCodesArray = oraConn.createARRAY("EL_EGWH_EXT_WORK.CST_LTG_ARRAY_VARCHAR2", subSetCodes);

Now final step is to pass this subSetCodesArray  array to callableStatement setArray method as below

 statement.setArray(2, subSetCodesArray);


Final method looks like below initializeDataSource is methd used to get connection reference from dataSource in weblogic server.

    public String callApplyClusterStoredProcedure(Long batchNumber, String[] subSetCodes) {


        DBTransactionImpl dbtrx = (DBTransactionImpl) getDBTransaction();

        CallableStatement statement =

            dbtrx.createCallableStatement(("BEGIN " + "SCHEMA_NAME.PROCEDURE_NAME(?,?,?,?);" + "END;"), 0);

        try {

            DataSource ds = initializeDataSource();

            java.sql.Connection conn = ds.getConnection();

            OracleConnection oraConn = conn.unwrap(OracleConnection.class);

            statement.setLong(1, batchNumber);

            if (subSetCodes != null) {

                Array subSetCodesArray = oraConn.createARRAY("EL_EGWH_EXT_WORK.CST_LTG_ARRAY_VARCHAR2", subSetCodes);

                statement.setArray(2, subSetCodesArray);

            } else {

                //use below code to set Null if array is empty or null

                statement.setNull(2, java.sql.Types.ARRAY,"EL_EGWH_EXT_WORK.CST_LTG_ARRAY_VARCHAR2");

            }


            statement.registerOutParameter(3, java.sql

                                                  .Types

                                                  .VARCHAR);

            statement.registerOutParameter(4, java.sql

                                                  .Types

                                                  .VARCHAR);

            statement.execute();

            //Long balanceToInclude = statement.getLong(4);

            String result = statement.getString(3);

            String message = statement.getString(4);

            System.out.println("result -" + result);

            System.out.println("message-" + message);

            return result;

        } catch (SQLException sqlerr) {

            throw new JboException(sqlerr.getMessage());

        } finally {

            try {

                if (statement != null) {

                    statement.close();

                }

            } catch (SQLException closeerr) {

                throw new JboException(closeerr.getMessage());

            }

        }

    }


    private DataSource initializeDataSource() {

        InitialContext ctxt = null;

        DataSource dataSource = null;

        try {

            ctxt = new InitialContext();

            dataSource = (DataSource) ctxt.lookup("jdbc/EgwhDS");

            ctxt.close();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return dataSource;

    }

Thursday, May 20, 2021

ADF view object with bind parameter and like operator .

 Requirement:

In this post i am explaining how to create ADF view object with like operator and bind parameter in where clause. requirement is very simple get all rows from employee table with employee containing runtime value entered by user.


In this case while we create new object in Jdeveloper give query as below

Query here is -


select EMPLOYEE_NAME,EMPLOYEE_ID from EMPLOYEE 

where  ( (UPPER(EMPLOYEE_NAME) LIKE UPPER('%' || :pEmployeeName || '%') )
















In the next screen give bind parameter pEmployeeName of type string as below














After this pass the bind parameter from UI as user entered value .Hope this helps

Saturday, March 27, 2021

Oracle Cloud Infrastructure 2020 Certified Architect/1Z0-1072-20 -EXAM questions/Dump

 HI All,

Recently i passed the exam for Oracle Cloud Infrastructure 2020 Certified Architect. Its tough exam with 60% passing percentage.

Attached are exam dump questions that i got along with answers for each. You will definitely pass the exam with only following the document questions


click link for Dump questions and answers

All the Best :)

Friday, March 12, 2021

ADF table -Achieve case insensitive sort for af:column

 In Oracle ADF when we use sortable="true" on af:column By default sorting will be done case-sensitively ,which means that upper case data will be shown first and then lower case data will shown .As shown in below screenshot






,









To make this work case insensitively , we can use sortStrength="Primary" attribute on af:column as below






Now my work works case insenstive as below.














Please note this works only with 11.1.1.7 and above version

Wednesday, March 10, 2021

Setting NULL value using af:setPropertyListener in ADF

 Usually we come across common requirement to set value of session scope or pageFlowScope variable to NULL on click of adf button or  af:commandLink to do this you can af:setPropertyListener inside af:commandLink as below and use EL as #{null}

<af:commandLink text="Clear">

            <af:setPropertyListener  from="#{null}"

                                                  to="#{sessionScope.userName}"

                                                   type="action"/>

</af:commandLink>


in above case i am setting userName to null.

Tuesday, March 9, 2021

Reset ADF table filters programmatically

Requirement-When we use ADF table i.e af:table with filters on each column ,It is very common requirement to clear filter data and reset table result to its initial state.

One way to do is to add af:column as first column in af:table and set rowHeader="true" attribute in af:column.This will show icon in first column to clear filter and reset table results.


There may be a requirement to do this on click of button which is outside af:table .So in this case add below code in button actionListener.



    public void backActionListener(ActionEvent actionEvent) {

        // Add event code here...

        FilterableQueryDescriptor fqd = (FilterableQueryDescriptor)deleteUserTableBinding.getFilterModel();

                      if (fqd != null && fqd.getFilterCriteria() != null) {

                        fqd.getFilterCriteria().clear();

                        deleteUserTableBinding.queueEvent(new QueryEvent(deleteUserTableBinding, fqd));          

                       

                     }

    }

Note: deleteUserTableBinding is my af:table component binding name.(change as per yours)

This will work as long as you are on same page on click of reset button in my case i call it back button. But if are redirecting to different jsff or jspx on click of your reset button above code will throw error saying binding not found because on the page which you are redirecting to does not have table binding iterators and tree binding .


Solution to solve this problem is go to first page's page defination file and copy tree binding and iterator binding ,now paste this in page defination file of next page which you are redirecting to so when we queue event in above code snippet it will find the required binding and wont throw exception.