Saturday, December 20, 2008

Charts in JDeveloper 10.1.3

With JDeveloper 11g you have many out of the box JSF graph components but too bad this isn't the case in JDeveloper 10.1.3. In this blog I will show you how you can have free graphs components and use it in 10.1.3.
First we need to download Chartcreator this is JSF tag library which works on jfreechart. With these two jars we can make the following charts pie ring timeseries xyline polar scatter xyarea xysteparea xystep bubble candlestick boxandwhisker highlow histogram wind bar stackedbar linearea stackedarea gantt waterfall

Here are some examples with ADF.




Add chartcreator as taglib to your project.
And add jfreechart and jcommon libraries to this project. We don't need the other libraries

Add the JSF chart component to your ADF page

<chart:chart id="ChartTimeseries"
datasource="#{backing_chart.timeDataset}"
type="timeseries" is3d="true" antialias="true"
title="Timeseries" xlabel="year"
ylabel="Total" height="300" width="300"/>
<chart:chart id="chartLine" datasource="#{backing_chart.dataset2}"
type="line" is3d="true" antialias="true"
title="Line" xlabel="year"
ylabel="Total" height="300" width="500"/>

We need a backing bean to provide the charts with data. Create and add a backing bean to the faces-config.xml



<?xml version="1.0" encoding="windows-1252"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config xmlns="http://java.sun.com/JSF/Configuration">
<managed-bean>
<managed-bean-name>backing_chart</managed-bean-name>
<managed-bean-class>nl.ordina.view.backing.Chart</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>bindings</property-name>
<value>#{bindings}</value>
</managed-property>
</managed-bean>
<application>
<default-render-kit-id>oracle.adf.core</default-render-kit-id>
</application>
<lifecycle>
<phase-listener>oracle.adf.controller.faces.lifecycle.ADFPhaseListener</phase-listener>
</lifecycle>
</faces-config>

The chart backing bean code



package nl.ordina.view.backing;

import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCIteratorBinding;

import oracle.jbo.Row;
import oracle.jbo.RowSetIterator;
import oracle.jbo.domain.Number;

import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.Year;

public class Chart {
private DCBindingContainer bindings;
private DefaultPieDataset pieDataSet;
private DefaultCategoryDataset dataset2;

public DefaultPieDataset getPieDataSet() {
return pieDataSet;
}

public DefaultCategoryDataset getDataset() {

DefaultCategoryDataset dataset = new DefaultCategoryDataset();
pieDataSet = new DefaultPieDataset();
DCBindingContainer bc = getBindings();
if (bc != null) {
DCIteratorBinding normIter =
bc.findIteratorBinding("DepartmentEmployeesCountIterator");

RowSetIterator rsi = normIter.getRowSetIterator();
String[] attNames = rsi.getRowAtRangeIndex(0).getAttributeNames();

int departmentIdNum = 0;
int totalNum = 0;

for (int j = 0; j < attNames.length; j++) {
if (attNames[j].equalsIgnoreCase("DepartmentId")) {
departmentIdNum = j;
} else if (attNames[j].equalsIgnoreCase("Total")) {
totalNum = j;
}
}

for (int i = 0; i < rsi.getRowCount(); i++) {
Row currentRow = rsi.getRowAtRangeIndex(i);
Object[] attValues = currentRow.getAttributeValues();
Number departmentIdValue = (Number)attValues[departmentIdNum];
Number totalValue = (Number)attValues[totalNum];

pieDataSet.setValue(departmentIdValue.toString(),
totalValue.toDouble(totalValue.getBytes()));
dataset.addValue(totalValue.toDouble(totalValue.getBytes()),
"Employees", departmentIdValue.toString());
}
}
return dataset;
}

public DefaultCategoryDataset getDataset2() {
return dataset2;
}

public TimeSeriesCollection getTimeDataset() {

dataset2 = new DefaultCategoryDataset();
TimeSeries s1 = new TimeSeries("Year", Year.class);

DCBindingContainer bc = getBindings();
if (bc != null) {
DCIteratorBinding normIter =
bc.findIteratorBinding("EmployeeHireYearIterator");

RowSetIterator rsi = normIter.getRowSetIterator();
String[] attNames = rsi.getRowAtRangeIndex(0).getAttributeNames();

int yearNum = 0;
int totalNum = 0;

for (int j = 0; j < attNames.length; j++) {
if (attNames[j].equalsIgnoreCase("Year")) {
yearNum = j;
} else if (attNames[j].equalsIgnoreCase("Total")) {
totalNum = j;
}
}

for (int i = 0; i < rsi.getRowCount(); i++) {
Row currentRow = rsi.getRowAtRangeIndex(i);
Object[] attValues = currentRow.getAttributeValues();
String yearValue = (String)attValues[yearNum];
Number totalValue = (Number)attValues[totalNum];

s1.add(new Year(new Integer(yearValue)),
totalValue.toDouble(totalValue.getBytes()));

dataset2.addValue(totalValue.toDouble(totalValue.getBytes()),
"Employees", yearValue.substring(2));


}
}
TimeSeriesCollection dataset = new TimeSeriesCollection();
dataset.addSeries(s1);
return dataset;
}

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

public DCBindingContainer getBindings() {
return bindings;
}
}


Here you have my example project which works on the HR demo database schema

4 comments:

  1. Hi,

    I am trying to develop graphs using jfreechart on the jdeveloper 10.1.3 IDE. However when I try to run the JSF page I get the following exception...

    09/03/05 15:03:39.568 TenorJavaGraph: Servlet error
    java.lang.RuntimeException: Unsupported chart type
    at net.sf.jsfcomp.chartcreator.utils.ChartUtils.createChartWithType(Unknown Source)
    at net.sf.jsfcomp.chartcreator.Chartlet.doGet(Unknown Source)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:743)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:712)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:369)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.unprivileged_forward(ServletRequestDispatcher.java:258)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.access$100(ServletRequestDispatcher.java:50)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher$2.oc4jRun(ServletRequestDispatcher.java:192)
    at oracle.oc4j.security.OC4JSecurity.doPrivileged(OC4JSecurity.java:283)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.forward(ServletRequestDispatcher.java:197)
    at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:346)
    at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:152)
    at oracle.adfinternal.view.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:157)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:107)
    at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:245)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:137)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:214)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:712)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:369)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:865)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:447)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.serveOneRequest(HttpRequestHandler.java:215)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.run(HttpRequestHandler.java:117)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.run(HttpRequestHandler.java:110)
    at oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:260)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
    at java.lang.Thread.run(Thread.java:595)
    09/03/05 15:04:11.396 TenorJavaGraph: Servlet error
    java.lang.RuntimeException: Unsupported chart type
    at net.sf.jsfcomp.chartcreator.utils.ChartUtils.createChartWithType(Unknown Source)
    at net.sf.jsfcomp.chartcreator.Chartlet.doGet(Unknown Source)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:743)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:712)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:369)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.unprivileged_forward(ServletRequestDispatcher.java:258)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.access$100(ServletRequestDispatcher.java:50)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher$2.oc4jRun(ServletRequestDispatcher.java:192)
    at oracle.oc4j.security.OC4JSecurity.doPrivileged(OC4JSecurity.java:283)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.forward(ServletRequestDispatcher.java:197)
    at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:346)
    at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:152)
    at oracle.adfinternal.view.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:157)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:107)
    at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:245)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:137)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:214)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:712)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:369)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:865)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:447)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.serveOneRequest(HttpRequestHandler.java:215)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.run(HttpRequestHandler.java:117)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].server.http.HttpRequestHandler.run(HttpRequestHandler.java:110)
    at oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:260)
    at oracle.oc4j.network.ServerSocketAcceptHandler.procClientSocket(ServerSocketAcceptHandler.java:239)
    at oracle.oc4j.network.ServerSocketAcceptHandler.access$700(ServerSocketAcceptHandler.java:34)
    at oracle.oc4j.network.ServerSocketAcceptHandler$AcceptHandlerHorse.run(ServerSocketAcceptHandler.java:880)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.1.1) ].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
    at java.lang.Thread.run(Thread.java:595)

    I have changed teh web.xml file in accordance wtih your jfreechart sample available for the pie/timeseries/bar/line graph.

    Please could you help me out with the above as I am not getting any help on this issue.

    Regards,
    Lester.

    ReplyDelete
  2. Hi,

    can you post a part of the jsf code and the backing bean. So I can take a look.

    thanks Edwin

    ReplyDelete
  3. Hi Edwin,

    Here are the JSF and the Backing Bean Codes. Hope this does not clog the page.

    For some reason this does not allow me to post the JSF code saying server side scripting not allowed. I have also attached this problem in detail at the following link which has the JSF Code:-

    http://forums.oracle.com/forums/thread.jspa?threadID=868266&tstart=15



    =============
    BACKING BEAN:
    =============

    package view.backing;

    import java.sql.SQLException;

    import java.text.DateFormat;

    import java.text.ParseException;
    import java.text.SimpleDateFormat;

    import java.util.Date;

    import javax.faces.component.html.HtmlForm;

    import oracle.adf.model.binding.DCBindingContainer;
    import oracle.adf.model.binding.DCIteratorBinding;

    import oracle.adf.view.faces.component.core.output.CoreMessages;

    import oracle.adf.view.faces.component.html.HtmlBody;
    import oracle.adf.view.faces.component.html.HtmlHead;
    import oracle.adf.view.faces.component.html.HtmlHtml;

    import oracle.jbo.Row;
    import oracle.jbo.RowSetIterator;

    //import oracle.jbo.domain.Number;
    import java.lang.Number;

    import oracle.adf.view.faces.component.core.data.CoreColumn;
    import oracle.adf.view.faces.component.core.data.CoreTable;
    import oracle.adf.view.faces.component.core.input.CoreInputText;

    import org.jfree.data.category.DefaultCategoryDataset;
    import org.jfree.data.general.DefaultPieDataset;
    import org.jfree.data.time.Day;
    import org.jfree.data.time.TimeSeries;
    import org.jfree.data.xy.XYSeries;
    import org.jfree.data.time.TimeSeriesCollection;
    import org.jfree.data.time.TimeSeriesDataItem;
    import org.jfree.data.time.Year;
    import org.jfree.data.xy.XYDataItem;
    import org.jfree.data.xy.XYSeriesCollection;

    public class Graphtest {


    private HtmlHtml html1;
    private HtmlHead head1;
    private HtmlBody body1;
    private CoreMessages messages1;
    private HtmlForm form1;
    private DCBindingContainer bindings;
    private DefaultCategoryDataset dataset2;
    private CoreTable table1;
    private CoreColumn column1;
    private CoreInputText inputText1;
    private CoreColumn column2;
    private CoreInputText inputText2;

    public void setHtml1(HtmlHtml html1) {
    this.html1 = html1;
    }

    public HtmlHtml getHtml1() {
    return html1;
    }

    public void setHead1(HtmlHead head1) {
    this.head1 = head1;
    }

    public HtmlHead getHead1() {
    return head1;
    }

    public void setBody1(HtmlBody body1) {
    this.body1 = body1;
    }

    public HtmlBody getBody1() {
    return body1;
    }

    public void setMessages1(CoreMessages messages1) {
    this.messages1 = messages1;
    }

    public CoreMessages getMessages1() {
    return messages1;
    }

    public void setForm1(HtmlForm form1) {
    this.form1 = form1;
    }

    public HtmlForm getForm1() {
    return form1;
    }


    public DefaultCategoryDataset getDataset2() {
    return dataset2;
    }

    public DefaultCategoryDataset getDataset() throws ParseException,
    SQLException {

    System.out.println("Am into getDataset() function");
    XYSeries series = new XYSeries("Installation Vessel Level Graph");
    //dataset2 = new DefaultCategoryDataset();
    TimeSeries s1 = new TimeSeries("Year", Year.class);

    //XYSeriesCollection dataset = new XYSeriesCollection();
    DefaultCategoryDataset dataset = new DefaultCategoryDataset();

    DCBindingContainer bc = getBindings();
    if (bc != null) {

    System.out.println("\n\n Am into getDataset() function --> bc not null");

    DCIteratorBinding normIter =
    bc.findIteratorBinding("ViewObj1Iterator");

    RowSetIterator rsi = normIter.getRowSetIterator();
    String[] attNames = rsi.getRowAtRangeIndex(0).getAttributeNames();

    int readDateTimeNum = 0;
    int levelNum = 0;

    for (int j = 0; j < attNames.length; j++) {
    if (attNames[j].equalsIgnoreCase("ReadingDatetime")) {
    readDateTimeNum = j;
    } else if (attNames[j].equalsIgnoreCase("PostFillLevel")) {
    levelNum = j;
    }
    }

    for (int i = 0; i < rsi.getRowCount(); i++) {

    Row currentRow = rsi.getRowAtRangeIndex(i);
    Object[] attValues = currentRow.getAttributeValues();

    String readingDateStr = attValues[readDateTimeNum].toString();

    SimpleDateFormat format = new SimpleDateFormat("ddMMyy");
    java.util.Date readingValue = format.parse(readingDateStr);

    //Integer readingDate = Integer.parseInt(readingValue.toString());
    Number levelValue = (Number)attValues[levelNum];



    /* series.add(levelValue, (Number)(Integer.parseInt(readingValue.toString())));
    dataset.addSeries(series); */
    dataset.addValue(levelValue,
    "Date", readingValue.toString());
    }

    //return dataset2;
    }

    /*TimeSeriesCollection dataset = new TimeSeriesCollection();
    dataset.addSeries(s1); */
    return dataset;
    }

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

    public DCBindingContainer getBindings() {
    return bindings;
    }


    public void setTable1(CoreTable table1) {
    this.table1 = table1;
    }

    public CoreTable getTable1() {
    return table1;
    }

    public void setColumn1(CoreColumn column1) {
    this.column1 = column1;
    }

    public CoreColumn getColumn1() {
    return column1;
    }

    public void setInputText1(CoreInputText inputText1) {
    this.inputText1 = inputText1;
    }

    public CoreInputText getInputText1() {
    return inputText1;
    }

    public void setColumn2(CoreColumn column2) {
    this.column2 = column2;
    }

    public CoreColumn getColumn2() {
    return column2;
    }

    public void setInputText2(CoreInputText inputText2) {
    this.inputText2 = inputText2;
    }

    public CoreInputText getInputText2() {
    return inputText2;
    }
    }


    Thanks a lot for your help.

    Regards,
    Lester.

    ReplyDelete
  4. Hi Mr. Edwin,

    I am also using jfreechart on the jdeveloper 10.1.3 IDE to develop some graphs needed by users on my application. However when I try to run the JSF page I get empty box for chart and I did what you mentioned about this issue. Could you please help me to fixed this problem. Thanks,

    ReplyDelete