Wednesday, September 28, 2011

Get value from task flow using Contextual Event


Often a page or a region within a page needs information from somewhere else on the page or from a different region. Among the options for passing information to and from regions, Contextual Events is the most powerful and the option that does not make regions refresh or require the referenced bounded task flow to restart.

Contextual events have two parts:
  • A publisher (or producer), such as a button that raises a named event, with or without a custom payload.
  • A handler (or consumer) that listens for a specifically named event or a wildcard event, to process that event.
Create a Contextual Event:

  • Create a bounded task flow with page fragment and create a view inside it. Create a view object and place it as a tree table or tree in page.
  • To create a contextual event just select the tree and go to its properties. There go under the option publish event and click on add button to create a contextual event. Select create new event and press ok, this will create a contextual event. Here event type will be currency change event.
Get Contextual Event:
  • Create a adf jar file of this application. Add this library to a new application where you will use the task flow as a region.
  • Create a page and put a input text on it, give its value from a bean class.
public class NewBean {
    private RichOutputText newtext;
    String MyValue=null;

    public NewBean() {
    }

    public void setNewtext(RichOutputText newtext) {
        this.newtext = newtext;
    }

    public RichOutputText getNewtext() {
        return newtext;
    }

    public void setMyValue(String MyValue) {
        this.MyValue = MyValue;
    }

    public String getMyValue() {
        return MyValue;
    }
}
  • Now create a event handler class which will act as a consumer of event generated by a producer. In it create a function which will get the value from producer event. This function will take a parameter of currency change event type which is produce by the tree node selection event.
public class EventHandler  {
    public EventHandler() {
        super();
    }
   
    public void handleEventStringPayload(DCBindingContainerCurrencyChangeEvent customPayLoad) {

        this.setNewValue(customPayLoad.getSource().toString());
        FacesContext fctx = FacesContext.getCurrentInstance();
        ELContext elctx = fctx.getELContext();
        ExpressionFactory exprFactory = fctx.getApplication().getExpressionFactory();
        ValueExpression ve = exprFactory.createValueExpression(elctx, "#{NewBean}", Object.class);
        NewBean pageBean = (NewBean)ve.getValue(elctx);
        pageBean.setMyValue(customPayLoad.getSource().toString());
        AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
        adfFacesContext.getCurrentInstance().addPartialTarget(pageBean.getNewtext());

    }
  • To make this function available at the binding level, create this java class' data control. To do this right click on this java class and go to create data control. Select all 3 option if you are using release 2 of jdeveloper.
  • Now go to page , drag and drop task flow from library and make it a region or dynamic region. By this event will also be available in this page. Go to binding section of page and add new method binding to it. Add method from data control to it. By this, method can be accessed from this page.
  • Again go to binding tab of page and open contextual event tab. In this tab go to subscriber tab and click on add button. This will pop up a window. Click on the search button it will show available events in this page. Select previously defined event in task flow's page.
  • select the publisher or keep it any. Now go to handler option and click search button it will show available functions in bindings. Select the function created for event handling. Go to last part of subscriber parameter. Give parameter name same given in event handler function. Its value will be ${payLoad}.
  • Now run application it will show selected tree value in output box which is outside the region.

Tuesday, August 23, 2011

UNSAVED DATA WARNING


Introduction :

If You are working on a form or table and some of data is modified or added, on moving to other page of taskflow this data will remain in cache or it will show no warning for unsaved data


How to do it :

To show warning of unsaved data between page navigation just go to property of af:document and set Uncommitted data warning to true. Then whenever you move out of that page or close the browser it will show you a warning of unsaved data. 

Warning message
Warning Message

SHOW UNSAVED ROW HIGHLIGHTED


Introduction :
This post to describe how to show a unsaved row of a table. There is a property of an entity which is entity state. This entity can be in 4 states:
  1. New
  2. Modified
  3. Unmodified
  4. Initialized

How to do it :
just copy the following code and paste in to inline style of column of table. This will highlight newly created row.

#{row.row.entities[0].entityState == 0? 'background-color:#ff9c31;':''}

To highlight modified row compare entity state to 2

0 for new unsaved row
1 for unmodified row
2 for modified unsaved row
-1 for initialized row

for showing unsaved rows whether modified or a new place both condition together. 

#{row.row.entities[0].entityState == 2||row.row.entities[0].entityState == 0?'background-color:#ff9c31;':''}




Thursday, August 4, 2011

CUSTOM VALIDATOR


In my last post I included information about different validations available in ADF-BC. These validations are very easy to apply in Entity object and view objects. There are most of the possible validations are available. Still you may want to define your own custom validation, for this you will write code in your managed bean. 
To apply a custom validator go to your jspx or jsff page and select the input text or other input component an go to its properties. Give a function name to validator.

 
This validator will look like :
public void NameValidation(FacesContext facesContext, UIComponent uIComponent, Object object) {

return true:

}


Now in this validator method you can write your own validation code. Such as I have written here validation of name input text, so that user can only insert capital letters, numbers and “_”. If validation fails it will show a error, else nothing.
public void NameValidation(FacesContext facesContext, UIComponent uIComponent, Object object) {
        String value = (String)object;
        if ((value == null) || value.length() == 0) {
            return;
        }
        String expression = "^[A-Z 0-9_]{2,100}$";
        CharSequence inputStr = value;
        Pattern pattern = Pattern.compile(expression);
        Matcher matcher = pattern.matcher(inputStr);
        String error = “Only upper case letter and _ allowd”;
        if (matcher.matches()) {
        } 
else {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, error, null));
        }
    }

When you run application and validation fails you will get an error like this:

Monday, August 1, 2011

ADF-BC Validations


This framework provides very good feature of validation. In ADF we can validate user inputs at different levels. Which are
  • Attribute level: Fires on value change.
  • Entity level: Fires on moving from one record to another.
  • Transaction level: Fires after attribute and entity level validations are complete. It validates Master-detail validations.
These validations are defined in Entity object and View object level. There are many rules of possible validations and ADF-BC provide lots of them. These validations rules are:
  • Compare: Attribute value compared with other attribute's value or an expression or a literal.
  • List: Value is validated against a list of values.
  • Key Exists: Its like a foreign key validator, it checks the value whether it exists or not. Like value for employee will check for the department to check whether it is present or not.
  • Regular Expressions: Value compared against provided regular expression. Like for email validation, Number Format validation.
  • Script Expression: Groovy expression are used to do validations.
  • Method Validator: When a method validator is created it adds a method in corresponding entityImpl calss. Like
public boolean validateEname(String ename) {  
return true;
}

Friday, July 29, 2011

ADF page refresh using java code


This post will show the code for a full page refresh. Most of the time Partial page rendering do the work, still we need a full page refresh. For this easy way is to call a java method and refresh the page. This is needed when there is a change in database values and you want to refresh the form and table after operation. 

So use following code for this:
public void refresh() {
      FacesContext facesContext = FacesContext.getCurrentInstance();
      String refreshpage = facesContext.getViewRoot().getViewId();
 ViewHandler  viewHandler =
facesContext.getApplication().getViewHandler();
      UIViewRoot viewroot =  viewHandler.createView( facesContext, refreshpage);
viewroot.setViewId(refreshpage);
facesContext.setViewRoot(viewroot);
}

Thursday, July 7, 2011

Generate a XML file for a view object

There is a need of generating a xml file from a view object. This is a very easy process as there is a method of view object class “writeXml” to write the content of view object to a xml format.

  1. First generate Impl class for application module.
  2. Write following code to create an object of view object, and generate xml content. Then write this generated xml to a file using output stream.
public String printXml() {

        Connection conn;
        FileOutputStream out;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            AppModuleImpl am = (AppModuleImpl)resolvEl("AppModuleDataControl");
            conn = am.getDBTransaction().createStatement(0).getConnection();
            ViewObject vo = am.findViewObject("EmployeeView");
            ((XMLNode)vo.writeXML(4, XMLInterface.XML_OPT_ALL_ROWS)).print(outputStream);
            System.out.println(outputStream);
            out = new FileOutputStream("F://Employee.xml");
            PrintStream p = new PrintStream(out);
            p.println(outputStream);
            p.close();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }

  public Object resolvEl(String data){
    FacesContext fc = FacesContext.getCurrentInstance();
    Application app = fc.getApplication();
    ExpressionFactory elFactory = app.getExpressionFactory();
    ELContext elContext = fc.getELContext();
    ValueExpression valueExp = elFactory.createValueExpression(elContext, "#{data."+data+".dataProvider}", Object.class);
   return valueExp.getValue(elContext);
  }

Friday, July 1, 2011

Use database table for authentication in adf security


To use sql authenticator in weblogic server security realm, read following blog post:  SQLAuthenticator

Now go to application and apply adf security. You do not need to modify the role mapping in weblogic.xml. The default is perfectly fine:


  
    valid-users
    users
  
 
For each group in your SQLAuthenticator provider in weblogic console, create an equivalent application role in jazn.xml, and recreate those roles in the Enterprise Roles in jazn.xml. In jazn,xml make enterprise role as member of the appropriate application role. There is no need to create user in jazn.xml file. Crating role will do the work.

Tuesday, June 21, 2011

Refresh Resource Bundle


  • Resource bundle can not be refreshed using ResourceBundle class. using following code do not clear the cache.
Class type = ResourceBundle.class;
Field cacheList = type.getDeclaredField("cacheList");
cacheList.setAccessible(true);
((Map)cacheList.get(ResourceBundle.class)).clear();
  • If you want to refresh resource bundle of your application you should need to use Resource bundle manager instead of Resource bundle class.
ResourceBundleManagerRT rt = (ResourceBundleManagerRT)ResourceBundleManagerRT.getResourceBundleManager();
 rt.flush();

Monday, June 20, 2011

Use external XML file for Resource Bundle


  • Create list resource bundle file for default and supported locale. And read label value from xml file.
  • This approach gives a facility to change label or message value, without compilation and redeployment of application.
  • To do this first crate a xml file containing key and value pair, so that you can use label according to their key.


 
 
 

  • This method also give an option to use single file for different application, which are used as a library.
  • Here you can write code to read xml file and assign key value pair to an object of resource bundle class.
public class MyResources extends ListResourceBundle {

    public MyResources() {
        super();
    }
  
  private static final Object[][] contents =
    { { "", "" }, { "", "" }, { "", "" } };

    protected Object[][] getContents() {
        try {
            File file = new File("C:\\Users\\admin\\Desktop\\locale\\Resource.xml");
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();
            NodeList nList = doc.getElementsByTagName("label");

            for (int temp = 0; temp < nList.getLength(); temp++) {

                Node nNode = nList.item(temp);
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                    Element eElement = (Element)nNode;

                    contents[temp][0] = getTagValue("key", eElement);
                    contents[temp][1] = getTagValue("value", eElement);

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

    private static String getTagValue(String sTag, Element eElement) {
        NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
        Node nValue = (Node)nlList.item(0);

        return nValue.getNodeValue();
    }

}

Friday, June 10, 2011

Jdeveloper 11g release 2 , with lots of new features


Oracle released a new version of Jdeveloper 11g, containing lots off new features and even rapid development of application. These new features take jdeveloper to another level and now can be compared with other J2EE IDE such as java bean and eclipse.


Main features of new jdeveloper are:

  • Hot deployment: There is no need now to run application after any change in application files. Now just save the changed file and refresh the page.
  • Skin Editor: This new editor for skin is very use full to create css for application. It made it easy to select different properties of a component and change their attributes.

You can also get installation guides for this new release and for new skin editor in this link : http://www.oracle.com/technetwork/developer-tools/jdev/documentation/index.html

Check for the related documents: http://download.oracle.com/docs/cd/E16162_01/index.htm

Wednesday, June 1, 2011

Call Jasper report using a link

In previous post jasper report is called with the help of java bean. Now we can use a link to call report as in previous method calling report from a .jsff page gives error.

To call report using link follow following steps: 

  • Add a go link to page which will call servlet and also pass parameters.
  • Add a command button to assign value to parameters.
  • Add value in destination like “/jasperservlet?deptno=#{bindings.DepartmentId1.inputValue}&reporttype=#{bindings.Filetype1.inputValue}”.
  • Here deptno and reporttype are parameters passed from url and will be used in servlet.
  • To get parameter value in servlet use following code.
Integer code = Integer.valueOf(request.getParameter("deptno"));
String reporttype = request.getParameter("reporttype");

Thursday, May 26, 2011

Jasper report in ADF aaplication

This post is to create an application which will use to generate Jasper report as created with the help of iReport tool.
Next are the steps of creating that needed application.
  • In application create entity object, view object and application module use to database table employees and departments from HR user.
  • Go to employee view object and create List of values for department id. Create a transient attribute for file types in which report will be generated.
  • So create a list of values in this attribute and take static values from a static view object like pdf, xls, csv etc.
  • Before creating any page or java class, Jasper report related libraries should be imported in jdeveloper so that jasper related java classes can be used.
    • commons-beanutils-1.8.3.jar
    • commons-collections-3.2.1.jar
    • commons-digester-2.1.jar
    • commons-logging-1.1.1.jar
    • iText-2.1.7.jar
    • jasperreports-4.0.1.jar
    • jfreechart-1.0.13.jar
    • poi-3.7-20101029.jar
  • Now create a page to select report output file type and to pass the parameter to jasper report. Add both list of values to page for run time selection.









  • When user will select the values for department and file type and run the report, these values will be passed to servlet from java class. To get selected values in java class lov should be changed. Add a for each element in select one choice and get item value from this.
  • Bind these both list to bean class so that selected values will be passed to servlet.
  • Now create a servlet for request and response for report. For this go to new, select servlet from category and http servlet from items, click ok.
  • Give servlet name, its package, type to html, and select doget and doPost methods. Click next. 
  • Now it will show created servlet on editor . Write code for jasper report in this servlet.
  • Write code in one of the method doGet() or doPost().
  • public void doPost(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
    
    response.setContentType(CONTENT_TYPE);
  • Create a connection so that report will use this connection to get data from database.
try{ 
PreparedStatement st = null;

String amDef = "jasper.model.module.AppModuleAM";
String config = "AppModuleAMLocal";
AppModuleAMImpl am =
(AppModuleAMImpl)Configuration.createRootApplicationModule(amDef,
config);    
st = am.getDBTransaction().createPreparedStatement("select 1 from dual", 0);
Connection conn = st.getConnection();
  • Place jrxml file in public-html folder of application so that it will pick file from server location . To get this file input stream is created .
InputStream input = new FileInputStream(new File(getServletConfig().getServletContext()
.getRealPath("/reports/parReport.jrxml")));

JasperDesign design = JRXmlLoader.load(input);
JasperReport report = JasperCompileManager.compileReport(design); 
  • Now get Attributes which are set at the time of servlet calling.
Integer code = (Integer)request.getAttribute("deptno");
String reporttype = (String)request.getAttribute("reporttype");
  • Set value for parameter of report. If you have more than one parameter in your report, then you have to call the put method for each parameter.
Map parameters = new HashMap();
parameters.put("DeptNo", code);
JasperPrint jasperPrint=JasperFillManager.fillReport(report, parameters, conn);
  • Now create a output stream to send file to client. Then Check file type and export file to client in right format.
OutputStream ouputStream = response.getOutputStream();
JRExporter exporter = null;

if( "pdf".equalsIgnoreCase(reporttype) )
{
response.setContentType("application/pdf");

response.setHeader("Content-Disposition", "attachement; filename=\"file.pdf\"");


exporter = new JRPdfExporter();

exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
}
else if( "rtf".equalsIgnoreCase(reporttype) )
{
response.setContentType("application/rtf");
response.setHeader("Pragma", "no-cache");
response.setHeader("Content-Disposition", "attachement; filename=\"file.rtf\"");

exporter = new JRRtfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
}
else if( "html".equalsIgnoreCase(reporttype) )
{
exporter = new JRHtmlExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
}
else if( "xls".equalsIgnoreCase(reporttype) )
{
response.setContentType("application/xls");
response.setHeader("Content-Disposition", "attachement; filename=\"file.xls\"");

exporter = new JRXlsExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
}
else if( "csv".equalsIgnoreCase(reporttype) )
{
response.setContentType("application/csv");
response.setHeader("Content-Disposition", "attachement; filename=\"file.csv\"");

exporter = new JRCsvExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
}

try
{
exporter.exportReport();
}
catch (JRException e)
{
throw new ServletException(e);
}
finally
{
if (ouputStream != null)
{
try
{
ouputStream.flush(); 
ouputStream.close();

}
catch (IOException ex)
{
System.out.println(ex.getMessage());
throw (ex);
}
}
}

}catch(Exception ex) {
ex.printStackTrace();
}
  • After writing servlet we have to call this servlet and pass dynamic values from page to servlet. For this write a function and call this function from a button on page.
  • To send request to servlet we will use http request and response cycle. In request we will set attributes, which we will need in servlet to pass to jasper report and to print report according to its format.
public void callServlet(ActionEvent actionEvent) throws Exception  {
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest)ctx.getExternalContext().getRequest();
HttpServletResponse response =(HttpServletResponse) ctx.getExternalContext().getResponse();

request.setAttribute("deptno", deList.getValue());
request.setAttribute("reporttype", fileTypeList.getValue());

request.getRequestDispatcher(response.encodeURL("/jasperservlet")).forward(request, response);   

response.flushBuffer();  
ctx.responseComplete();    

}