Wednesday Jul 31, 2013

EJB DC - Using JPQL constructor expressions

In JPA 2.0, a new feature is provided - "Constructor Expressions in the SELECT Clause". This feature is mainly useful for queries with multiple Select expressions, where custom result objects is necessary. This feature works with Oracle JDeveloper 12.1.2.0.0

Implementation Steps

Create Fusion Web Application with entities based on Departments and Employees, then create a session bean.

Create a Java class "DeptAndEmp" and add the below code.

public class DeptAndEmp implements Serializable {
    private String departmentName;
    private String email;
    private String firstName;
    private String lastName;
    public DeptAndEmp() {
        super();
    }

    public DeptAndEmp(String departmentName, String email, 
		String firstName, String lastName) {
        this.setDepartmentName(departmentName);
        this.setEmail(email);
        this.setFirstName(firstName);
        this.setLastName(lastName);
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
	 this.lastName = lastName;
    }
    public String getLastName() {
        return lastName;
    }
}

Open the session bean and paste the below method code and expose the method filterDeptEmpResult() method in local/remote interface.

public List<DeptAndEmp> filterDeptEmpResult() { String qlString = "SELECT NEW model.util.DeptAndEmp(dept.departmentName, emp.email, emp.firstName, emp.lastName) FROM Employees emp, Departments dept where emp.departments.departmentId = dept.departmentId"; TypedQuery<DeptAndEmp> query = em.createQuery(qlString, DeptAndEmp.class); return query.getResultList(); }

Note:- In the Query "model is a package name and TypedQuery is a JPA query that returns a specific type of Object. TypedQuery eliminates the need to cast the query result to a specific type or having to add a SuppressWarnings annotation to eliminate compiler warnings about unchecked conversions. TypedQuery is well explained in Java Persistence Architecture 2.0 - Using The New TypedQuery Interface

Create a Sample Java Client and add the below code in main method.

SessionEJB sessionEJB = (SessionEJB) context.lookup("JPAConstructorApp-Model-SessionEJB#model.SessionEJB");

for (DeptAndEmp deptAndEmp : (List<DeptAndEmp>) sessionEJB.filterDeptEmpResult()) { System.out.println("departmentName = " + deptAndEmp.getDepartmentName()); System.out.println("email = " + deptAndEmp.getEmail()); System.out.println("firstName = " + deptAndEmp.getFirstName()); System.out.println("lastName = " + deptAndEmp.getLastName()); System.out.println("======================================="); }

Deploy the sessionFacade and run the java client. In the console employees details will be displayed as below.

Add-Edit multiple rows using EJB DC

Let us take a scenario where in users wants to add/edit multiple records in the ADF table,  earlier with stateless session bean we need have work around to achieve this scenario.

This scenario can be achieved using stateful session bean, the application-managed transaction model for EJB/POJO data controls which additionally maintains a cache of managed entities and using commit operations user will be able to add/edit multiple records.

Implementation Steps

Create Java EE Web Application with entity based on Dept(sequences enabled on deptId), then create a stateful session bean with Transaction Type as "CMT with Explicit Commit" and data control for the session bean.  "CMT with Explicit Commit" supported in Oracle JDeveloper 12.1.2.0.0

In View controller project, create jspx page. Drop deptFindAll->Table/List View as ADF Table with  multi-selection option enabled.



Run the jspx page (i.e the web page look something like the image shown below). Notice here the commit button will be disabled. Once user click on the create button, commit button will get enabled.



Here we will create two records, so clicking the create button twice. Enter the dept details and click on commit button to save the records. You can also configure @SequenceGenerator/@TableGenerator to auto generate the DeptNo.


Result page should contains newly added records.

Thursday May 03, 2012

Construct ADF Master Detail Tree using EJB Datacontrol Objects programatically

This article describes the creation of master detail Tree using EJB Datacontrol Objects.

Use Case Description

Construct ADF Tree using Employees & Departments objects.It is straight forward to build a tree when foreign key relationship exists between the objects. For cases where no foreign key relationships exist, we can use this technique to programatically construct the tree in the view layer.

Implementation steps

Let us suppose that we have created Java EE Web Application with Entities from Employees & Departments table .Also add 'ADF Faces Components 11' under ViewController->project properties-> JSP Tag Libraries.

Then we will create Stateless Session Bean and and generate data control for the Stateless Session Bean.

Create Tree.jspx page .Goto its page definition overview editor & create table Binding for departmentsFindAll

Similarly create table binding for employeesFindAll.

Now we will create 2 Beans:

TreeItem.java
  - Defines Tree structure
DisplayTree.java
 Managed bean - Programatically construct tree node items

Copy this code in Tree.jspx source page:

<af:tree var="node" value="#{DisplayTree.model}">
   <f:facet name="nodeStamp">
    <af:outputText id="l1" value="#{node.text}"/>
    </f:facet>
</af:tree>

Run the page & it displays Departments->Employees Tree .


Wednesday Apr 25, 2012

EJB DataControl - programmatically construct Master-Detail hierarchy

Sometimes, in EJB data control it is necessary to construct Master-Detail relationships across different levels pro-grammatically. One of the most common use cases is construct the master-detail relation based on database tables where tables doesn't have foreign key relationship. So in this article, I'm trying to construct master-detail hierarchy pro-grammatically by taking simple custom_dept, custom_emp tables.

You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]

Note:- In Bean Data Control, Master-Detail hierarchy can be constructed as a same way but  java bean classes to be created first and then pro-grammatically populate the data in session facade.

Model Diagram:

BMD-Model.png


Note:- Here entities doesn't have any foreign key relationship. DB script for creating the tables and inserting the data required for this application is in application/etc folder.

Implementation Steps

Create Java EE Web Application with entities based on custom_dept and custom_emp tables, then create a session bean and data control for the session bean. Open cusotm_dept entity and create a transient variable called "empCollection" and add the below code.

@Transient
private Collection<CustomEmp> empCollection = new ArrayList();

public void setEmpCollection(Collection<CustomEmp> empCollection) {
	this.empCollection = empCollection;
}

public Collection<CustomEmp> getEmpCollection() {
	return empCollection;
}
Open session facade, add the below code to the session facade and expose the masterDetailFindAll() method in local/remote interface and generate a data control for that.

Note:- Here in the below code "em" is a EntityManager.
public List<CustomDept> masterDetailFindAll() {
String deptQueryString = "select * from custom_dept";
System.out.println(deptQueryString);
Query deptSearchQuery = em.createNativeQuery(deptQueryString, "deptQuery");
List deptResultList = deptSearchQuery.getResultList();
Iterator deptListIterator = deptResultList.iterator();
List<CustomDept> deptList = new ArrayList();
while (deptListIterator.hasNext()) {
	Object deptCol[] = (Object[])deptListIterator.next();
	CustomDept dept = new CustomDept();
	BigDecimal departmentId = (BigDecimal)deptCol[0];
	dept.setDepartmentId(departmentId);
	dept.setDepartmentName((String)deptCol[1]);
	dept.setLocationId((BigDecimal)deptCol[2]);
	String empQueryString =
		"select * from custom_emp emp, custom_dept dept where emp.department_id = dept.department_id and dept.department_id = " +
		departmentId;
	Query empSearchQuery = em.createNativeQuery(empQueryString, "empQuery");
	List empResultList = empSearchQuery.getResultList();
	Iterator empListIterator = empResultList.iterator();
	List<CustomEmp> empList = new ArrayList();
	while (empListIterator.hasNext()) {
		Object empCol[] = (Object[])empListIterator.next();
		CustomEmp emp = new CustomEmp();
		emp.setEmployeeId((BigDecimal)empCol[0]);
		emp.setFirstName((String)empCol[1]);
		emp.setLastName((String)empCol[2]);
		emp.setEmail((String)empCol[3]);
		emp.setJobId((String)empCol[4]);
		emp.setDepartmentId((BigDecimal)empCol[5]);
		empList.add(emp);
	}
	dept.setEmpCollection(empList);
	deptList.add(dept);
 }
  return deptList;
}

In the ViewController create index.jspx page, from data control palette drag and drop masterDetailFindAll()->CustomDept->empCollection->Master-Detail as ADF Master Form, Detail Table.

Run the index.jspx page, now we can traverse through Master-Detail records.

BMD-result.png

Thursday Apr 19, 2012

Display Lookup values from related ejb entities using JOIN FETCH

JOIN FETCH - The purpose of JOIN FETCH is to fetch the related objects from the database in a single query. So in this article, I'm trying to explain how can we use jpql JOIN FETCH and expose those attributes to EJB data control layer.

Take a scenario, where we need to build ADF tree based on departments,employees and location tables. While displaying the tree, root node should display departmentName along with city attribute which is stored in related object Location table.

Model Diagram:

EJBJFA-Model.png


In BC4J, this scenario can be implemented using Entity Objects facility provided in View Object layer. These entity objects are used by the view object for accessing the related objects attributes and will be exposed in data control layer automatically.

Same behavior can be implemented in EJB using JOIN FETCH. Using this query improves the efficiency of iteration over the result Departments objects because it eliminates the need for retrieving the associated Location objects separately.So in single query related objects attributes is also fetched from the database.

You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]

Implementation Steps

Create Java EE Web Application with entities based on Departments, Employees and Location table, then create a session bean and data control for the session bean.

Open the departments entity and alter the named query as below.

@NamedQuery(name = "Departments.findAll",
                             query = "select o from Departments o join fetch o.locations")

Note:- The query above returns Departments instances and guarantees that the locations attributes will already be fetched in the returned instances.

Now we need to expose the location attribute values to data control, create a Transient variable called "city" and add the below code in department entity.

@Transient
 private String city;
	
public String getCity() {
  return this.locations.getCity();
}

Note: Can create sample java client to check whether the city attribute value is coming in departments instance before proceeding to data control.

In the ViewController create index.jspx page, from data control palette drop departmentsFindAll->Tree as ADF Tree and in edit tree bindings select the attributes as shown in below image.

EJBJFA-DeptBinding.png


Run the index.jspx page. Now notice root node will display departmentName along with city attribute value also.

EJBJFA-output.png

Thursday Apr 05, 2012

EJB Named Criteria - Apply bind variable in Backingbean

EJB Named criteria are predefined and reusable where-clause definitions that are dynamically applied to a ViewObject query. Here we often use to filter the ViewObject SQL statement query based on Where Clause conditions.

Take a scenario where we need to filter the SQL statements query based on Where Clause conditions, instead of playing with SQL statements use the EJB Named Criteria which is supported by default in ADF and set the Bind Variable parameter at run time.

You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]

Implementation Steps

Create Java EE Web Application with entity based on Employees table, then create a session bean and data control for the session bean.

Open the DataControls.dcx file and create sparse xml for as shown below.

ncbva-dcx.png


In sparse xml navigate to Named criteria tab -> Bind Variable section, create binding variable deptId.

ncbva-bindvariable.png


Now create a named criteria and map the query attributes to the bind variable.

ncbva-namedcriteria.png


In the ViewController create index.jspx page, from data control palette drop employeesFindAll->Named Criteria->EmployeesCriteria->Table as ADF Read-Only Filtered Table and create the backingBean as "IndexBean".

Open the index.jspx page and remove the "filterModel" binding from the table, add <af:inputText />, command button and bind them to backingBean. For command button create the actionListener as "applyEmpCriteria" and add below code to the file.

public void applyEmpCriteria(ActionEvent actionEvent) {
   DCIteratorBinding dc = (DCIteratorBinding)evaluteEL("#{bindings.employeesFindAllIterator}");
   ViewObject vo = dc.getViewObject();
   vo.applyViewCriteria(vo.getViewCriteriaManager().getViewCriteria("EmployeesCriteria"));
   vo.ensureVariableManager().setVariableValue("deptId", this.getDeptId().getValue());
   vo.executeQuery();
}

/**
 * Programmtic evaluation of EL
 *
 * @param el EL to evalaute
 * @return Result of the evalutaion
 */
public Object evaluteEL(String el) {
	FacesContext fctx = FacesContext.getCurrentInstance();
	ELContext elContext = fctx.getELContext();
	Application app = fctx.getApplication();
	ExpressionFactory expFactory = app.getExpressionFactory();
	ValueExpression valExp = expFactory.createValueExpression(elContext, el, Object.class);
	return valExp.getValue(elContext);
}
Run the index.jspx page, enter departmentId value as 90 and click in ApplyEmpCriteria button. Now the bind variable for the Named criteria will be applied at runtime in the backing bean and it will re-execute ViewObject query to filter based on where clause condition.

ncbva-filteredresult.png

Monday Mar 26, 2012

Implement Tree/Details With Taskflow Regions Using EJB

This article describes on Display Tree/Details using taskflow regions.

Use Case Description

Let us take scenario where we need to display Tree/Details, left region contains category hierarchy with items listed in a tree structure (ex:- Region-Countries-Locations-Departments in tree format) and right region contains the Employees list.

In detail, Here User may drills down through categories using a tree until Employees are listed. Clicking the tree node name displays Employee list in the adjacent pane related to particular tree node.

Implementation Steps

The script for creating the tables and inserting the data required for this application

CreateSchema.sql


Lets create a Java EE Web Application with Entities based on Regions, Countries, Locations, Departments and Employees table. Create a Stateless Session Bean and data control for the Stateless Session Bean. Add the below code to the session bean and expose the method in local/remote interface and generate a data control for that.

Note:- Here in the below code "em" is a EntityManager.

public List<Employees> empFilteredByTreeNode(String treeNodeType, String paramValue) {
        String queryString = null;
        try {
            if (treeNodeType == "null") {
                queryString = "select * from Employees emp ORDER BY emp.employee_id ASC";
            } else if (Pattern.matches("[a-zA-Z]+[_]+[a-zA-Z]+[_]+[[0-9]+]+", treeNodeType)) {
                queryString = "select * from employees emp INNER JOIN departments dept\n" +
                        "ON emp.department_id = dept.department_id JOIN locations loc\n" +
                        "ON dept.location_id = loc.location_id JOIN countries cont\n" +
                        "ON loc.country_id = cont.country_id JOIN regions reg\n" +
                        "ON cont.region_id = reg.region_id and reg.region_name = '" + paramValue +
                        "' ORDER BY emp.employee_id ASC";
            } else if (treeNodeType.contains("regionsFindAll_bc_countriesList_1")) {
                queryString = "select * from employees emp INNER JOIN departments dept \n" +
                        "ON emp.department_id = dept.department_id JOIN locations loc \n" +
                        "ON dept.location_id = loc.location_id JOIN countries cont \n" +
                        "ON loc.country_id = cont.country_id and cont.country_name = '" + paramValue +
                        "' ORDER BY emp.employee_id ASC";
            } else if (treeNodeType.contains("regionsFindAll_bc_locationsList_1")) {
                queryString =
                        "select * from employees emp INNER JOIN departments dept ON emp.department_id = dept.department_id JOIN locations loc ON dept.location_id = loc.location_id and loc.city = '" +
                        paramValue + "' ORDER BY emp.employee_id ASC";

            } else if (treeNodeType.trim().contains("regionsFindAll_bc_departmentsList_1")) {
                queryString =
                        "select * from Employees emp INNER JOIN Departments dept ON emp.DEPARTMENT_ID = dept.DEPARTMENT_ID and dept.DEPARTMENT_NAME = '" +
                        paramValue + "'";
            }
        } catch (NullPointerException e) {
            System.out.println(e.getMessage());
        }   
        return em.createNativeQuery(queryString, Employees.class).getResultList();
    }

In the ViewController project, create two ADF taskflow with page Fragments and name them as FirstTaskflow and SecondTaskflow respectively. Open FirstTaskflow,from component palette drop view(Page Fragment) name it as TreeList.jsff. Open SeconfTaskflow, from component palette drop view(Page Fragment) name it as EmpList.jsff and create two paramters in its overview parameters tab as shown in below image.
TaskflowParameters.png

Open TreeList.jsff , from data control palette drop regionsFindAll->Tree as ADF Tree. In Edit Tree Binding dialog, for Tree Level Rules select the display attributes as follows:-
model.Regions - regionName
model.Countries - countryName
model.Locations - city
model.Departments - departmentName

EditTreeBinding.png


In structure panel, click on af:Tree - t1 and select selectionListener with edit property. Create a "TreeBean" managed bean with scope as "session" as shown in below Image.

TreeBean.png


Create new method as getTreeNodeSelectedValue and click ok.

getTreeNodeSelectedValue.png


Open TreeBean managed bean and add the below code:

private String treeNodeType;
private String paramValue;

public void getTreeNodeSelectedValue(SelectionEvent selectionEvent) {
        RichTree tree = (RichTree)selectionEvent.getSource();
        RowKeySet addedSet = selectionEvent.getAddedSet();
        Iterator i = addedSet.iterator();
        TreeModel model = (TreeModel)tree.getValue();
        model.setRowKey(i.next());
        JUCtrlHierNodeBinding node = (JUCtrlHierNodeBinding)tree.getRowData();
        //oracle.jbo.Row
        Row rw = node.getRow();
        Object selectedTreeNode = node.getAttribute(0);

        Object treeListType = node.getBindings();
        String treeNodeType = treeListType.toString();

        this.setParamValue(selectedTreeNode.toString());
        this.setTreeNodeType(treeNodeType);
    }

    public void setTreeNodeType(String treeNodeType) {
        this.treeNodeType = treeNodeType;
    }

    public String getTreeNodeType() {
        return treeNodeType;
    }

    public void setParamValue(String paramValue) {
        this.paramValue = paramValue;
    }

    public String getParamValue() {
        return paramValue;
    }<br />
Open EmpList.jsff , from data control palette drop empFilteredByTreeNode->Employees->Table as ADF Read-only Table. After selecting the  Employees result set, in Edit Action Binding dialog window pass the pageFlowScope parameters as shown in below Image.

EmpEditActionBinding.png


In empList.jsff page, click Binding tab and click on Create Executable binding and select Invoke action and follow as shown in below image.

executeEmpFiltered.png



Edit executeEmpFiltered invoke action properties and set the Refresh to ifNeeded, So when ever the page needs the method will be executed.

executeEmpFilteredInvoke.png


Create Main.jspx page with page template as Oracle Three Column Layout. Drop FirstTaskflow as Region in start facet and drop SecondTaskflow as Region in center facet, Edit task Flow Binding dialog window pass the Input Paramters as shown in below Image.

EditTaskFlowBinding.png


Run the Main.jspx, tree will be displayed in left region and emp details will displyaed on the right region. Click on the Americas in tree node, all emp related to the Americas related will be displayed.

ResultNew.png


Click on Americas->United States of America->South San Francisco->Accounting, only employee belongs to the Accounting department will be displayed.

SelectedResult.png

Tuesday Mar 20, 2012

Achieve Named Criteria with multiple tables in EJB Data control

In EJB create a named criteria using sparse xml and in named criteria wizard, only attributes related to the that particular entities will be displayed.  So here we can filter results only on particular entity bean.

Take a scenario where we need to create Named Criteria based on multiple tables using EJB. In BC4J we can achieve this by creating view object based on multiple tables. So in this article, we will try to achieve named criteria based on multiple tables using EJB.

Implementation Steps

Create Java EE Web Application with entity based on Departments and Employees, then create a session bean and data control for the session bean.

Create a Java Bean, name as CustomBean and add below code to the file. Here in java bean from both Departments and Employees tables three fields are taken.

public class CustomBean {
    private BigDecimal departmentId;
    private String departmentName;
    private BigDecimal locationId;
    private BigDecimal employeeId;
    private String firstName;
    private String lastName;

    public CustomBean() {
      super();
    }

    public void setDepartmentId(BigDecimal departmentId) {
        this.departmentId = departmentId;
    }

    public BigDecimal getDepartmentId() {
        return departmentId;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setLocationId(BigDecimal locationId) {
        this.locationId = locationId;
    }

    public BigDecimal getLocationId() {
        return locationId;
    }

    public void setEmployeeId(BigDecimal employeeId) {
        this.employeeId = employeeId;
    }

    public BigDecimal getEmployeeId() {
        return employeeId;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }
}


Open the sessionEJb file and add the below code to the session bean and expose the method in local/remote interface and generate a data control for that.

Note:- Here in the below code "em" is a EntityManager.

public List<CustomBean> getCustomBeanFindAll() {
     String queryString =
            "select d.department_id, d.department_name, d.location_id, e.employee_id, e.first_name, e.last_name from departments d, employees e\n" +
            "where e.department_id = d.department_id";
     Query genericSearchQuery = em.createNativeQuery(queryString, "CustomQuery");
     List resultList = genericSearchQuery.getResultList();
     Iterator resultListIterator = resultList.iterator();
     List<CustomBean> customList = new ArrayList();
     while (resultListIterator.hasNext()) {
         Object col[] = (Object[])resultListIterator.next();
         CustomBean custom = new CustomBean();
         custom.setDepartmentId((BigDecimal)col[0]);
         custom.setDepartmentName((String)col[1]);
         custom.setLocationId((BigDecimal)col[2]);
         custom.setEmployeeId((BigDecimal)col[3]);
         custom.setFirstName((String)col[4]);
         custom.setLastName((String)col[5]);
         customList.add(custom);
     }
     return customList;
}

Open the DataControls.dcx file and create sparse xml for customBean. In sparse xml navigate to Named criteria tab -> Bind Variable section, create two binding variables deptId,fName.

BindVariables.png


In sparse xml navigate to Named criteria tab ->Named criteria, create a named criteria and map the query attributes to the bind variables.

CustomBeanCriteria.png


In the ViewController create a file jspx page, from data control palette drop customBeanFindAll->Named Criteria->CustomBeanCriteria->Query as ADF Query Panel with Table. Run the jspx page and enter values in search form with departmentId as 50 and firstName as "M". Named criteria will filter the query of a data source and display the result like below.

NamedCriteriaResult.png

Friday Sep 16, 2011

Contextual events with EJB DC

This article describes contextual events with EJB Datacontrol

Use Case Description

Let us consider a scenario wherein the user wants to display deptno list & commandButton in region1 & region2 displays the Emp records corresponding to selected deptno in region1.We will try to achieve this using contextual events.

When the user selects deptno & clicks on the commandButton ,a contextual event with payLoad parameter is broadcasted by taskflow1.This event is then consumed by the  taskflow2 and the handleEvent() handler passes payLoad parameter(i.e deptno) to sessionBean.SessionBean has findByDeptno() method that returns the Emp records & taskflow2 displays the respective Emp records .

Implementation steps

Let us suppose that we have created Java EE Web Application with Entities from Emp & Dept table
.Also add 'ADF Faces Components 11' under ViewController->project properties-> JSP Tag Libraries.

Edit Emp.java & create a custom named query that returns Emp Object for the respective deptno :


 @NamedQuery(name = "findEmpByDeptno", query = "select o from Emp o
 where o.dept.deptno = :deptNo")
Let us create Stateful Session Bean and expose the Named Query through the Session Facade.Create a contextual handle event that passes deptno as payload parameter:   

 public void handleEvent(Object payload) 
    {
           this.setDepartNo((BigDecimal)payload);
    }
Modify findEmpByDeptno namedQuery as below:

 public List<Emp> findEmpByDeptno() 
{
 
 return em.createNamedQuery("findEmpByDeptno").setParameter
 ("deptNo",  this.getDepartNo()).getResultList();
}

Generate Data control for the above Session Bean & expose the above method through the Session Facade.

Create a ADF taskflow1 with page Fragments & drop  view activity(DeptView) on that.In the same taskflow drop Execute operation((findByDeptno()->Emp->Operations->Execute).Define control flow case 'execute' from DeptView to Execute operation in taskflow.

Drop deptno as selectOneChoice & commandButton 'showEmpRecords' on the DeptView page Fragment page.Set showEmpRecords action property  as 'execute'

In its page definition create deptno attribute value that points to deptFindAllIterator &  handler event method action binding to handle the event:

handleEvtAction.JPG
              
Select commandButton 'showEmpRecords' & create new contextual event on that:


contextEvent.JPG

Now we will create new Event subscriber in its contextual events binding editor tab:

subscribeEvt.JPG

Create taskflow2 that displays Emp table(findByDeptno()->Emp) & create main.jspx page,drop both the taskflows as region

Run the page & now if user selects deptno,table below shows Emp records corresponding to the selected deptno.


Thursday Sep 15, 2011

AutoSuggest behavior In ADF Using EJB

AutoSuggest feature somewhat expected feature, nowadays that most of the top sites have implemented this functionality. This feature makes your site as user friendly and easy to navigate in inputText feature.

AutoSuggest behavior in ADF adds a pull-down menu of suggested values to a text field. The user can either click directly on a suggestion to enter it into the field, or navigate the list using the up and down arrow keys, selecting a value using the enter key.

Lets create a Java EE Web Application with Entities based on Departments, edit the Departments.java entity and add the below code.

@NamedQuery(name = "Departments.filteredValues",
            query = "select o from Departments o where o.departmentName like CONCAT(:deptName,'%')

Create a Stateless Session Bean and data control for the Stateless Session Bean. Add the below code to the session bean and expose the method in local/remote interface and generate a data control for that.

Note:- Here in the below code "em" is a EntityManager.

/** select o from Departments o where o.departmentName like CONCAT(:deptName,'%') */
public List<String> getDepartmentsFilteredValues(String deptName) {
   //To store the resultset
   List<String> deptNameResultset = new ArrayList<String>();
   Query query = em.createNamedQuery("Departments.filteredValues").setParameter("deptName", deptName);
   Vector result = (Vector)query.getResultList();
   int resultSize = result.size();
   for (int i = 0; i > resultSize; i++) {
      Departments dept = (Departments)result.get(i);
      deptNameResultset.add(dept.getDepartmentName());
   }
   return deptNameResultset;
}
In the ViewController create a file AutoSuggest.jspx page, from component palette drag and drop <af:inputText/> and in PI palette change the label to Dept Name. Add the autoSuggestBehavior tag to the inputText. Click on the autoSuggestBehavior, in  PI palette click on Edit property for Suggested Items and create a "AutoSuggest" managed bean with scope as "request" as shown in below Image.

AutoSuggestBean.png


Create new method as deptNameResultList and click ok.

AutoSuggestBeanMethod.png


In AutoSuggest.jspx page, go to binding tab and click create binding by selecting methodAction and click ok with parameter blank as shown in below image

FilteredValuesBinding.png


Open AutoSuggest.java managed bean and paste the below code.

public List deptNameResultList(String paramValue) {
  //Store the deptName result set
  List<SelectItem> deptResultList = new ArrayList<SelectItem>();
  //Filter the values using Items List
  List<SelectItem> items = new ArrayList<SelectItem>();
        
  BindingContainer bindings = getBindings();
  //Execute the Method
  OperationBinding operationBinding = bindings.getOperationBinding("getDepartmentsFilteredValues");
  //Populate the deptName parameter 
  operationBinding.getParamsMap().put("deptName", paramValue);
  operationBinding.execute();
  if (operationBinding.getResult() != null) {
      operationBinding.getResult();
      ArrayList result = (ArrayList)operationBinding.getResult();
      int resultSize = result.size();
      for (int i = 0; i < resultSize; i++) {
         deptResultList.add(new SelectItem(result.get(i)));
      }
   }
   for (SelectItem item : deptResultList) {
     if (item.getLabel().startsWith(paramValue)) {
          items.add(item);
     }
   }
  return items;
}

public BindingContainer getBindings() {
   return BindingContext.getCurrent().getCurrentBindingsEntry();
}
Run AutoSuggest.jspx, Dept Name text field will be displayed. As soon as the user has typed a character, a filtered list of suggested values is presented( for ex: C), Now traverse the list by using up and down arrow and select a suggested value from the list and thus applying that value to the inputText component.
 
AutoSuggestResult.png

Wednesday Aug 03, 2011

Passing parameter to EJB Method in taskflow

This article describes on passing parameter to EJB Method in taskflow.

Use Case Description

Suppose we have a table displaying Dept records.Table also has column link & clicking on this link displays a region in popup.This region accepts deptno parameter,executes EJB Method & displays respective Emp details in a popup.

Implementation steps

Let us suppose that we have created Java EE Web Application with Entities from Emp & Dept table .Also add 'ADF Faces Components 11' under ViewController->project properties-> JSP Tag Libraries.

Edit Emp.java & create a custom named query that returns Emp Object for the respective deptno :


 @NamedQuery(name = "findEmpByDeptno", query = "select o from Emp o
 where o.dept.deptno = :deptNo")
Let us create Stateful Session Bean and expose the Named Query through the Session Facade.Our use case deals with passing parameters to EJB method in taskflow.So we will define simple EJB method that just accepts deptno parameter & stores its value in private variable:
   
 public void passDeptno(BigDecimal deptNo) 
 {
 this.setDepartNo(deptNo);
 }

Now that we have separate method to accept parameter we will modify findEmpByDeptno namedQuery as below:

 public List<Emp> findEmpByDeptno() 
{
 
 return em.createNamedQuery("findEmpByDeptno").setParameter
 ("deptNo", this.getDepartNo()).getResultList();
}

Generate Data control for the above Session Bean & expose the above method through the Session Facade.

Create a ADF taskflow with page Fragments & create an inputParameter 'inputParameter1' in its overview parameters tab:

adf_taskflow.JPG










taskflow_param.JPG
Drop passDeptno(BigDecimal) as Method Call activity with value as
#{pageFlowScope.inputParameter1}.Drop findEmpByDeptno()->Operations->execute operation as Method Call activity & then drop  emp view activity on the taskflow.Define all control flows.

taskflow2.jpeg
Create emp.jsff page fragment & drop findEmpByDeptno()->Emp as ADF Table with single row selection

emp_tab.JPG


Now we will create main.jspx page & drop deptFindAll as ADF table with single row selection on this.We will also create deptno attribute bindings in page definition file:

attribute.JPG
Insert a new column inside the table that displays Emp Details.Drop the above created taskflow as region inside the column.Pass '#{sessionScope.deptno}' value for inputParameter1 & set the taskflow's ifNedded property to 'Refresh'.Here we are using setPropertyListener to pass parameter to taskflow method:

<af:column id="c4" headerText="Emp details">
<af:commandLink text="Emp details" id="cl1">
<af:showPopupBehavior popupId="p1"/>
</af:commandLink>
<af:popup id="p1" contentDelivery="lazyUncached">
<af:dialog id="d2" title="Emp Details" type="none">
<af:region
 value="#{bindings.taskflowdefinition1.regionModel}"
id="r1"/>
</af:dialog>
<af:setPropertyListener type="popupFetch"
from="#{bindings.deptno.inputValue}"
to="#{sessionScope.deptno}"/>
</af:popup>
</af:column>

Run the page,it shows Dept records.Select any dept record & click on 'Emp Details' link.It shows popup with its respective Emp records


Thursday Jul 28, 2011

Custom Table Pagination Using EJB Native Query

Let us take scenario where the table has more records. Here employees table has more number of records, if the entire records are displayed in single ADF table, It will be difficult for user to navigate or traverse to the exact record. This can be achieved by implementing pagination, Pagination is an important aspect when displaying large number of records. This blog would be of help if you are building applications that render large number of records in a table. With pagination, the number of records displayed can be controlled into several manageable chunks, thus making it easy to locate the records of interest.

Model Diagram:
Employees.png

Here in the above model diagram, Employees table schema.

Let us consider the above Employees table has more number of records, User will not be able to see all the records at the same time on web page.
For ex:- Employees Details Page

Employee More Record.png


We use the af:iterator tag to implement the custom table with pagination. This tag renders a collection in the same fashion as the af:table tag does. Same as af:table tag, af:iterator can be based on table binding available in page definition. It iterates over data collection and renders data rows.

First, create entities based on  Employees, then create a stateless session bean and data control for the session bean. Add the below code to the session bean and expose the method in local/remote interface and generate a data control for that.

Note:- Here in the below code "em" is a EntityManager.

 /**
  * Returns list of employee list starting at the given first index with the given max row count.
  * @return list of  employee list starting at the given first index with the given max row count.
  */
   public List<Employees> employeesByLimit(int firstRow, int maxRow) {
        String queryString = "select * from Employees order by employee_id ASC";
        return em.createNativeQuery(queryString,
                                    Employees.class).setMaxResults(maxRow).setFirstResult(firstRow).getResultList();
   }

 /**
  * Returns total amount of rows in table.
  * @return Total amount of rows in table.
  */
   public int employeesTotalRows() {
        String queryString = "select * from Employees order by employee_id ASC";
        Query query = em.createNativeQuery(queryString);
        List results = query.getResultList();
        return results.size();
   }

In the ViewController create a file CustomPagination.jspx page, right click and "Go to Page Definition", CustomPaginationPageDef.xml file will be created. 

Create a CustomPagination managed bean with scope as "sessionScope" add the below code:

    private int firstRow = 0;
    private int rowsPerPage = 10;
    private int totalRows;
    private int totalPages;
    private int currentPage = 1;

    public CustomPagination() {
        this.loadList();
    }

    public void loadList() {
        /**
         * Returns total amount of rows in table.
         * @return Total amount of rows in table.
         */
        BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
        AttributeBinding attr = (AttributeBinding)bindings.getControlBinding("EmployeesTotalRowCount");
        String val = attr.getInputValue().toString();
        int rows = Integer.parseInt(val);
        this.setTotalRows(rows);

        double val1 = ((double)this.getTotalRows() / this.getRowsPerPage());
        int totalPagesCal = (int)Math.ceil(val1);
        this.setTotalPages((totalPagesCal != 0) ? totalPagesCal : 1);

    }

    public void firstActionListener(ActionEvent actionEvent) {
        this.setCurrentPage(1);
        this.setFirstRow(0);
    }

    public void previousActionListener(ActionEvent actionEvent) {
        this.setCurrentPage(this.getCurrentPage() - 1);
        this.setFirstRow(this.getFirstRow() - this.getRowsPerPage());
    }

    public void nextActionListener(ActionEvent actionEvent) {
        this.setCurrentPage(this.getCurrentPage() + 1);
        this.setFirstRow(this.getFirstRow() + this.getRowsPerPage());

    }

    public void lastActionListener(ActionEvent actionEvent) {
        this.setCurrentPage(this.getTotalPages());
        this.setFirstRow(this.getTotalRows() -
                         ((this.getTotalRows() % this.getRowsPerPage() != 0) ? this.getTotalRows() %
                          this.getRowsPerPage() : this.getRowsPerPage()));
    }

    public boolean isBeforeDisabled() {
        return this.getFirstRow() == 0;
    }

    public boolean isAfterDisabled() {
        return this.getFirstRow() >= this.getTotalRows() - this.getRowsPerPage();
    }

    public void setFirstRow(int firstRow) {
        this.firstRow = firstRow;
    }

    public int getFirstRow() {
        return firstRow;
    }

    public void setRowsPerPage(int rowsPerPage) {
        this.rowsPerPage = rowsPerPage;
    }

    public int getRowsPerPage() {
        return rowsPerPage;
    }

    public void setTotalRows(int totalRows) {
        this.totalRows = totalRows;
    }

    public int getTotalRows() {
        return totalRows;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getCurrentPage() {
        return currentPage;
    }

Open CustomPagination.jspx, click on Binding tab and and click on Create control binding and select methodAction for employeesTotalRows as shown in below image.


EmployeesTotalRows_ActionBinding.png


Open CustomPaginationPageDef.xml and add the below code snippet inside "variableIterator" tag.

<variable Type="int" Name="employeesTotalRows_Return" IsQueriable="false" IsUpdateable="0" DefaultValue="${bindings.employeesTotalRows.result}"/>
Open CustomPagination.jspx,  click on Binding tab and click on Create control binding and select attributeValues and create attribute binding for employeesTotalRows_Return and in Property Inspector change the id to "EmployeesTotalRowCount"

EmployeesTotalRows_AttributeBinding.png


Click on Create control binding and select methodAction for employeesByLimit as shown in below image

EmpBinding.png


Create Tree binding for control of Employees result set.

EmpEditTreeBinding.png


Click on Create Executable binding and select Invoke action and follow as shown in below image.

InvokeAction.png


Edit TotalRows invoke actiion and set the Refresh to prepareModel, so when ever page loads employeesTotalRows method will get executed.


prepareModel.png


Go to CustomPagination.jspx Source tab and copy the below code snippet. As mentioned above af:iterator tag to implement the custom table with pagination.

<af:group id="g1">
	<af:panelGroupLayout id="pgl1" layout="scroll">
		<af:spacer width="10" height="10" id="s16"/>
		<af:panelGroupLayout id="pgl9" layout="horizontal">
			<af:spacer width="10" height="10" id="s9"/>
			<af:panelGroupLayout id="pgl10" inlineStyle="width:75px;" layout="horizontal">
				<af:outputText value="Employeed Id" id="ot1" inlineStyle="font-weight:bold;"/>
			</af:panelGroupLayout>
			<af:spacer width="10" height="10" id="s7"/>
			<af:panelGroupLayout id="pgl7" inlineStyle="width:75px;" layout="horizontal">
				<af:outputText value="First Name" id="ot6" inlineStyle="font-weight:bold;"/>
			</af:panelGroupLayout>
			<af:spacer width="10" height="10" id="s10"/>
			<af:panelGroupLayout id="pgl11" inlineStyle="width:75px;" layout="horizontal">
				<af:outputText value="Last Name" id="ot4" inlineStyle="font-weight:bold;"/>
			</af:panelGroupLayout>
			<af:spacer width="10" height="10" id="s11"/>
			<af:panelGroupLayout id="pgl12" inlineStyle="width:75px;" layout="horizontal">
				<af:outputText value="Email" id="ot7" inlineStyle="font-weight:bold;"/>
			</af:panelGroupLayout>
			<af:spacer width="10" height="10" id="s12"/>
			<af:panelGroupLayout id="pgl15" inlineStyle="width:75px;" layout="horizontal">
				<af:outputText value="Salary" id="ot10" inlineStyle="font-weight:bold;"/>
			</af:panelGroupLayout>
		</af:panelGroupLayout>
		<af:separator id="s15"/>
		<af:spacer width="10" height="10" id="s2"/>
		<af:iterator id="i1" value="#{bindings.result.collectionModel}" var="row">
			<af:panelGroupLayout id="pgl2" layout="horizontal">
				<af:spacer width="10" height="10" id="s3"/>
				<af:panelGroupLayout id="pgl3" layout="horizontal" inlineStyle="width:75px;">
					<af:outputText value="#{row.employeeId}" id="ot8"/>
				</af:panelGroupLayout>
				<af:spacer width="10" height="10" id="s13"/>
				<af:panelGroupLayout id="pgl13" layout="horizontal" inlineStyle="width:75px;">
					<af:outputText value="#{row.firstName}" id="ot11"/>
				</af:panelGroupLayout>
				<af:spacer width="10" height="10" id="s4"/>
				<af:panelGroupLayout id="pgl4" layout="horizontal" inlineStyle="width:75px;">
					<af:outputText value="#{row.lastName}" id="ot9"/>
				</af:panelGroupLayout>
				<af:spacer width="10" height="10" id="s6"/>
				<af:panelGroupLayout id="pgl5" layout="horizontal" inlineStyle="width:75px;">
					<af:outputText value="#{row.email}" id="ot2"/>
				</af:panelGroupLayout>
				<af:spacer width="10" height="10" id="s8"/>
				<af:panelGroupLayout id="pgl8" inlineStyle="width:75px;" layout="horizontal">
					<af:outputText value="#{row.salary}" id="ot3"/>
				</af:panelGroupLayout>
			</af:panelGroupLayout>
			<af:spacer width="10" height="10" id="s1"/>
		</af:iterator>
		<af:panelGroupLayout id="pgl6">
			<af:commandButton text="First" id="cb1"
							  actionListener="#{CustomPagination.firstActionListener}"
							  partialTriggers="i1" disabled="#{CustomPagination.beforeDisabled}"/>
			<af:commandButton text="Prev" id="cb2"
							  actionListener="#{CustomPagination.previousActionListener}"
							  partialTriggers="i1" disabled="#{CustomPagination.beforeDisabled}"/>
			<af:commandButton text="Next" id="cb3"
							  actionListener="#{CustomPagination.nextActionListener}"
							  partialTriggers="i1" disabled="#{CustomPagination.afterDisabled}"/>
			<af:commandButton text="Last" id="cb4"
							  actionListener="#{CustomPagination.lastActionListener}"
							  partialTriggers="i1" disabled="#{CustomPagination.afterDisabled}"/>
			<af:spacer width="10" height="10" id="s5"/>
			<af:outputText value="Page #{CustomPagination.currentPage} / #{CustomPagination.totalPages}"
						   id="ot5"/>
		</af:panelGroupLayout>
	</af:panelGroupLayout>
</af:group>

Run the CustomPagination.jspx, Now It always displays 10 rows (configurable) in the CustomPagination.java page. The page provides buttons to navigate between pages and shows current page number. If user is moves to second or third page, navigation buttons for

previous page will be enabled, If we navigate to the last page, navigation buttons for next navigation become disabled and If we navigate to the first page, First and Prev buttons should be disabled.

FinalResult.png


Monday May 09, 2011

Native Query using the SQL 'IN' clause

Use-Case Description:

Consider a case where we need to retrieve employees where Department and Employees entities are associated by One to Many mapping, the retrieval is using complex queries with a complex result set.

Ex: JPQL with "IN clause" where we need to pass series of values in one parameter, say list type. As the Java Persistence Query Language does not support passing a list of items as an input/named parameter, we are limited by the JPQL language to use "IN clause" in named queries.

Here is one solution to overcome this limitation, this can be achieved by creating native SQL queries to run complex queries and also handle complex result sets.

First, create entities based on Department, Employees, then create a stateless session bean and data control for the session bean. Add the below code to the session bean and expose the method in local/remote interface and generate a data control for that.

Note: Parameters in the example below are hard coded.

The code below describes one way of creating a native query and defining a result set that can map to an entity. Notice that the result set is mapped to the Employees entity class.

Note:- Here in the below code "em" is a EntityManager.

 public List<Employees> NativeQuery() {
        String queryString =
            "select * from Employees where department_id in (10, 20, 40, 50) order by department_id ASC";
        return em.createNativeQuery(queryString,
                                    Employees.class).getResultList();
    }

Here is another way of creating a native query using custom code to generate a custom result set.

 public List<Employees> NativeQueryCustomCode() {
        String queryString =
            "select * from Employees where department_id in (10, 20, 40, 50) order by department_id ASC";
        Query genericSearchQuery =
            em.createNativeQuery(queryString, "InQuery");
        List resultList = genericSearchQuery.getResultList();
        Iterator resultListIterator = resultList.iterator();
        List<Employees> employeesList = new ArrayList();
        while (resultListIterator.hasNext()) {
            Object col[] = (Object[])resultListIterator.next();
            Employees employees = new Employees();
            BigDecimal employeeId = (BigDecimal)col[0];
            employees.setEmployeeId(employeeId.longValue());
            employees.setFirstName((String)col[1]);
            employees.setLastName((String)col[2]);
            employees.setEmail((String)col[3]);
            employees.setPhoneNumber((String)col[4]);
            employees.setJobId((String)col[6]);
            BigDecimal salary = (BigDecimal)col[7];
            employees.setSalary(salary.doubleValue());
            employees.setCommissionPct((Double)col[8]);

            Departments departments = new Departments();
            BigDecimal departmentId = (BigDecimal)col[10];
            departments.setDepartmentId(departmentId.longValue());
            employees.setDepartments(departments);

            employeesList.add(employees);
        }
        return employeesList;
}


In the ViewController create a file NativeQuery.jspx, from the DataControl palette drag and drop NativeQuery->Employees as ADF Read-only Table and select the columns to be displayed.

Run NativeQuery.jspx, Employees who belong to the departments with Id (10,20,30,40) should only be displayed. 

NativeQuery.PNG

About

Tips and Tricks from Oracle's JDeveloper & ADF QA

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today