Showing posts with label adf. Show all posts
Showing posts with label adf. Show all posts

Wednesday, April 8, 2020

Fasten JDeveloper IDE memory and development

1- To quick open a file , you want to change the default view editor from design to source.


2- To open Jdeveloper quickly without opening last opened tabs or welcome messages , open command prompt "cmd.exe" and go to the path of your "jdeveloper.exe" and execute:
jdeveloper.exe -nonag -noreopen
3- To increase memory, Edit the file "ide.conf" at oracle home :
E:\Oracle\Middleware_12_c\jdeveloper\ide\bin\ide.conf and add following lines to increase memory

AddVMOption -XX:MaxPermSize=1024m
AddVMOption -XX:PermSize=512M
AddVMOption -Xms2048M
AddVMOption -Xmx4096M

4- To increase memory, Edit the file "jdev.conf" at oracle home :
E:\Oracle\Middleware_12_c\jdeveloper\jdev\bin\jdev.conf

// Increase your MaxPermSize
AddVMOption -XX:MaxPermSize=1024m
AddVMOption -XX:PermSize=512M
AddVMOption -Xms1024M
AddVMOption -Xmx3072M

//Adds a memory monitor which helps in check current heap used by jdeveloper
AddVMOption -DMainWindow.MemoryMonitorOn=true

//ADD the following JVM options towards the end of file
AddVMOption -XX:+UseStringCache
AddVMOption -XX:+OptimizeStringConcat
AddVMOption -XX:+UseCompressedStrings
AddVMOption -XX:+UseCompressedOops
AddVMOption -XX:+AggressiveOpts
AddVMOption -XX:+UseConcMarkSweepGC
AddVMOption -DVFS_ENABLE=true
AddVMOption -Dsun.java2d.ddoffscreen=false
AddVMOption -XX:+UseParNewGC
AddVMOption -XX:+CMSIncrementalMode
AddVMOption -XX:+CMSIncrementalPacing
AddVMOption -XX:CMSIncrementalDutyCycleMin=0
AddVMOption -XX:CMSIncrementalDutyCycle=10

To make JDeveloper responsive after returning from minimizing and restoring :
Dsun.awt.keepWorkingSetOnMinimize=true

5- Remove build after save action, click on "Tools" menu select "Preferences" then select "Save Actions" from the tree menu then delete this action.
6- Try to install one of the free ram disk softwares which creates a virtual drive using the available main memory (RAM) in your compute then you can checkout your application in this driver to make it faster.
 EX. 
At "AMD Radeon RAMDisk" software, you can configure 4GB of your computers available RAM (up to 6GB if you have AMD Radeon™ memory installed).


Monday, April 6, 2020

Filtering ADF dynamic table with array list using Lambda Expression(Java 8 or Higher)

We may need to programmatically fill data that may comes from a service inside an array list, to view this list we can bind it to an ADF table component.

But can we filter this list in the JSF view ?

Lets' see an example:

1- We have a Java class called "Car" and defined as:
public class Car {
    int modelNo;
    String name;
    public Car(int x , String y) {
         modelNo = x;
         name = y;
     }
    public void setModelNo(int modelNo) {
        this.modelNo = modelNo;
    }
    public int getModelNo() {
        return modelNo;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
2- We have another class "Cars" contains list of cars, data generated at java class level as :
import java.util.ArrayList;
import java.util.List;
public class Cars {
    public List<Car> getCarsAsList(){
        List<Car> cars = new ArrayList();
        Car car = new Car(1,"Avalon");
        Car car2 = new Car(1,"Camry");
        Car car3 = new Car(2,"Hyndai");
        cars.add(car);
        cars.add(car2);
        cars.add(car3);
        return cars ;
    }
}
 To display previous list of cars, we will create a JSF page and assign the list to the value of the table :
<af:form id="f1">
    <af:table var="row" rowBandingInterval="0" id="t1"
              value="#{backingBeanScope.cars.carsAsList}"
              partialTriggers="::it1">
        <af:column sortable="false" headerText="CountryName" id="c1" rowHeader="true">
            <af:outputText value="#{row.modelNo}" id="ot1" partialTriggers="::it1"/>
        </af:column>
        <af:column sortable="false" headerText="Currency" id="c2">
            <af:outputText value="#{row.name}" id="ot2"  partialTriggers="::it1"/>
        </af:column>
    </af:table>
</af:form>

Now, We need to filter the table when a search input text is filled otherwise retrieve the list as it is.

1- Create a search input text ,with value  "#{pageFlowScope.modelNo}".
2- Set the search input text "autoSubmit" property  to  "true" and set the table partial trigger to that input text.
3-

a - when the search input text is empty, value of the table should be the list as it is without filtering:
value = "#{backingBeanScope.cars.carsAsList}"

b- when the search input text is filled, we will need to filter the list, ,so we will use lambda expression to filter the table when the search text field is filled as :
value = "#{backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo)}"
Combining a and b conditions we can form it as if-else expression language as:

value="#{pageFlowScope.modelNo !='' ? backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo).toList() : backingBeanScope.cars.carsAsList}"
value="#{pageFlowScope.modelNo !='' ? backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo).toList() : backingBeanScope.cars.carsAsList}"
af:form id="f1">
    <af:inputText id="it1" value="#{pageFlowScope.modelNo}" label="Search Model Number" autoSubmit="true"/>
    <af:table var="row" rowBandingInterval="0" id="t1"
              value="#{pageFlowScope.modelNo !=null and pageFlowScope.modelNo !=''? backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo).toList() : backingBeanScope.cars.carsAsList}"
              partialTriggers="::it1">
        <af:column sortable="false" headerText="Model Number" id="c1" rowHeader="true">
            <af:outputText value="#{row.modelNo}" id="ot1" partialTriggers="::it1"/>
        </af:column>
        <af:column sortable="false" headerText="Car Name" id="c2">
            <af:outputText value="#{row.name}" id="ot2"  partialTriggers="::it1"/>
        </af:column>
    </af:table>
</af:form>

To convert "Car Name" field to upper case
 <af:table var="row" rowBandingInterval="0" id="t1"

                      value="#{backingBeanScope.cars.carsAsList.stream().map((car)->[car.modelNo,car.name.toUpperCase()]).toList()}"

                      partialTriggers="::it1">

                <af:column sortable="false" headerText="CountryName" id="c1" rowHeader="true">

                    <af:outputText value="#{row[0]}" id="ot1"/>

                </af:column>

                <af:column sortable="false" headerText="Currency" id="c2">

                    <af:outputText value="#{row[1]}" id="ot2"/>

                </af:column>

            </af:table>

Saturday, October 13, 2018

How to execute lov View Accessor Query?

UseCase:
At each  Employee record, You want to display list of departments, this list of departments is changed according to a parameter changed at run-time.

You click a button and change the parameter value, the LOV must execute its query to fetch the correct data after changing the parameter.

So you have a ViewAccessor  it's query has a parameter ( :bvDeptId ) to filter data,
this parameter is changed during run-time when you click a button you change this parameter but the LOV shows old data, so how to make it's query to be executed:


Departments as list of value (LOV) at EmployeesView

DepartmentsView1 is the ViewAccessor attached to EmployeesView1 ViewObject .
ViewAccessor has a parameter ( bvDeptId ) to filter data,

Solution:
Note: When you create  LOV, you bound an attribute of a ViewObject with a ViewAccessor, This ViewAccessor is a new instance of the ViewObject ( Departments ), this instance is different than instances exists at application module container, this is new instance.

Ways to make the LOV execute it's query:

1- Get the view object which the LOV created on  (EmployeesView1) then retrieve the LOV view accessor  (DepartmentsView1)  then executes it's query:
ApplicationModuleImpl am = ADFUtils.getAppImpl("AppModule");
ViewObject vo =  am.findViewObject("EmployeesView1");
RowSet lov =(RowSet) vo.getCurrentRow().getAttribute("DepartmentsView1"); lov.executeQuery();
2-From the binding container get the LOV attribute and retrieves it's attached view object  then executes it's query:
BindingContainer bindings = getBindingContainer();
//FacesCtrlListBinding
FacesCtrlLOVBinding lov = (FacesCtrlLOVBinding) bindings.get("DepartmentId");
ViewObject departmentVO = lov.getListIterBinding().getViewObject();
departmentVO .executeQuery();
3- You can execute custom method at applicationModuleImpl as described here:
http://come2adf.blogspot.com/2013/05/create-department-while-creating.html

Thursday, November 19, 2015

ADF InputColor Component

When you need to pick a color from a popup you can deal with ADF component called af:InputColor.
Use Case
Need coloring a number values according to specific ranges.
Example: 
Numbers between 0 and 50 will be colored with black.
Implementations
Create a table that saves the desired color for each specific range.
Because the InputColor  component needs a value of type Color, create a transient attribute with type java.awt.Color , you will change the type at XML level manually:
When page loads you will need to get a color object, so convert the color string to object of type color.
When you set color object you will need to convert the chose color object to string and set the color string to be saved in the database after commit.

Drag and drop the InputColor component and set it's value to the color object attribute.

The result will looks like this:

Sunday, September 6, 2015

Validate creation of one master record with one detail record at least

Case
Any new Department must provide at least one Employee.

Implementation Method
  1. Create "Business Component from Tables" for Departments and Employees.
  2. Check the property "Composition Association" at the association.
There are many method to apply the validation of existing one Employee for each Department:
  • Using "Entity Validators" of type "Script Expression"
    Create new "Validator" on the Department of type script Expression and write:
 if(DETAIL_ACCESSOR_NAME.count('ANY_DETAIL_ATTRIBUTE_NAME') >=1)
return true;
return false;
  • Using "Entity Validators" of type"Collection":
    Cretae new entity validators on Department of type "Collection",
    Choose the :
    Operation =  "Count"
    Accessor  = Accessor Name of Employee.
    Atribute   = any attribute
    Operator  = "GreaterOrEqualTo"
    Enter Literal Value = 1
  • Create managed been class implements "BindingContainerValidator" interface and overrides "validateBindingContainer" method:
@Override
public void validateBindingContainer(BindingContainer bindingContainer) {
if(  ( (DCIteratorBinding) bindingContainer.get("DETAIL_ITERATOR_NAME")).getCurrentRow()==null){
throw new ValidatorException(new FacesMessage("Create a new Contact info before commit"));
        }
    }
       then go to page definition properties and set two properties
       CustomValidator="#{YOUR_CUSTOM_VALIDATE_MANAGED_BEAN}"
      SkipValidation="custom"

EntityState ( STATUS_NEW , STATUS_INITIALIZED )

EntityState
  1. STATUS_INITIALIZED ( -1 )This status indicates a new record that is not yet a candidate to insert into the database as no changes have yet occurred to its attributes, it's basically just empty.
  2. STATUS_NEW ( 0 )Says that at least one of the attributes of the EO has been updated ( attribute is AutoSubmit or a  button is  clicked then the validation will start) and thus the record is a candidate to be inserted to the database.
When you click "CreateInsert" button, the new record status is STATUS_INITIALIZED

When you set any attribute value, the entity's state transitions into NEW and will be added to the transaction.

When an entity row is created, modified, or removed, it is automatically enrolled in the transaction's list of pending changes.


        The entity instance is added to the entity cache once the primary key is populated.


When you call commit() on the Transaction object, it processes its pending changes list, validating new or modified entity rows that might still be invalid.

When the entity rows in the pending list are all valid, the Transaction issues a database SAVEPOINT and coordinates saving the entity rows to the database. 

If all goes successfully, it issues the final database COMMIT statement.
If anything fails, the Transaction performs a ROLLBACK TO SAVEPOINT to allow the user to fix the error and try again.


The Transaction object used by an application module represents the working set of entity rows for a single end-user transaction.By design, it is not a shared, global cache.


The database engine itself is an extremely efficient shared, global cache for multiple, simultaneous users.



Setting row with status STATUS_INITIALIZED delay validation.

https://docs.oracle.com/cd/E57014_01/adf/api-reference-model/oracle/jbo/Row.html

Thursday, May 21, 2015

Fast Call 2 Database 4 DDL, DML, function and Procedure



public String print() {

        System.out.println(Calls2DatabaseHelper.exeucteSql("procedure", "Pro_Get_Employee_Name(?,?)", new String[] { "100" },

                                                           1));

        System.out.println(Calls2DatabaseHelper.exeucteSql("function", "fn_Get_Employee_Name(?)", new String[] { "100" },

                                                           1));

        String sql ="SELECT FIRST_NAME || ' ' ||  LAST_NAME Emp_Name FROM EMPLOYEES WHERE EMPLOYEE_ID = 100";

        System.out.println(Calls2DatabaseHelper.exeucteSql("select", sql, new String []{},

                                                           0));

        sql ="SELECT FIRST_NAME || ' ' ||  LAST_NAME Emp_Name FROM EMPLOYEES WHERE EMPLOYEE_ID = ?";

        System.out.println(Calls2DatabaseHelper.exeucteSql("select", sql, new String []{"100"},

                                                           0));

        sql ="update EMPLOYEES set  LAST_NAME = ? WHERE EMPLOYEE_ID = ?";

        System.out.println(Calls2DatabaseHelper.exeucteSql("update", sql, new String []{"MAhmoud","100"},

                                                           0));
        return "";


    }



public static DBTransaction getConnection() throws SQLException {

        return ADFUtils.getAppImpl().getDBTransaction();

    }

  

    public static String exeucteSql(String operaition, String signature, String[] inValues, int numOutValues) {
        String returnValue = ""
        String begin = " begin ";
        String end = " end; ";
        String sql = "";
        System.out.println(sql);
        if (operaition == "procedure") {
            signature+=";";
              sql = begin + signature + end;
            try (CallableStatement cs = getConnection().createCallableStatement(sql, 0)) {
                for (int i = 1; i <= inValues.length; i++) {
                    cs.setString(i, inValues[i - 1]);
                }
                for (int i = inValues.length + 1; i <= numOutValues + 1; i++) {
                    cs.registerOutParameter(i, OracleTypes.VARCHAR);
                }
                cs.execute();
                returnValue = cs.getString(2);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
            else  if (operaition == "function") {
            signature+=";";
            signature="?:= "+signature;
            sql = begin + signature + end;
            System.out.println(sql);
            try (CallableStatement cs = getConnection().createCallableStatement(sql, 0)) {
                cs.registerOutParameter(1, OracleTypes.VARCHAR);
                for (int i = 2; i <= inValues.length+1; i++) {
                    cs.setString(i, inValues[i - 2]);
                }
                cs.execute();
                returnValue = cs.getString(1);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        else if(operaition== "select"){
            if(inValues.length>0){
            try( PreparedStatement cs = getConnection().createPreparedStatement(signature, 0);) {
                for (int i = 1; i <= inValues.length; i++) {
                    cs.setString(i, inValues[i - 1]);
                }
                ResultSet rs = cs.executeQuery();
                if (rs.next()) {
                 returnValue =   rs.getString("Emp_Name");
                }
            } catch (SQLException e) {
                e.printStackTrace();
             } 
        }  else{
          Statement stmt;
            try {
                stmt = getConnection().createStatement(0);
                ResultSet rs = stmt.executeQuery(signature);
                if (rs.next()) {
                 returnValue =   rs.getString("Emp_Name");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        }
            else {
                try( PreparedStatement cs = getConnection().createPreparedStatement(signature, 0);) {
                    if(inValues.length>0){
                    for (int i = 1; i <= inValues.length; i++) {
                        cs.setString(i, inValues[i - 1]);
                    }
                    }
                    int numChangedRows = cs.executeUpdate();
                    getConnection().commit();
                    System.out.println("numChangedRows="+numChangedRows);
                } catch (SQLException e) {
                    e.printStackTrace();
                 } 
            }
        return returnValue;
        }

Download Link

http://sameh-nassar.blogspot.com/2010/12/calling-sql-statment-inside-java-code.html

Tuesday, May 5, 2015

Sorting , Filtering

Filtering
  • setQuery
    public void filter(){ setQuery(getQuery()+ " where department_id=1"); executeQuery();System.out.println(getQuery());
    }
  • setWhereClause
    - If the view object (VO) has where clause then set where clause will be joined ( anded ) with the actual vo where clause.
    - setWhereClause(null) doesn't effect the actual where clause written inside VO xml but affect only the written in VO implementation class.
    public void filter(){
    System.out.println(getQuery());
    setWhereClause("department_id=1");
    System.out.println(getQuery());
    executeQuery();
    System.out.println(getQuery());
    }
    
    Example
    If actual view object contains where clause department_id= 1,then output after set where clause programmatically is:
    select ....... where ( department_Name='Administration' ) and ((( department_id= 1 )))
  • View Criteria
    - Once we have the view object with the rows populated from the database,we can sort, filter, search with the existing rows in memory without re-querying the database.This will greatly help us to minimize the database round-trip.
    ViewCriteria.CRITERIA_MODE_QUERY  // Uses database.
    ViewCriteria.CRITERIA_MODE_CACHE  // Uses rows in memory without querying the database.
    - After we change the SQL mode, new setting will take effect the next time we call the executeQuery() method.

    
    public void applyViewCriteriaAtRunTime(){
    ViewCriteria vc = createViewCriteria();
    //Try this line when commented and then remove commented to see the diffident output
    //vc.setCriteriaMode(ViewCriteria.CRITERIA_MODE_CACHE);
    ViewCriteriaRow vcr = vc.createViewCriteriaRow();
    vcr.setAttribute("ManagerId", "200");
    //ViewCriteriaItem jobItem = vcr ensureCriteriaItem("ChannelId");
    //vci.setOperator(JboCompOper.OPER_ON_OR_AFTER);
    //jobItem.setOperator("=");
    //jobItem.getValues().get(0).setValue(channelId);
    vcr.setAttribute("FirstName","LIKE 'R%'");
    vc.addRow(vcr);// same as vc.add(vcr);
    System.out.println(getQuery());
    applyViewCriteria(vc);
    System.out.println(getQuery());
    executeQuery();
    System.out.println(getQuery());
    }
    
Test Case
Put two instances and apply view criteria for one of them by pressing edit, we see that:

The applied view criteria effects only the view that we applied the view criteria on it.
  • When you choose Database:
    New row created in first instance  will be added also to second  rowset due to the "association consistency".
    New row created in 2nd instance  will  Not be added also to second  rowset. 
  • When you choose In Memory:
New row created in first instance  will be added also to second  rowset due to the "association consistency"( better naming for this "new row consistency" )
New row created in 2nd instance  will  be  added  to the 1st if it matches the criteria.
Maintaining New Row Consistency in View Objects Based on the Same Entity
When multiple instances of entity-based view objects in an application module are based on the same underlying entity object, a new row created in one of them can be automatically added (without having to re-query) to the row sets of the others to keep your user interface consistent or simply to consistently reflect new rows in different application pages for a pending transaction.
In-memory filtering with RowMatch
Don't use RowMatch if you have the option to filter the values at database level.
In-memory filtering is much slower than filtering done at the database layer.
Sorting
  • setSortBy
Used when you want to sort transient attributes because it is done in memory, If you have table built using a transient ViewObject , a click on the sort icon for a column would call ViewObjectImpl::setSortBy(String sortBy) to perform in memory sorting.

 public void sortInMemory(){ 
        setQueryMode(ViewObject.QUERY_MODE_SCAN_VIEW_ROWS);
        setSortBy("ViewObjectAttributeName");   // setOrderByClause("Table_Column_Name")
        executeQuery();
        System.out.println(getQuery());
        System.out.println(getWhereClause());
}
http://bpetlur.blogspot.com/2013/11/adf-view-criteria-execution-modes.html

Friday, March 27, 2015

Copy and paste selected rows

Select number of rows in a view as a source (v1) then insert them into other view as target (v2) :
  • At source view xml (v1):
     Create transient attribute "MarkedForInsert", set type to boolean.
  • At application module Impl:
    You need to keep your current iterator not affected, so you need to make a secondary rowSet
Create a secondary row set to not impact the row set
   RowSet selecetdRowSet= vo1.createRowSet("selecetdRowSet");
Set rowset to first row to avoid "attempt to access dead row" exception
  selecetdRowSet.first();
Get all rows that have the transient attribute "MarkedForInsert" set to true
  Row[] selectedRows =
  selecetdRowSet.getFilteredRows("MarkedForInsert", true);
Close the rowSet and clear the selection back to false for further selection next time.
  selectedRowSet.closeRowSet();
  vo1.first().setAttribute("selected", false);
  while(vo1.hasNext()){
  vo1.next().setAttribute("selected", false);
Now you can insert the rows into v2
for(Row row : rows){
Row newRow = vo2.createRow();
vo2.insertRowAtRangeIndex(vo1.getRowCount,row);
The all code :
 public Row [] getSelectedRows(){
       ViewObject vo1 =   getFirstViewObject();
        Row [] selectedRows = null;
       if(vo1.getRowCount()>0){
       RowSet selectedRowSet = vo1.createRowSet("selectedRowSet");
       selectedRowSet.first();
       selectedRows = selectedRowSet.getFilteredRows("selected", true);
        selectedRowSet.closeRowSet();
        vo1.first().setAttribute("selected", false);
        while(vo1.hasNext()){
            vo1.next().setAttribute("selected", false);
        }
       }
       return selectedRows;
    }
    public void insertSelectedRows(){
        ViewObject vo2 = getSecondViewObject();
        Row [] rows = getSelectedRows();
        if(rows!=null){
        for(Row row : rows){
            Row newRow = vo2.createRow();
            vo2.insertRowAtRangeIndex(vo.getRowCount() , newRow);
        }
        }
    }

Thursday, March 26, 2015

Sonar tip for code quality

Collection.isEmpty() should be used to test for emptiness

Using Collection.size() to test for emptiness works, but using Collection.isEmpty() makes the code more readable.
The following code:
if (myCollection.size() == 0) {  // Non-Compliant
  /* ... */
}
should be refactored into:
if (myCollection.isEmpty()) {    // Compliant
  /* ... */
}

Sunday, November 9, 2014

Deploy image as resource for other applications

Sometimes you have classes,images or any other files that is used in most of your applications(apps.),
copied and pasted in each new application.
Solution for this is to deploy these files to be used between apps as a shared resource.
This is an example of how to deploy folder of images and use it in other apps.:

1- Locate the META-INF folder YOUR_PROJECT_NAME/.adf/META-INF
and put the images folder there. 

2- Create new ADF Library Jar File.



3- Enter name for the  Deployment Profile.



4- Now we need to get a jar file then deploy it to the server, so choose deploy for your Deployment profile.

5- A new jar has been created and ready to be deployed,
Take the path for that jar.


6- Run the integrated server of jdeveloper, At deployments make new and write the path of the jar to deploy it.


Now you can use this jar files in other applications, but you need first to add a reference for your shared jar at web.xml file.



7- As a test I created a page and added image inside, in the source property write the path:
adf/image/YOUR_IMAGE_NAME

Run the application, the image will appear as following:


Thursday, September 5, 2013

Pass parameters to a database view

Sometimes you will find that it's better to write a database view instead of a select statement.
Why? For ease of maintenance and reusability.
After develop you application and a requirement came from customer to make a requirement change.
This modification may leads to modify a select statement at all views that use this select.
It will be difficult to go to each view and make the change to the select statement requirement change,
and if the requirement change came after deploy the application you will need to redeploy the application which wast a lot of time.
So it's better to write your queries inside the database as function or procedure or as a database view.
A view may needs to have a parameter such as:

 CREATE OR REPLACE FORCE VIEW EMPLOYEESVIEW  
 AS  
  SELECT ID,NAME FROM EMP WHERE SALARY > 20000;  

20000 can be a variable that needs to be passed to the view.

Views doesn't accept parameters so as a workaround we will use the database session to store that variable. The database view sql  will be:

 CREATE OR REPLACE FORCE VIEW EMPLOYEESVIEW  
 AS  
  SELECT ID,NAME FROM EMP WHERE SALARY > SYS_CONTEXT ('Emp_CTX', 'Salary_Session');  

We need to create a context with name 'Emp_CTX' to set the Salary value,
So I created a procedure called from a package:

 CREATE OR REPLACE  
 PACKAGE Emp_Session_CTX_PKG  
 IS  
  PROCEDURE SET_CONTEXT(  
    IN_NAME VARCHAR2,  
    IN_VALUE VARCHAR2);  
 END Emp_Session_CTX_PKG;  
 create or replace   
 PACKAGE BODY Emp_Session_CTX_PKG  
 IS  
  GC$SESSION_ID VARCHAR2 (100);  
 PROCEDURE SET_CONTEXT(  
   IN_NAME VARCHAR2,  
   IN_VALUE VARCHAR2)  
 AS  
 BEGIN  
  SELECT SYS_CONTEXT('USERENV', 'SESSIONID') INTO GC$SESSION_ID FROM dual;  
   DBMS_SESSION.SET_IDENTIFIER (GC$SESSION_ID);  
  DBMS_SESSION.SET_CONTEXT ('Emp_CTX', IN_NAME, IN_VALUE, USER, GC$SESSION_ID);  
 END;  

Next, call the procedure to set the Salary_Session value :

 Emp_Session_CTX_PKG.set_context('Salary_Session', '20000') ;  
Know you can make a select on the view after setting the parameter ( Salary_Session) :
 SELECT * FROM EMPLOYEESVIEW;  

Sunday, May 26, 2013

Add new department into lookup during adding an employee

While adding a new employee you can select a department for that employee from a List Of Value ( LOV ).
The case is that, the LOV displays all existed departments, But you may want to add a new department not existed in the list for the employee.
a: At the model layer :
1- Create DepartmentsView , EmployeesView then add them at application module.
2- Go to DepartmentsView and write a default expression for the DepartmentId primary key to get a positive number directly when creating a new Department:

The written expression is:
 (new oracle.jbo.server.SequenceImpl("DEPARTMENTS_SEQ",adf.object.getDBTransaction())).getSequenceNumber()  
3- Go to EmployeesView creating a new View Accessor to DepartmentView at EMPLOYEE table.








4- Go to application module to create a method and add it to the client interface by
                                                 Create the Java Class AppModuleImpl:

then write a method that define a single formal parameter           
                                             
      The written code is :
   public void RefreshAndSelect(Number Id){  
     if(Id!=null){  
       EmployeesViewImpl employeesViewImpl= getEmployees1();  
       EmployeesViewRowImpl employeesViewRowImpl = (EmployeesViewRowImpl)employeesViewImpl.getCurrentRow();  
       RowSet rowSetDep= employeesViewRowImpl.getDepartmentsView1();  
       employeesViewRowImpl.getDepartmentsView1().executeQuery();        
       employeesViewRowImpl.setDepartmentId(Id);  
     }  

  Add the created method  RefreshAndSelect  to the application module Client Interface


b: At the ViewController Layer 
We will need to make two Task Flows:
1 - ManageEmployees-Task
2 - Department-Task.
  • We will need two task flows to have the ability to commit each task separately,
Which means that if we created a new employee (Inside ManageEmployees-Task ) then created a new Department inside ( Department-Task ) and click a save button at Department-Task, it will save only the department not the employee and vice versa.

1- First Task Flow (ManageEmployees-Task) :

This task contains a default activity Fragment Page called  EmployeesFrag , this fragment page shows all employees as a table and has a button AddEmp  to add a new Employee.
AddEmp  button has ( CreateInsert ) as ( ActionListener ) and ( addEmp ) as ( Action ) to navigate to the ( EmployeesFormFrag ).


The  ( EmloyeesFormFrag ) contains a form represent employee:  
EmloyeesFormFrag has a button ( AddDept ) that only has Action  ( addDept ) to  navigate to the Department-Task

The Department-Task has a default activity CreateInsert to  create a new record then goes to DepartmentFrag 

DepartmentFrag  contains a form and two buttons that have SetActionListener to set a sesionScope parameter,

OK button set the Id of the new created Department  to a sessionScope parameter (DeptId)

 Cancel button set  the DeptId to null 


Pressing OK will goes to taskFlowReturn1 to Commit the transaction . .

 Pressing Cancel will goes to taskFlowReturn2 to Rollback the transaction.

What makes taskFlowReturn1 commit only the department is the selection of " Always Begin New Transaction " and unchecking of " Share data controls with calling task flow ":



The method RefreshAndSelect will be called if the Ok button is pressed because it sets the the sessionScope parameter to non null value:


The RefreshAndSelect method will be executed with parameter equal to the sessionScope Parameter:


Notes:
  1.  At application module don't make a relation between DepartmentView and EmployeesView.            If you related the EmployeesView with DepartmentsView,  the Employees Page which contain employees table will show the employees of the first department only.
  2. If you used pageflowScope instead of sessionScope the return value would be null.
Download the sample application from here


java - fill distinct objects in ArrayList

If you have a list that contains some objects that it is considered as duplication when two or three fields of these objects are equal. How ...