ads

X

Tuesday, April 8, 2014

Configuring Extensions.xml and Manifest.MF after creating extensions project

In my last post Creating and Debugging Jdeveloper 12c Extensions project, I explained how to download Extensions SDK and create a new Jdev Extensions project.
But that was not all to set and start creating jdev extensions.

After creating the project, there is very important step which has to be taken care of to start working with extensions.

So after we created the extensions project, it still does not have library dependencies for jdev audit extensions. If we check its classpath, it shows something like below :-





At this point if we go and create our custom Audit Analyzer (jdev extension rule analyzer), it gives compile time error for the framework class Analyzer not found.

The catch to this is that we need to add bundles in Manifest.MF file and dependencies in Extensions.xml file.
For this , go to Extensions.xml overview tab and go to Dependencies. There you can see that Required Bundles are empty.
The Required Bundles should have lib which will be used in the project. For this, go to Manifest.MF file and add the bundles like below.
Save it, and now if we see Extension.xml, it has all the required bundles.
Adding dependencies to Extension.xml will result in changing Manifest.MF and vice-versa. Any of two can be used to do this step.
Now we are done. If we go to Custom Analyzer, we can see that it has access to framework extension class.

Custom Rules for ADF BC Java Files

We will be discussing how we can write rules for ADF BC framework classes like EntityImpl and ViewObjectImpl.

The way how we identify that we are in current file for example, to know wether we are in Entity defination XML file we need below piece of code. This tells the Custom Analyzer that for all the files other than entity defination files, the Rules should be set false. This means that for all files other than entity files, rules for Entity Objects should be disabled i.e  Framework should not execute further drill down methods of the Analyzer which are exit(AuditContext, Drill Down Elements) in most of the cases.





Now this works well for XML Files. But what if we need to do this check for Java files.

Lets take an example:
I need to create a rule which checks, that there is no reference to Application Module from Entity Class. 
This rule needs to check in the code of EOImpl class that is there any call to ApplicationModule.

The point worth noting here is, when we check for XML file, we use Document object in enter method as second parameter. This is because Document is the root node of any XML document and it will be executed by the framework once for each XML document. Since this is called only once, its a good place to write the logic to enable or disable further calls to other methods.

But for the source files, Document won't work. If we use the same enter method with same signature, it will not be called by the framework for java source file.

So the root node for source file is oracle.javatools.parser.java.v2.model.SourceFile. This needs to be used as second parameter of enter method , which gives us a place to write logic for enable and disable of rules.

Now again there is one more catch. How will we identify that this class is EntityImpl class. Because we need to disable rule for all classes other than EntityObjectImpl classes. Below is the code which does this.


This checks whether  the class's super class is EntityImpl. This is because every Entity Object Impl class extends EntityImpl.

Now we are good at checking part. Now lets write a logic for checking if code has reference to ApplicationModule and if yes, send warnings as violations.

Below is the code which checks for the same :

The logic inside the IF Condition is very simple. If the text contains ApplicationModule, report violation of rule. But the catch here is which parameter should be used as second parameter of exit method which framework will call again and again for a construct.
SourceBlock (oracle.javatools.parser.java.v2.model.SourceBlock) returns text of complete block within the braces({}) of the java code. This becomes little tricky to find out which type to be used as second parameter in exit method to suite your need.
So below is the link to all the Types inside oracle.javatools.parser.java.v2.model package. This can be used as reference when working with defining custom rules for source files.
http://docs.oracle.com/cd/E26098_01/apirefs.1112/e17493/oracle/javatools/parser/java/v2/model/package-summary.html

Friday, April 4, 2014

Refresh Page in Oracle ADF by Java Code

Some times we need to refrsh whole page in Oracle ADF, then we can use this managed bean code to refresh whole page in ADF.


  1. protected void refreshPage() {
  2. FacesContext fctx = FacesContext.getCurrentInstance();
  3. String refreshpage = fctx.getViewRoot().getViewId();
  4. ViewHandler ViewH = fctx.getApplication().getViewHandler();
  5. UIViewRoot UIV = ViewH.createView(fctx, refreshpage);
  6. UIV.setViewId(refreshpage);
  7. fctx.setViewRoot(UIV);
  8. }

Partially refresh any UIComponent-


  1. AdfFacesContext.getCurrentInstance().addPartialTarget(UIComponent);

Wednesday, April 2, 2014

Performing Partial Rollback (Undo Changes) operation in ADF, Stay on current row after rollback

This post talks about a common requirement of using partial rollback in ADF

Suppose there is two tables on page Departments and Employees, and i have changed one row in Departments table and same time created a row in Employees table, now i want to rollback the changes done in Departments table only

In this case if i use default Rollback operation then it will not only undo the changes of Department table but also remove the newly created row of Employees table
but this was not my purpose.

So to do this kind of things we can use partial rollback operation

  • I have created a fusion web application (Model & VC) using Departments & Employees Table of Oracle's default HR Schema

  • Now drop departments & employees VO on page with it's default operations (CreateInsert, Delete, Execute, Commit & Rollback) and a button to execute partial rollback of departments ViewObject


  • here in this example i am creating partial rollback for Departments VO only, so to do this add a new transient attribute in Departments Vo to get current state of each row


  • now to get state of each row , in RowImpl class of departments ViewObject , write this code in getter of transient attribute or see my previous blog-post http://oracleadf-java.blogspot.in/2014/01/identifying-modifiednewely-added-row-in.html

  •     /**
         * Gets the attribute value for the calculated attribute RowStatusTrans.
         * @return the RowStatusTrans
         */
        public Integer getRowStatusTrans() {
            /*here row is reference variable of collection, this expression returns an int value if it is
             2-Modified
             0-New
             1-Unmodified
            -1-Initialized
            */
            byte entityState = this.getEntity(0).getEntityState();
            return new Integer(entityState);
        }
    

  • have created a method to remove newly added row , and to undo changes in existing rows of departments VO in Impl class

  •     /**Method to revert changes of current row
         * @param curRow
         */
        public void revertChangesCurrentRow(Row curRow) {
            if (curRow != null) {
                curRow.refresh(Row.REFRESH_UNDO_CHANGES | Row.REFRESH_WITH_DB_FORGET_CHANGES);
            }
        }
    
        /**Method to check whether row should be removed or not 
         * If it is new - removed
         * If old one- Undo Changes
         * */
        public void revertOrremoveRowValues() {
            ViewObject deptVo = this;
            RowSetIterator deptIter = deptVo.createRowSetIterator(null);
            while (deptIter.hasNext()) {
                Row nextRow = deptIter.next();
                if (nextRow.getAttribute("RowStatusTrans") != null) {
                    Integer rowStatus = (Integer) nextRow.getAttribute("RowStatusTrans");
                    if (rowStatus == 2) {
                        System.out.println("Modified Rows-" + nextRow.getAttribute("DepartmentId"));
                        revertChangesCurrentRow(nextRow);
                    } else if (rowStatus == 0) {
                        System.out.println("New Row Removed");
                        nextRow.remove();
                    }
                }
            }
            this.executeQuery();
        }
    

  • to read more about REFRESH_UNDO_CHANGES and other constants -http://docs.oracle.com/cd/B14099_19/web.1012/b14022/oracle/jbo/Row.html
  • exposed this method to client and added it to page bindings then called it on Partial Rollback button


  • after running application, i have changed some rows of Departments table and created a new row in employees table


  • now if i use rollback, it will also remove the new row of employees table, this is the dis-advantage of using rollback


  • again i have changed some rows of departments table and created a new row in employees table


  • now see when i click on partial rollback button, it will only undo changes done in department table and employee table is untouched


  • and to stay on current row after partial rollback operation just remove executeQuery from revertOrremoveRowValues() method
Download Sample App

Creating and Using an ADF Declarative Component

This tutorial shows you how to create ADF declarative component metadata, add ADF Faces components that make up the composite component, and use the declarative component on a JSF page.

In this post ADF: About JSF fragments, ADF regions, declarative components …, i wrote about different declarative component in ADF faces.

You will use wizards to quickly create applications and projects, and a declarative component definition consisting of an attribute, a facet and a method.

The declarative component you will create is panel box containing one label, list of input text, and button. The metadata for the declarative component definition will allow page authors to set the label for a panel box, attach a method to the button to print the input lists after modification, and use built in controllerContext to view page viewId as default value.

To create the declarative component layout, you will use design tools such as the visual editor, Component Palette, and the Property Inspector. Then you will deploy the project to an ADF Library JAR file. For an application to consume the declarative component, you will use the Resource Palette to add the deployed JAR, and then add the deployed JAR to the project that contains JSF pages.

To make use of the declarative component, you will add it to a simple JSF page, edit the pre-defined attributes, create a method and attach it to the declarative component. When you run the application, the page will look similar to this:




1- From the main menu, choose File > New. In the New Gallery, expand the General category and select Applications. Then in the Items list, select Fusion Web Application (ADF) and click OK.



2- I created a separate ADF ViewController project in my work space:


3- In this project open the Create JSF Declarative Component wizard:


4- The new declarative component I18NDef should have at least three attributes and one method:

  • Some string for label.
  • Attribute binding for input texts as Array list called dataI18Ns.
  • Some object for other with default value of "# {controllerContext.currentViewPort.viewId} ".
  • Method called doPrint of signature of " void method(javax.faces.event.ActionEvent) ":

The source code of I18NDef.jspx component looks like this:
?
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <af:componentDef var="attrs" componentVar="comp" id="ccDef">
        <!-- Component implementation -->
        <af:panelBox text="#{attrs.label}" id="dc_pb1">
            <af:panelGroupLayout id="dc_pgl1" layout="vertical">
                <af:outputLabel value="#{attrs.other}" id="dc_ol1"/>
                <af:forEach items="#{attrs.dataI18Ns}" var="langVal">
                    <af:inputText value="#{langVal.name}"/>
                </af:forEach>
            </af:panelGroupLayout>
            <af:commandButton text="Print" id="dc_cb1" actionListener="#{comp.handleDoPrint}"/>
        </af:panelBox>
        <!-- Component Definition -->
        <af:xmlContent>
            <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
                <display-name>I18NDef</display-name>
                <attribute>
                    <attribute-name>label</attribute-name>
                    <attribute-class>java.lang.String</attribute-class>
                    <required>true</required>
                </attribute>
                <attribute>
                    <attribute-name>dataI18Ns</attribute-name>
                    <attribute-class>java.util.ArrayList</attribute-class>
                    <required>true</required>
                </attribute>
                <attribute>
                    <attribute-name>other</attribute-name>
                    <attribute-class>java.lang.Object</attribute-class>
                    <default-value>#{controllerContext.currentViewPort.viewId}</default-value>
                </attribute>
                <component-extension>
                    <component-tag-namespace>component</component-tag-namespace>
                    <component-taglib-uri>/componentLib</component-taglib-uri>
                    <method-attribute>
                        <attribute-name>doPrint</attribute-name>
                        <method-signature>void method(javax.faces.event.ActionEvent)</method-signature>
                        <required>true</required>
                    </method-attribute>
                </component-extension>
            </component>
        </af:xmlContent>
    </af:componentDef>
</jsp:root>

5- The next step is to deploy the component into ADF Library. We have to add new deployment profile for the CSComponents project:




6- And let's deploy the project into library:



7- The following step is to define File System connection in the resource palette to the deployment path of CSComponents project:


8- After that we have to choose the project where we're going to use the new component (in my case Custom Components) and add CSComponents.jar library to it:


Now we can use I12NDef component in our page and drag it from the component palette:



In our CCTestPage.jsf page the source code is going to look like this:
?
1
2
3
4
5
6
7
8
9
10
11
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        xmlns:cc="/componentLib">
    <af:document title="CCTestPage.jsf" id="d1">
        <af:form id="f1">
            <cc:I18NDef dataI18Ns="#{cCTestBean.dataI18N}" doPrint="#{cCTestBean.doSomthing}"
                        label="Display Panel"/>
        </af:form>
    </af:document>
</f:view>

And the following is the CCTestBean JSF 2 managed bean source:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package eg.com.tm.cc.view.managed;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ActionEvent;
@ManagedBean
public class CCTestBean {
    private ArrayList<datai18n> dataI18N = new ArrayList<datai18n>(3);
    public void doSomthing(ActionEvent event) {
        for (DataI18N data : dataI18N)
            System.out.println(data.getName());
    }
    @PostConstruct
    public void init() {
        dataI18N.add(new DataI18N("Data 1"));
        dataI18N.add(new DataI18N("Data 2"));
        dataI18N.add(new DataI18N("Data 3"));
    }
    public ArrayList<datai18n> getDataI18N() {
        return dataI18N;
    }
}

The data that contained in the list is instance from the following object:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package eg.com.tm.cc.view.managed;
public class DataI18N {
    private String name;
    public DataI18N(String name) {
        super();
        this.name = name;
    }
    public DataI18N() {
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

And after changing the data in the input boxes then press the print button you will see the reflected changes printed in the jdeveloper console as the following:






Summary
In this tutorial you defined an ADF declarative component and then used it on a JSF page. You learned how to:
  • Use JDeveloper wizards and dialogs to create applications and projects.
  • Define attribute, facet and method metadata for a declarative component, and the declarative component layout.
  • Define the tag library that will contain the declarative component.
  • Create a deployment profile for an ADF Library JAR.
  • Deploy the project that contains the declarative component definition to an ADF Library JAR.
  • Share the ADF Library JAR by adding a file system connection in the Resource Palette.
  • Add the ADF Library JAR to the application and project that will make use of the declarative component.
  • Add and modify the declarative component on a JSF page.
  • Use the Create Managed Bean dialog to add and attach a managed bean method.
  • Use Integrated WebLogic Server to run an ADF Faces application.
To learn more about using Oracle ADF Faces refer to:

About JSF fragments, ADF regions, declarative components …

Starting application development with Oracle ADF and ADF Faces, some concepts may be hard to grasp at the beginning. Using Oracle ADF and ADF Faces, the following terminologies are used in the context of reuse of components and processes
JSF fragments
JSF page fragments are page definitions that run embedded in another JSF page. Fragments are like page includes in JavaServer Pages, with the difference that in Oracle ADF Faces they are usually used in the context of ADF regions or dynamic declarative components. You can also reference page fragments directly from a JSP includes tag added to a JavaServer Faces document (JSPX). However, in this case, and only if a page fragment has ADF bound content, you need to make sure the content of the page fragments ADF binding file (PageDef) is copied to the PageDef file of the parent page. Otherwise ADF queried data will not show.
ADF regions
ADF regions consist of an ADF Faces af:region tag, an ADF bounded task flow and page fragments. Page fragments that are used in a bounded task flow don't need to copy their ADF binding references to the parent container, which is a huge difference between JSP includes and ADF regions. ADF regions define an interactive area on a view, a JSF document or another JSF page fragment, that developers use to show a single view or a complete, multi-step, process. ADF regions can be statically or dynamically defined. In either way they require a PageDef file and a bounded task flow to reference. ADF regions help building desktop like web applications in which users stay for long on a single page while working on a business task.
Declarative components
Declarative components allow developers to build a composite component out of existing ADF Faces components. Declarative components exist in two flavors: library driven and dynamic declarative components (ddc). The tag library driven components are declaratively built from the File | New menu option. In the JSF view option you find a declarative component menu option that steps you through building your own ADF F aces component from existing ADF Faces components. You use tag library driven declarative components to build custom components with behavior, like a tool bar or a custom file-upload handler. The goal of building declarative components is to build re-usable components that simplify development and administration by avoiding duplicate page codes. Dynamic declarative components (DDC) are used within the scope of the web application they are defined in and cannot be re-used across applications. Their main usage is to build reusable layout artifacts or page area components. For example, a custom tab canvas is what you would build using DDC components.  
Page templates
Page templates are layout definitions that you use as a starter when building new pages to enforce consistent page layouts throughout applications and enterprises. Best practices are to build a page template using the ADF Faces Quick start templates. You cannot nest page templates, but you can use page templates on parent and child views (page fragments). A page template is the page level equivalent to a DDC component.
ADF Library
ADF libraries are special Oracle ADF archive files that you use to reuse bounded task flows (regions), page templates and declarative components. They are standard JAR files with extra information in the archive manifest file that allows you to import the library files into the Oracle JDeveloper Resource Palette for declarative reuse.
When designing an application you best start planning reuse of components and page segments. If you have an application wide look and feel that you can define as page template(s) then do this first. If you can identify areas within pages that you may need more often on other pages as well, without the pages to be identical from their layout, you use dynamic declarative components. For functionality like global toolbars or common and composite user interface logic, you build tag library based declarative components, which then can be used across applications too. An ADF region is an interactive and optionally also data centric page are that you use to show complete business processes in place. ADF regions are a friend for building rich Internet application interfaces and business centric web desktops. ADF libraries are the vehicle to deploy your reusable work.

Tuesday, April 1, 2014

Creating pdf file using Apache PDFBox API in ADF Faces and opening it in new window -Oracle ADF

Apache PDFBox library is an open source java tool for working with PDF documents, go to http://pdfbox.apache.org/ for API docs and download jar (pdfbox-app-1.8.2) from there.


  •  Now create a fusion web application and add jar to view controller project's library and class-path
  •  To convert text to pdf format, i have used an input text and bind it to bean (to get value)
  •  Now see the button code that converts text to pdf file format using Apache PDFBox

  •         PDDocument document = new PDDocument();
            PDPage page = new PDPage();
            document.addPage(page);
    
            // Create a new font object selecting one of the PDF base fonts
            PDFont font = getFontDef();
    
            // Start a new content stream which will "hold" the to be created content
            PDPageContentStream contentStream = new PDPageContentStream(document, page);
    
            // Define a text content stream using the selected font, moving the cursor and drawing the text "Hello World"
    
            contentStream.beginText();
            contentStream.setFont(font, 10);
            contentStream.moveTextPositionByAmount(50, 700);
            contentStream.drawString(textToConvert.getValue().toString());
            contentStream.endText();
    
            // Make sure that the content stream is closed:
            contentStream.close();
    
            // Save the results and ensure that the document is properly closed:
            try {
                document.save("D:/Test_pdf.pdf");
            } catch (COSVisitorException e) {
            }
            document.close();
    

  • now your pdf is generated in fixed path, and if user want to open it immediately , try to do this

  •         if ((new File("D:\\Hello World.pdf")).exists()) {
    
                Process p = Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler D:\\Hello World.pdf");
                p.waitFor();
    
            } else {
    
                System.out.println("File is not exists");
    
            }
    

  • this code invokes File Protocol using Runtime class
  • Run this application and see-
 Click on generate button-


For more details and functionality visit Apache PDFBox site