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.

Tuesday, December 23, 2008

Learning ADF

Now days I am learning ADF 11g and working on a sample example in Jdev 11g. For developers like me who had and still working on Oracle OAF and Oracle apps and what to learn ADF, it is very imporatnt to learn basic java, J2EE concepts as well as understanding XML and JSF concepts. Here are few links that I found usefull for learning these:-

--> Basic java -
http://java.sun.com/docs/books/tutorial/java/index.html
--> J2EE -
http://www.amazon.com/Certified-Component-Developer-Study-Companion/dp/0955160316
--> JSF -
http://www.javapassion.com/j2ee/JSFBasics_speakernoted.pdf
--> XML concepts -
http://www.w3schools.com/xml/default.asp

I will be posting my ADF 11g learning application by next year.

Happy Learning.

Tuesday, October 14, 2008

Call method on page load in ADF

call method on page load in ADF – [JDeveloper Version 10.1.3]

In this example we will see how we can call a method inside your backing bean or application module when page is getting loaded.
The scenario I am taking here is you have to show the current row index of the view object row on page load in ADF table column.
1) Create a view object based on Job table in HR schema with name OnPageLoadJobVO. Do generate the VOImpl and VORowImpl java classes for the created view object.



2) Add a transient variable inside your view object with name
“myCurrentRowIndex”



3) Add the above created view Object inside your application module.
4) Add the following code inside your application module Impl class.

public void setJobCurrentRowIndex() {
System.out.println("I am here inside AM");
OnPageLoadJobVOImpl vo = getOnPageLoadJobVO1();
OnPageLoadJobVORowImpl row=null;
long fetchedRowCount = vo.getEstimatedRowCount();
RowSetIterator jobVoIter = vo.createRowSetIterator("jobVoIter");
if (fetchedRowCount > 0)
{
jobVoIter.setRangeStart(0);
jobVoIter.setRangeSize((int)fetchedRowCount);
for (int count = 0; count < fetchedRowCount; count++)
{
row=(OnPageLoadJobVORowImpl)jobVoIter.getRowAtRangeIndex(count);
row.setmyCurrentRowIndex(new Number(count));
}
}
jobVoIter.closeRowSetIterator();
}

5) Expose the above created method in application module to the client.
6) Drag and drop the OnPageLoadJobVO object to your jspx page as ADF read only table.
7) Create a new Managed bean using faces-config.xml with
name= OnPageLoadBackingBean and

class= OnPageLoadBean

8) Copy and paste the following code inside your newly created managed bean class.

package viewlayer.backing;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import model.common.AppModule;
import oracle.adf.controller.v2.lifecycle.Lifecycle;
import oracle.adf.controller.v2.lifecycle.PagePhaseEvent;
import oracle.adf.controller.v2.lifecycle.PagePhaseListener;


public class OnPageLoadBean implements PagePhaseListener{
public OnPageLoadBean() {
}
public void afterPhase(PagePhaseEvent event) {
}
public void beforePhase(PagePhaseEvent event) {
if (event.getPhaseId() == Lifecycle.PREPARE_MODEL_ID) {
if (!isPostback())
/*
System.out.println("i am here inside backing bean");
this.getApplicationModule().setJobCurrentRowIndex();
}
}
private boolean isPostback() {
return Boolean.TRUE.equals(resolveExpression("#{adfFacesContext.postback}"));
}
private Object resolveExpression(String expression) {
FacesContext ctx = FacesContext.getCurrentInstance();
Application app = ctx.getApplication();
ValueBinding bind = app.createValueBinding(expression);
return bind.getValue(ctx);
}
private AppModule getApplicationModule() {
return (AppModule)resolveExpression ("#data.AppModuleDataControl.dataProvider}");
}
}
9) Right click on your jspx page and go to your page definition. Where set the attribute ControllerClass inside your pageDefinition tag as the name of the managed bean.


Run your page to check the results.

Add new row in ADF table on button click

Add new row in ADF table on button click – [JDeveloper Version 10.1.3]
In this example we will add a new row at last position in an ADF table. I am taking an example of Employee table in HR schema. We need this approach if we want to create an empty row in ADF table and then initialize it with some values or to add the empty row at the end of the table.

Step 1) Create a new Employee View Object(say EmpViewObjEOBased) based on an Employee Entity object.

Step 2) Add the above view object in your application module.

Step 3) Drop it on your page as a ADF table (not as ADF readonly table).

Step 4) Add the following code inside your application module class.


public void createRow() {
Row newRow = getEmpViewObjEOBased1().createRow();
newRow.setNewRowState(Row.STATUS_INITIALIZED);
//get instance of the above created view object
ViewObjectImpl vo=getEmpViewObjEOBased1();
// to insert row at the end of the table
vo.insertRowAtRangeIndex(vo.getRangeSize()-1,newRow);
System.out.println(getEmpViewObjEOBased1().getCurrentRowIndex());
}

If you want to insert the row at the begening of the table replace line vo.insertRowAtRangeIndex(vo.getRangeSize()-1,newRow); with
vo.insertRow(newRow);

Step 5) Expose this application module method to client.




This will expose the method to be used in UI and method will appear in the data control.

Step 6) Drop the createRow button inside the “Table facets->action” as a ADF command button.


Now run your page and check the result...

Wednesday, October 8, 2008

Jdeveloper 11g production

Finally after much of wait , Jdeveloper 11g productions is released and is
Ready for download.
http://www.oracle.com/technology/software/products/jdev/htdocs/soft11.html .

JDeveloper 11g — Online Demonstrations

http://www.oracle.com/technology/products/jdev/viewlets/11/index.html

Documentation and Developer guide

http://download.oracle.com/docs/cd/E12839_01/index.htm