Monday, September 30, 2013

How to get only modified attributes in an Entity ?

This blog explains about performing customized audit s on a specific tables

Scenario : Audit only modified columns associated data into Audit table, rather than unmodified field values into history/audit table.

 - get only modified attribute name, old value and new value for an entity
 - get the table name associated to an entity
 - get the database column name associated to an entity
- store only modified columns associated data into audit table.

Implementation

- Create a BaseEntityImpl class which extends to oracle.jbo.server.EntityImpl, override doDML() method as shown below

- Get the entity state, based on the entity state perform database CRUD operations.


       

           @Override
    protected void doDML(int i, TransactionEvent transactionEvent) {
        String userName =
            ADFContext.getCurrent().getSecurityContext().getUserName();
        SimpleDateFormat sdf = new SimpleDateFormat("d-MMM-yyyy HH:mm:ss");
        String currentTime = sdf.format(System.currentTimeMillis());

        if (EntityImpl.DML_DELETE == i) {
            System.out.println("Delete operation");
            Long timeInMillis = System.currentTimeMillis();
            try {

                String sql =
                    "INSERT INTO XXATDTPR_HISTORY_DATA(ID,TABLE_NAME,KEY_NAME,KEY_VALUE,OPERATION,CREATED_BY,CREATED_ON,UPDATED_BY,UPDATED_ON) VALUES(" +
                    timeInMillis + ",'" + this.getEntityDef().getSource() +
                    "','" +
                    ((BaseDefImpl)this.getEntityDef()).getPrimaryKeys()[0].getColumnName() +
                    "','" +
                    getAttribute(((BaseDefImpl)this.getEntityDef()).getPrimaryKeys()[0].getIndex()) +
                    "','" + "DELETE" + "','" + userName + "','" + currentTime +
                    "','" + userName + "','" + userName + "')";
                System.out.println("SQL :: " + sql);
                getDBTransaction().executeCommand(sql);

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (EntityImpl.DML_INSERT == i) {
            System.out.println("Insert operation");

            Long timeInMillis = System.currentTimeMillis();
            try {

                String sql =
                    "INSERT INTO XXATDTPR_HISTORY_DATA(ID,TABLE_NAME,KEY_NAME,KEY_VALUE,OPERATION,CREATED_BY,CREATED_ON,UPDATED_BY,UPDATED_ON) VALUES(" +
                    timeInMillis + ",'" + this.getEntityDef().getSource() +
                    "','" +
                    ((BaseDefImpl)this.getEntityDef()).getPrimaryKeys()[0].getColumnName() +
                    "','" +
                    getAttribute(((BaseDefImpl)this.getEntityDef()).getPrimaryKeys()[0].getIndex()) +
                    "','" + "INSERT" + "','" + userName + "','" + currentTime +
                    "','" + userName + "','" + userName + "')";
                System.out.println("SQL :: " + sql);
                getDBTransaction().executeCommand(sql);

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (EntityImpl.DML_UPDATE == i) {
            System.out.println("Update operation");

            AttributeDef[] attributeDefs =
                this.getEntityDef().getAttributeDefs();
            for (AttributeDef attributeDef : attributeDefs) {
                if (isAttributeChanged(attributeDef.getIndex())) {
                    Object oldValue =
                        getPostedAttribute(attributeDef.getIndex());
                    Object newValue = getAttribute(attributeDef.getIndex());
                    //use sequence generator here to generate unique prmary key
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                    }

                    Long timeInMillis = System.currentTimeMillis();
                    try {

                        String sql =
                            "INSERT INTO XXATDTPR_HISTORY_DATA(ID,TABLE_NAME,KEY_NAME,KEY_VALUE,COLUMN_NAME,OLD_VALUE,NEW_VALUE,OPERATION,CREATED_BY,CREATED_ON,UPDATED_BY,UPDATED_ON) VALUES(" +
                            timeInMillis + ",'" +
                            this.getEntityDef().getSource() + "','" +
                            ((BaseDefImpl)this.getEntityDef()).getPrimaryKeys()[0].getColumnName() +
                            "','" +
                            getAttribute(((BaseDefImpl)this.getEntityDef()).getPrimaryKeys()[0].getIndex()) +
                            "','" + attributeDef.getName() + "','" +
                            oldValue.toString() + "','" + newValue.toString() +
                            "','" + "UPDATE" + "','" + userName + "','" +
                            currentTime + "','" + userName + "','" + userName +
                            "')";
                        System.out.println("SQL :: " + sql);
                        getDBTransaction().executeCommand(sql);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        super.doDML(i, transactionEvent);
    }
       
 




Thursday, September 26, 2013

Various Entity States in ADF


Below are the list of various entity states, which are helpful to determine whether entity has been updated or not.

Below is how we can determine the state of an entity.
 VORowImpl newRow = (VORowImpl )getVO1().getCurrentRow();
        EOImpl eo = (EOImpl) newRow.getEntity(0);
        byte newRowStatus = eo.getEntityState();
        if (newRowStatus ==  eo.STATUS_NEW){
            isNewRow = true;
        }

States are set to one of these values: STATUS_INITIALIZEDSTATUS_NEWSTATUS_MODIFIEDSTATUS_DELETED and STATUS_DEAD based on whether the Entity Object is being created, updated, deleted, or rolled back, respectively. These operations can set either or both the post-state and the Entity-state. The status values have a slightly different meaning depending on whether they are set for an Entity-state or a post-state:
  • For Entity-state:
    • STATUS_UNMODIFIED - if this Entity Object originated in the database and is unmodified, or if modifications have been committed to the database.
    • STATUS_MODIFIED - if this Entity Object originated in the database, and has been modified in the current transaction.
    • STATUS_NEW - if this Entity Object is new in the current transaction.
    • STATUS_DELETED - if this Entity Object has been deleted in the current transaction.
    • STATUS_DEAD - if this Entity Object is new in the current transaction and has been deleted.
  • For post-state:
    • STATUS_UNMODIFIED - if this Entity Object has been queried from the database and is unchanged, or if it has been posted to the database.
    • STATUS_MODIFIED - if this Entity Object has been queried from the database and has changed.
    • STATUS_INITIALIZED - if this Entity Object is new and the client application changed it's state to make this Object temporary.
    • STATUS_NEW - if this Entity Object is new in the post-cycle.
    • STATUS_DELETED - if this Entity Object has been marked for deletion.
    • STATUS_DEAD - if this Entity Object is new, but has been deleted.

Where to find system-jazn-data.xml?


System-jazn-data.xml - The system-jazn-data.xml is an XML file which is configured by the user to use as an ID store and/or policy store.This file stores all the roles and permissions for all the custom secured applications which are deployed to stand alone weblogic server. This file will be updated automatically whenever any secured application deployed. This is the master file which contains all the roles/permissions related information.

Where to find this file in UNIX box ?

 The file is located in$DOMAIN_HOME/config/fmwconfig.

Where can I find this file in local machine ?


C:\Users\user\AppData\Roaming\JDeveloper\system11.1.1.6.38.62.29\DefaultDomain\config\fmwconfig

Wednesday, September 25, 2013

How to test PL/SQL Stored Function in JDeveloper



This blog explains about testing Pl/SQL stored procedure using Jdeveloper

- Connect to the corresponding database where your function created.
- Right click on the database connection , Choose SQL Worksheet
- In this example, I have created a stored function named 'get_emp_fullname()' which accepts one parameter i.e called Employee ID and returns Employee Full Name
-  As shown below, use the query to test the function by passing required values for the arguments, you will see the response as shown below



s

J2EE[160149]Error while processing library references. Unresolved application


This blog explains about how to resolve the below error while deploying ADF applications to stand alone Weblogic server

Deployment Error :
<07 Mar 2013 9:17:19 AM> <Error> <Deployer> <BEA-149265> <Failure occurred in the execution of deployment request with ID '1362640639128' for task '1'. Error is: 'weblogic.management.DeploymentException: [J2EE:160149]Error while processing library references. Unresolved application library references, defined in weblogic-application.xml: [Extension-Name: oracle.webcenter.framework, Specification-Version: 11.1.1, exact-match: false], [Extension-Name: oracle.webcenter.skin, Specification-Version: 11.1.1, exact-match: false], [Extension-Name: oracle.sdp.client, exact-match: false], [Extension-Name: oracle.soa.workflow.wc, exact-match: false].'
weblogic.management.DeploymentException: [J2EE:160149]Error while processing library references. Unresolved application library references, defined in weblogic-application.xml: [Extension-Name: oracle.webcenter.framework, Specification-Version: 11.1.1, exact-match: false], [Extension-Name: oracle.webcenter.skin, Specification-Version: 11.1.1, exact-match: false], [Extension-Name: oracle.sdp.client, exact-match: false], [Extension-Name: oracle.soa.workflow.wc, exact-match: false].
     at weblogic.application.internal.flow.CheckLibraryReferenceFlow.prepare(CheckLibraryReferenceFlow.java:26)
     at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:613)
     at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:52)
     at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:184)
     at weblogic.application.internal.EarDeployment.prepare(EarDeployment.java:58)
     Truncated. see log file for complete stacktrace
>
<07 Mar 2013 9:17:19 AM> <Warning> <Deployer> <BEA-149004> <Failures were detected while initiating deploy task for application 'VulindlelaScreens'.> 
<07 Mar 2013 9:17:19 AM> <Warning> <Deployer> <BEA-149078> <Stack trace for message 149004
weblogic.management.DeploymentException: [J2EE:160149]Error while processing library references. Unresolved application library references, defined in weblogic-application.xml: [Extension-Name: oracle.webcenter.framework, Specification-Version: 11.1.1, exact-match: false], [Extension-Name: oracle.webcenter.skin, Specification-Version: 11.1.1, exact-match: false], [Extension-Name: oracle.sdp.client, exact-match: false], [Extension-Name: oracle.soa.workflow.wc, exact-match: false].
     at weblogic.application.internal.flow.CheckLibraryReferenceFlow.prepare(CheckLibraryReferenceFlow.java:26)
     at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:613)
     at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:52)
     at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:184)
     at weblogic.application.internal.EarDeployment.prepare(EarDeployment.java:58)
     Truncated. see log file for complete stacktrace
>
[09:17:19 AM] ####  Deployment incomplete.  ####
[09:17:19 AM] Remote deployment failed (oracle.jdevimpl.deploy.common.Jsr88RemoteDeployer)
#### Cannot run application VulindlelaScreens due to error deploying to IntegratedWebLogicServer.
[Application VulindlelaScreens stopped and undeployed from Server Instance IntegratedWebLogicServer]
Resolution

- Click on 'Lock & Edit'
- Login to stand alone weblogic server where you are trying to deploy
- Select Deployments
- Click on 'adf.oracle.domain' library ( Select whatever the library it says missing in deployment error log) in summary of Deployments
- Click on 'Targets'
- Ensure selected library is associated to target server/cluster , If not select the check box corresponding to target cluster/managed server
- Save changes
- Click on 'Activiate Changes'
- You are all set now.




Tuesday, September 17, 2013

How to design layout templates in ADF ?

This blog explains about creating custom layout template and extending this layout in an ADF application.

What is template ?

A template in WebCenter (or an ADF application) is nothing more than a JSPX page with additional tags to define some regions. This means that you can use all the existing ADF or WebCenter components in your template.

This is very very common requirement in most of the ADF applications, It brings unique look and feel through out the application. In this example, I will be designing a template with two sections header and body. Header section contains company logo, title and logged in user info, Whereas body section holds the place holder for implementing pages to supply the necessary content to the template

- Right click on ViewController project, Choose new 'JSF Page Template' as shown below

- Give the proper name to the template , Choose the quick start template ( This is optional, You can have your own layout as well)
- Attributes - This section allows to define place holders for various attributes can be used such as 'title' , title can be different for each page , So that implementation page will supply required title to the template page. Below screenshot shows how to define attributes while creating template itself.



 - FacetDefinition - This section allows the implementation page to supply the content of the page to the template, I defined 'content' facet in my template, so that implementation page will supply the content to the template using this facet.

- After defining 'FacetDefinitions' and 'Attributes' in template, then below screenshot shows how to use them in template
- In this example, 'uploadFlag' attribute used in <af:form> element as shown below
- 'title' attribute used to display the title of the page.
- 'content' facet used in 'center' facet.

- Next step is to create implementation page, Create a jspx page and extend to newly created template as highlighted below.

- Supply values for 'title' and 'uploadFlag' attributes which are defined in template as shown below

- Define the content in 'content' facet as shown below

- Below is how output looks like.


Thursday, September 12, 2013

How to Set Default value to SelectOneChoice component in ADF

This blog explains about setting default value as first item in the <af:selectOneChoice>. This is very very common requirement in day to day development activity using Oracle ADF.

-  Define List of Values to the attribute as shown below, In this example I have created 'List of Values' for 'EmpName' attribute using 'CustomerROVO' as shown below screenshot.


- Define 'Groovy Expression' to 'Value' attribute to get the specific default value as shown below. Refer to How to Use Groovy Expressions to know more about usage of Groovy expressions. This groovy expression invokes Application Module Impl method and retrieves the required default value.


- Below is code snippet, Get First row in 'CountryROVO' , and returns the 'CountryName' as shown below

- Below is code how it looks like when you bind 'EmpName' attribute on to page as <af:selectOneChoice>

- You are done, Run the page and you would see default value as shown as below

Approach 2

Use below groovy expression as shown below.
-  RegionsLOVVA.first()?.LookupCode , RegionsLOVVA is the view accesor for the Region Field. LookupCode is the short code which sets to this field.



Monday, September 9, 2013

weblogic.common.ResourceException: No credential mapper entry found for password Error while deploying ADF application



If you notice below error message while deploying Custom ADF application to stand alone weblogic server,

[01:53:25 PM] Weblogic Server Exception: weblogic.application.ModuleException: 
[01:53:25 PM] Caused by: weblogic.common.ResourceException: java.security.PrivilegedActionException: weblogic.common.ResourceException: java.security.PrivilegedActionException: weblogic.common.ResourceException: No credential mapper entry found for password indirection user=System for data source FMADF
[01:53:25 PM]   See server logs or server console for more details



Follow the below steps

Launch Application Properties window, then unchecked  'Auto Generate and Synchronize Weblogic JDBC DEscriptors during Deployment"  option as shown in below screenshot.




Friday, September 6, 2013

How to Programatically Authenticate in ADF ? Integrating ADF with Oracle EBS

This blog explains about authenticating user programatically

Scenario : Integrating ADF Application with Oracle Apps (EBS) forms. User logged into Oracle Apps EBS , Providing a link in EBS forms to access to ADF Application. When user clicks on a link , Redirect to ADF application and use EBS Authentication login credentials to programatically authenticate ADF application, So that user will not be prompted for Login page again for ADF application.

- Crate Custom Filter (AuthFilter), Override doFilter() method as shown in below. This method will be invoked every time before screen loaded. We can customize this method not to perform the way how ever we want.


       
import java.io.IOException;

import java.util.HashSet;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import weblogic.security.URLCallbackHandler;
import weblogic.security.services.Authentication;
  /**
     * Override doFilter()
     * Retrieve UserID and Password from Session
     *  Authenticate the user and return credentials using the default realm.
     * Sets Current Thread Identity & Session Identity
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
        throws IOException, ServletException
    {
        if ( request instanceof HttpServletRequest )
        {
            HttpServletRequest httpRequest = ( HttpServletRequest )request;
            HttpSession session = httpRequest.getSession();
            //Assume you get userName & Password from HttpSession object.
            String username = ( String )session.getAttribute( SESSION_ATTR_USER );
            String password = ( String )session.getAttribute( SESSION_ATTR_PASSWORD );
            if (username != null && password != null)
            {
                byte[] pw = password.getBytes();
                Subject subject = null;
                try
                { 
                    // Prepare Security Context
                    subject = Authentication.login(new URLCallbackHandler(username, pw));
                    weblogic.servlet.security.ServletAuthentication.runAs(subject, httpRequest);
                } catch ( LoginException e )
                {
                    e.printStackTrace();
                }
            }
        }
        chain.doFilter( request, response );
    }
       
 

- Configure Above AuthFilter in web.xml as shown below


- Below Jspx (index.jspx) is not secured, By launching this page application will not perform for any login credentials.



- Below Jspx (DashBoard.jspx) is secured, By clicking on 'Go to Secure Page' hyper link on above page, I am programatically populating userName & password to HttpSession object & Authenticating in doFilter() method as shown below, This is going to skip the 'Login Page' and directly goes to secured page.


Thursday, September 5, 2013

How to upload and download file using ADF?


This blog explains about uploading and downloading any type of file as a BlobDomain data type into Database and retrieves in the same format.

- Ensure 'usesUpload=true'  in main .jspx page
- Develop a page/page fragment which accepts File as shown below

- Below is the code snippet for 'Download' button


- This is how screen looks like, User will upload file by clicking on 'Choose File', By clicking on 'Save' button Uploaded file will be saved into database

- Define below method in Page, and this will be invoked by clicking on 'Save Uploaded File' button on page.
       

     * This method invoked by clicking on 'SaveFile' Button,
     * Sets the uploaded file info to DTO and invoke App Module Impl to save into Database
     * @param actionEvent
     */
    public void saveUploadedFile(ActionEvent actionEvent) {
        BindingContainer bc = BindingContext.getCurrent().getCurrentBindingsEntry();
        OperationBinding ob = bc.getOperationBinding("saveUploadedFile");
        FileUtilDTO dto = new FileUtilDTO();
        dto.setContentType(contentType);
        dto.setFileContent(content);
        dto.setFileName(fileName);
        ob.getParamsMap().put("dto", dto);
        ob.execute();
    }
       
 

- This method converts uploaded File into BlobDomain data type and sets to class level variables.

       

      /**
     * This method invoked whenever user uploads file
     * @param valueChangeEvent
     */
    public void onFileUpload(ValueChangeEvent valueChangeEvent) {
        // The event give access to an Uploade dFile which contains data about the file and its content
        UploadedFile file = (UploadedFile)valueChangeEvent.getNewValue();
        // Get the original file name
        fileName = file.getFilename();
        // get the mime type
        contentType =
            file.getContentType(); 
        content = createBlobDomain(file);
    }
       
 

- This method converts UploadedFile into BlobDomain data type.
       

          /**
     * This method converts uploadedFile object
     * into BlobDomain datatype
     * @param file
     * @return
     */
    private BlobDomain createBlobDomain(UploadedFile file) {
        // init the internal variables
        InputStream in = null;
        BlobDomain blobDomain = null;
        OutputStream out = null;
        try {
            // Get the input stream representing the data from the client
            in = file.getInputStream();
            // create the BlobDomain datatype to store the data in the db
            blobDomain = new BlobDomain();
            // get the outputStream for hte BlobDomain
            out = blobDomain.getBinaryOutputStream();
            // copy the input stream into the output stream
            /*
             * IOUtils is a class from the Apache Commons IO Package (http://www.apache.org/)
             * Here version 2.0.1 is used
             * please download it directly from http://projects.apache.org/projects/commons_io.html
             */
            IOUtils.copy(in, out);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.fillInStackTrace();
        }

        // return the filled BlobDomain
        return blobDomain;
    }
       
 

- This method invoked by clicking on 'Download' button on <af:table> component for a selected Row, Gets the selected Row, corresponding BlobDomain and converts it into OutputStream based on selected file content type
       

            /**
     * This method prepares BlobDomain data to OutputStream
     * based on Content Type
     * @param facesContext
     * @param outputStream
     */
    public void downloadImage(FacesContext facesContext,
                              OutputStream outputStream) {
        UIXTable empTable = getFileContentTable();
        // Get the Selected Row Data
        FacesCtrlHierNodeBinding rowdata =
            (FacesCtrlHierNodeBinding)empTable.getRowData(empTable.getRowIndex());
        FileUploadDownloadROVORowImpl selectedRow =
            (FileUploadDownloadROVORowImpl)rowdata.getRow();
        // the value is a BlobDomain data type
        BlobDomain blob = selectedRow.getDocumentcontent();

        try {
            // copy hte data from the BlobDomain to the output stream
            IOUtils.copy(blob.getInputStream(), outputStream);
            // cloase the blob to release the recources
            blob.closeInputStream();
            // flush the outout stream
            outputStream.flush();
        } catch (IOException e) {
            // handle errors
            e.printStackTrace();
            FacesMessage msg =
                new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),
                                 "");
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    }
       
 

This method defined in AMImpl class, Invoke whenever user  clicks on 'Save' button after uploading, This method persists the file related information into database.

       

               /**
     * This method creates new row and set the file related info
     * commits to database.
     * @param dto
     * @return
     */
    public boolean saveUploadedFile(FileUtilDTO dto){
        TRPRO_TEST_FILEUPLOADVOImpl vo = getTRPRO_TEST_FILEUPLOADVO1();
        TRPRO_TEST_FILEUPLOADVORowImpl row = (TRPRO_TEST_FILEUPLOADVORowImpl)vo.createRow();
        row.setContenttype(dto.getContentType());
        row.setDocumentcontent((BlobDomain)dto.getFileContent());
        row.setDocname(dto.getFileName());
        vo.insertRow(row);
        getDBTransaction().commit();
        return true;
    }
       
 




Wednesday, September 4, 2013

How to configure javax.servlet.Filter in ADF Fusion application

This blog explains about configuring a Filter in ADF Fusion application

- Create a Java class which implements Filter class as shown below, override doFilter() method.


- Configure the newly created Filter class in web.xml as shown below

- Run your page, and you will see doFilter() method will invoked every time when page loaded.

Tuesday, September 3, 2013

How to apply Security at Entity level in ADF Application

This blog outlines about applying security at entity level,For eg : Admin should able to perform Create/Update/Delete/Read whereas User Role should only read the data and can't perform any other operation.

We can achieve this by applying security & authorization at entity level as shown below

- Select the Entity in Project, Open the structure view, Right click on Entity in Structure window, Choose Security , Select 'Update' operation as shown below


- Open Jazn.xml, Select the Entity, Select the Role for which you want to grant 'Update' access, select as shown below

- Launch the page by logging in using Admin Role, Below is how screen looks like, Here user can able to update existing data.

- Launch the page by logging in using 'User' Role, Below is how screen looks like, Here user can only view data and can't perform any updates.



How to redirect to external application Jspx page


This blog explains about redirecting or loading Jsp(Java Server Pages) file part of external application

Develop test.jsp page , include response.sendRedirect() by passing the respective jspx url as shown below, Whenever test.jsp page launched, it will redirect the request to welcome.jspx which is running in different environment.

  <body>
    <%
  response.sendRedirect("http://dbsoax2.atd-us.icd:8002/tproui/faces/welcome.jspx");
  %>
  </body>