Wednesday, August 19, 2009

Oracle ADF, dust under the carpet

Jdeveloper version usedin this post is:=10.1.3
When you create a component in ADF , whether its Entity object or a view object in the model layer, or drag and drop view object on the jsf page, there are many xml files and other files which are created by Jdeveloper. And developers gets crazy as, why so many files are created and what are they for. Specially beginners/ADF newbies gets confused with so many xml files which getting created, and that gives them one reason to run way from learning ADF. In this post I will try to explain these xml and other files which you should know as a developer when you do development using ADF.

When you create an application in Jdeveloper with “JSF , ADF BC” as template, two project gets created “Model” and “ViewController”. And a file
1) .jws which is used for storing the projects added in the workspace(check your workspace on disk).

Under the Model and ViewController projects two files gets created as “Model.jpr” and “ViewController.jpr”.
2) .jpr file is used to store the project related information like java files created in the project etc.

Once you start creating the Entity or View object under the Model, one more file gets created under the Model/src/Model.jpx.
3) Model.jpx file contains all the application modules defined in your Model project. And other configuration details such as database connection used in model layer. Some times during development, if you get “JBO 30003” or database error, then check the “_NamedConnection” parameter in the same file, if it is pointing to the correct database connection name.
Entity object is the Java object representation of the database table row from which it is created. Once your create an Entity object(say EmpEO), two files which gets created.
4)EntityName.xml (for EmpEO, it is EmpEO.xml):- This file contains the name of the database table from which the entity object is created, name and data type of each attribute in eneity object, and the corresponding column to which that attribute represents. For example in the following figure, attribute “EmployeeId” is driven from the column name “Employee_ID”, with type as number and other attributes such as primary key etc:-

5) EntityNameImpl.java(for EmpEO, it is EmpEoImpl.java):- though it is not required to generate this file, as default option it is created. It has getter and setter methods for the entity object attributes. This file can be used to add custom code, such as in the setter method of commission of the employee, commission can be first calculated based on the employee salary, hire date or other conditions.

View object fetch the result set from the database based on the query on which it is based. Once you create view object whether entity based or read only,two files are created:-
6) ViewObjectName.xml(for EmpVO, it is EmpVO.xml):-which specifies the entity object on which this view object is dependent, query of the view object which will fetch the desired resultset and the attributes which are there in view object.View object is created at run time based on this .xml file.
7)ViewObjectNameImpl.java(For EmpVO, it is EmpVOImpl.java):- When ever you create a new row in the view object, and you want to provide some custom behavior when a new row is created, you can overwrite create() method in same class. Similarly remove() and other methods.

An Application module which acts a container for view objects and take care of transaction handling. When you create an application module, two files are create:-
8) ApplicationModuleName .xml(for EmpAM, its EmpAM.xml):- It has name of the application module, the application module class path, and all view objects which are added in the application module. This information is used to create the view objects at runtime.
9)ApplicationModuleName Impl.java(For EmpAM, its EmpAMImpl.java):- In this java class you will write methods like:-
→ iterating two or more view objects result set added in same application module to perform some business logic.
→ calling a pl/sql code.
→ writing a method and later on exposing it by adding it in client interface, so that it can be called from view layer.
10) Bc4j.xcfg:- it has different configuration properties of the application module, as such , the name of the database connection, type of DB connection etc.

Once you create your jspx page with drag and drop any view object from data control palette, page definition file and DataBindings.cpx file gets created.
11) DataBindings.cpx:- This file is created for the first time and only once when you drag and drop any view object or method from data control palette to the jspx page. This page contains information about page definition file corresponding to your jspx page, the data controls used by your application. Ya ya, I know you are now thinking of what is data control and data bindings. Thats actually what I am thinking of my next blog post topic :). Check the following figure, it shows the contents of the DataBindings.cpx file, when I drag and dropped the EmpVO from the data control palette to ViewEmpDetails.jspx page as ADF read only table. It shows how ViewEmpDetails.jspx file is linked to its page definition file ViewEmpDetailsPageDef.xml:-


Created DataBindings.cpx file is created under the view controller project → Application Sources → view .
12) PageDef.xml(for ViewEmpDetails.jspx, its ViewEmpDetailsPageDef.xml):- Page definition file created for each jspx page,when you drop a particular component from data control palette to your jspx page. This is the file which actually wries your UI components to the corresponding attributes in the view object. This file mainly contains following elements(tags):-
12.1 ) executables:- which defines various result sets(specified as iterator tag) to be executed when the page is loaded. Or defines the methods exposed from application module in client tier(specified as methodIterator tag) to be executed.
12.2) bindings:- it specifies the attributes which will be contained in the result set pointed by the iterator tag. Or the details of method to be executed pointed by the methodIterator tag.
Check the following figure, in which iterator EmpVO1Iterator specifies the employee details to be fetched when page is loaded. And under bindings it specifies all attributes which will be available in the result set to be shown in UI.
If you check the source of the ViewEmpDetails.jspx page, it will be clear to you that how it is wired to the elements present in the page definition.

And at last two files which are created by Jdeveloper itself under web-inf folder in ViewController project once you have create an application with “JSF , ADF BC” as template are:-
13)faces-config.xml:- which acts as a controller by storing the navigations rules. And in addition to that it stores the configuration details about managed beans.
14)Web.xml :- which is the standard j2ee deployment description file and provide application level configuration details.



Thursday, July 9, 2009

Oracle ADF – I am beginner, from where I can start

There are many fellow developers who are just entering into the world of ADF and Jdeveloper. They do struggle a bit as from where to start from in ADF. Regardless of whether you are starting up with ADF 11g or 10g, in this post I will try to explain what all is required to start with Oracle ADF.
As ADF is a J2EE application framework, you first have to learn Java and OOB concepts. Though the in depth knowledge of Java is not required, nor are the advance concepts like threads need to be skilled, but you do need basic java concepts like class, object, inheritance, wrapper classes etc. A good java book that can help you is “SCJP Sun Certified Programmer for Java” by Bert Bates, Kathy sierra or Head first Java by same authors. As every thing in the ADF is metadata driven, means objects are constructed are at run time using metadata which is stored in the form of XML. So you have to learn XML also. A good link to learn the same is at
http://www.w3schools.com/XML/xml_whatis.asp.
The if you are starting up with ADF 11g, then get the overview of the same at
http://www.oracle.com/technology/products/adf/pdf/ADF_11_overview.pdf or
If you are starting up with ADF 10g then at
http://www.oracle.com/technology/products/jdev/collateral/papers/1013/adf_10.1.3_overview.pdf .
After getting the overview, start with the step by step tutorial, for ADF 10g at
http://www.oracle.com/technology/obe/ADF_tutorial_1013/index.htm
And for ADF 11g at
http://kohlivikram.blogspot.com/2009/03/oracle-adf-11g-sample-application.html
Most of the times when we do the tutorial, we get carried away with the steps given in the tutorial and try to finish it as soon as possible, rather then concentrating on the concepts given in the steps, so go slow and don’t worry if you are not able to finish it up, start it once again when you get time, but do finish it. If you are not able to understand the concept given in tutorial, try to refer the same topic in the ADF developer guide. Read developer guide in your free time; go through blogs written by Frank, Andrejus, and Steve. List of good ADF blogs are given here:-
http://wiki.oracle.com/page/ADF+Blogs
One more very good article on how to start with ADF is here
In the coming post I will try to explain the ADF concepts components wise. Hope that I will get enough time :) for that.

Sunday, April 26, 2009

Generate PDF report in ADF

Example is developed in Jdeveloper 10g. In this example I am using employee table from the HR schema and generating the pdf report which contains the first name ,last name and email address of the employee. I am making use of the Apache FOP. I am using the FOP version.95.Lets start with example. Create the application workspace with model and viewController projects. Add the following jar files in the viewController(Right click the viewController-->Project Properties-->Libraries--> Add Library -->New) :-
-->avalon-framework-4.2.0.jar
-->batik-all-1.7.jar
-->commons-io-1.3.1.jar
->custComps.jar
-->fop.jar
-->serializer-2.7.0.jar
-->xercesImpl-2.7.1.jar
-->xml-apis-1.3.04.jar
-->xml-apis-ext-1.3.04.jar
-->xmlgraphics-commons-1.3.1.jar
Create a read only view object with name "EmpVO" based on the employee table based on query
"SELECT
EMPLOYEES.EMPLOYEE_ID EMPLOYEE_ID,
EMPLOYEES.FIRST_NAME FIRST_NAME,
EMPLOYEES.LAST_NAME LAST_NAME,
EMPLOYEES.EMAIL EMAIL,
EMPLOYEES.PHONE_NUMBER PHONE_NUMBER,
EMPLOYEES.HIRE_DATE HIRE_DATE,
EMPLOYEES.SALARY SALARY
FROM EMPLOYEES".
Create a application module AppModule and add the above created view object in that.
The most difficult part in creating reports using FOP is you have to create the xsl fo file which defines the layout/formatting in which the xml data will be displayed in the pdf file.For this example I have developed following .xsl file:-
-----------------------------------------------------

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" version="1.0" omit-xml-declaration="no"
indent="yes"/>
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4" page-width="297mm"
page-height="210mm" margin-top="0.5in"
margin-bottom="0.5in" margin-left="0.5in"
margin-right="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4">
<fo:flow flow-name="xsl-region-body">
<fo:table table-layout="fixed" border-width="1mm"
border-style="solid">
<fo:table-column column-width="45mm"/>
<fo:table-column column-width="45mm"/>
<fo:table-column column-width="60mm"/>
<fo:table-header text-align="center" background-color="silver">
<fo:table-row>
<fo:table-cell padding="1mm" border-width="1mm"
border-style="solid">
<fo:block font-weight="bold">First Name</fo:block>
</fo:table-cell>
<fo:table-cell padding="1mm" border-width="1mm"
border-style="solid">
<fo:block font-weight="bold">Last Name</fo:block>
</fo:table-cell>
<fo:table-cell padding="1mm" border-width="1mm"
border-style="solid">
<fo:block font-weight="bold">Email Address</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:for-each select="//EmpVORow">
<fo:table-row>
<fo:table-cell border-style="solid">
<fo:block>
<xsl:value-of select="FirstName"/>
</fo:block>
</fo:table-cell>
<fo:table-cell border-style="solid">
<fo:block>
<xsl:value-of select="LastName"/>
</fo:block>
</fo:table-cell>
<fo:table-cell border-style="solid">
<fo:block>
<xsl:value-of select="Email"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
-----------------------------------------------------
Now create a JSPX page with one command button on it, on clicking which you will generate the PDF file and a command link on clicking which you will get the generated pdf.
<af:commandButton text="Generate XML" action="#{GenPDFBean.commandButton_action}" />
<h:commandLink value="Download PDF" action="#{GenPDFBean.downloadPDF}" target="_blank" />

Create a managed bean with name GenPDFBean and add the following code in the created bean.

import com.sun.java.util.collections.HashMap;

import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;


import java.io.OutputStream;
import java.io.PrintWriter;

import java.util.Map;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import model.AppModuleImpl;

import model.EmpVOImpl;

import oracle.adf.model.BindingContext;
import oracle.adf.model.binding.DCDataControl;
import oracle.adf.model.binding.DCUtil;
import oracle.adf.view.faces.context.AdfFacesContext;

import oracle.binding.BindingContainer;
import oracle.binding.OperationBinding;

import oracle.jbo.ApplicationModule;
import oracle.jbo.XMLInterface;

import java.io.Closeable;

import oracle.xml.parser.v2.XMLNode;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;

import org.w3c.dom.Node;

public class GenPDFBean {
private BindingContainer bindings;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
AdfFacesContext context = AdfFacesContext.getCurrentInstance();
HttpServletRequest request =
(HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
BindingContext ctx = DCUtil.getBindingContext(request);
DCDataControl dc = ctx.findDataControl("AppModuleDataControl");
ApplicationModule service = (ApplicationModule)dc.getDataProvider();
ApplicationModule am = service.findApplicationModule("AppModule");
AppModuleImpl amImpl = (AppModuleImpl)am;
EmpVOImpl empVO = (EmpVOImpl)amImpl.findViewObject("EmpVO1");
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.

public GenPDFBean() {
}

public BindingContainer getBindings() {
return this.bindings;
}

public void setBindings(BindingContainer bindings) {
this.bindings = bindings;
}

public String commandButton_action() {
HashMap viewDefMap = new HashMap();
viewDefMap.put("model.EmpVO",
new String[] { "FirstName", "LastName", "Email" });
try {
//printXML(empVO.writeXML(-1,XMLInterface.XML_OPT_ALL_ROWS));
printXML(empVO.writeXML(XMLInterface.XML_OPT_ALL_ROWS,
viewDefMap));
generatePDF();
System.out.println("success");
} catch (IOException e) {
// TODO
}

return null;
}

private static void printXML(Node n) throws IOException {
//((XMLNode)n).print(System.out);
java.io.File file =
new java.io.File("C:/jdevstudio10133/jdev/mywork/FOP/ViewController/src/view/emp.xml");
//java.io.File file = new java.io.File("C:/Windows/Temp/emp.xml");
PrintWriter output = null;
try {
output = new java.io.PrintWriter(file);
((XMLNode)n).print(output);
} catch (IOException e) {
//throw new RuntimeException("IOExceptions will crash the application", e);
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (output != null) {
try {
output.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

}


public void generatePDF() {
try {
System.out.println("FOP ExampleXML2PDF\n");
System.out.println("Preparing...");

// Setup directories
File baseDir = new File(".");
File outDir = new File(baseDir, "out");
outDir.mkdirs();

// Setup input and output files
File xmlfile =
new File("C:/jdevstudio10133/jdev/mywork/FOP/ViewController/src/view/emp.xml");
File xsltfile =
new File("C:/jdevstudio10133/jdev/mywork/FOP/ViewController/src/view/emp.xsl");
File pdffile =
new File("C:/jdevstudio10133/jdev/mywork/FOP/ViewController/src/view/EmpResultXML2PDF.pdf");

System.out.println("Input: XML (" + xmlfile + ")");
System.out.println("Stylesheet: " + xsltfile);
System.out.println("Output: PDF (" + pdffile + ")");
System.out.println();
System.out.println("Transforming...");

// configure fopFactory as desired
FopFactory fopFactory = FopFactory.newInstance();

FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
// configure foUserAgent as desired

// Setup output
OutputStream out = new java.io.FileOutputStream(pdffile);
out = new java.io.BufferedOutputStream(out);

try {
// Construct fop with desired output format
Fop fop =
fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent,
out);

// Setup XSLT
//TransformerFactory factory = TransformerFactory.newInstance();
TransformerFactory factory = new TransformerFactoryImpl();
Transformer transformer =
factory.newTransformer(new StreamSource(xsltfile));

// Set the value of a in the stylesheet
transformer.setParameter("versionParam", "2.0");

// Setup input for XSLT transformation
Source src = new StreamSource(xmlfile);

// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());

// Start XSLT transformation and FOP processing
transformer.transform(src, res);
} finally {
out.close();
}

System.out.println("Success!");
} catch (Exception e) {
e.printStackTrace(System.err);
//System.exit(-1);
}
}

public void downloadPDF() throws IOException {

// Prepare.
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response =
(HttpServletResponse)externalContext.getResponse();

File file = new File(getFilePath(), getFileName());
BufferedInputStream input = null;
BufferedOutputStream output = null;

try {
// Open file.
input =
new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);

// Init servlet response.
response.reset();
response.setContentType("application/pdf");
response.setContentLength((int)file.length());
//String fileName="ab2123";
response.setHeader("Content-disposition",
"inline; filename=\"" + getFileName() + "\"");
output =
new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}

// Finalize task.
output.flush();
} finally {
// Gently close streams.
close((Closeable)output);
close((Closeable)input);
}

// Inform JSF that it doesn't need to handle response.
// This is very important, otherwise you will get the following exception in the logs:
// java.lang.IllegalStateException: Cannot forward after response has been committed.
facesContext.responseComplete();
}

private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
// Do your thing with the exception. Print it, log it or mail it. It may be useful to
// know that this will generally only be thrown when the client aborted the download.
e.printStackTrace();
}
}
}

private String getFilePath() {
return "C:\\jdevstudio10133\\jdev\\mywork\\FOP\\ViewController\\src\\view\\";
}

private String getFileName() {
return "EmpResultXML2PDF.pdf";
}

}

Tuesday, April 21, 2009

Unexpected null value for literal data

: ) my first post on web services. I faced this issue in Jdeveloper 10g.
Some times we developer’s faces an error during our developed, which irritates like anything. This will keep coming in office and in dreamsJ. For me the culprit was “unexpected null value for literal data”. You might be facing this error when you are sending request using web service proxy to server to perform some operation on the web service in question. This problem is not at the server side, but is thrown at the client side, when you are not setting the request fields to the web service.
Now the question is how you can identify that which fields are required for the web service. The answer is in the WSDL using which you have generated the web proxy. Open your WSDL and check against each element the value for the attribute minOccur. If it is equal to one, it means that element is mandatory. If minOccur is zero, it means is an optional element. And if minOccur attribute is missing, it will take the default value equal to “1” which means it’s mandatory.

If you have fairly large WSDL and its difficult to identify and set the values, just go ahead and change your WSDL with all elements attribute property minOccur set to “0”.

Sunday, March 8, 2009

Oracle ADF 11g Tutorial Application

ADF 11g is simply great. Though there are many documents provided my oracle for learning ADF 11g. But still I felt there are are need for more documents. So when I started learning ADF 11g, I decided to build the sample application and document it. And finally this weekend I got some time to finish up this document. Following is the link from where you can view/download the document.

http://www.scribd.com/doc/13088674/Oracle-ADF-11g-Learning-Application-My-Procurement-Application

And following is the link for the sample application which I developed. This also includes the SQL script required to install the database objects.

MyADFLearningApp.zip

Hope you'll find it helpfull. Do let me know of any error's/suggestions to improve the doument.