Tuesday, August 25, 2009

JFreeChart - Easy way to include Graphics






I have used JFreeChart to setup some charts on my Web application . The app was built using J2EE framework . Example from my Project shown above, the code sample below shows the Aggregate image that's generated on the fly based on the input
Green - if percent is less than 33
Orange - if percent is less than 66
red - if percent is over 66


1 . Setting up , is fairly simple . Download the required files from http://www.jfree.org/jfreechart/download.html and include in the WEB-INF/lib directory . I have used 1.0.1 version.

2. Setup your utility class that generates the image on the fly ( Bar chart in this case ) . You have to go through the api's and do a lot of tries to get the image that works as per your specifications.
Here is the example code for the 3D graph , as shown in picture above

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import org.jfree.chart.ChartPanel;


/**
* Creates a 3D Graph bar based on the percent
*/
public class Treepercent extends ChartPanel {



public Treepercent(JFreeChart chart)
{
super(chart);
}


public static Treepercent createChart(String title,double dPercent,String sTree,String sFrac)
{
CategoryDataset dataset = createDataset(dPercent,sTree);
JFreeChart chart1 = createChart(dataset,sTree,dPercent,sFrac);
ChartPanel chartPanel = new ChartPanel(chart1, false);
chartPanel.setSize(new Dimension(50, 27));
chartPanel.setBounds(10,10,15,100);
//setContentPane(chartPanel);
Treepercent tp = new Treepercent(chart1);
return tp;
}


public static CategoryDataset createDataset(double dPercent,String sTree) {

// row keys...
String series1 = "First";

// column keys...
// String category1 = sTree;
String category1 = "";
// create the dataset...

DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(dPercent, series1, category1);
return dataset;

}

/**
* Creates a sample chart.
*
* @param dataset the dataset.
*
* @return The chart.
*/
public static JFreeChart createChart(CategoryDataset dataset, String sTree,double dPercent,String sFrac) {

// create the chart...
JFreeChart chart = ChartFactory.createBarChart3D(
"", // chart title
"", // domain axis label
"Aggregate "+String.valueOf(dPercent)+" Percent ("+ sFrac+")", // range axis label
dataset, // data
PlotOrientation.HORIZONTAL, // orientation
false, // include legend
true, // tooltips?
false // URLs?
);
// NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...

// set the background color for the chart...
chart.setBackgroundPaint(Color.white);

// get a reference to the plot for further customisation...
CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.white);

// set the range axis to display integers only...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setRange( 0.0D, 100D );
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

// disable bar outlines...
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setDrawBarOutline(true);

//renderer.setLegendItemToolTipGenerator( new StandardCategorySeriesLabelGenerator( "Tooltip: {0}" ) );
// renderer.setBaseItemLabelsVisible(false);
// set up gradient paints for series...

GradientPaint gpGreen = new GradientPaint(
0.0f, 0.0f, new Color(0, 64, 0),
0.0f, 0.0f, new Color(0, 64, 0)
);

GradientPaint gpOrange = new GradientPaint(
0.0f, 0.0f, new Color(220, 124, 9),
0.0f, 0.0f, new Color(220, 124, 9)
);
GradientPaint gpRed= new GradientPaint(
0.0f, 0.0f, Color.red,
0.0f, 0.0f, Color.red
);

if (dPercent <= 33) renderer.setSeriesPaint(0, gpGreen); else if(dPercent <= 66) renderer.setSeriesPaint(0, gpOrange); else renderer.setSeriesPaint(0, gpRed); CategoryAxis domainAxis = plot.getDomainAxis(); domainAxis.setLabel(""); domainAxis.setCategoryLabelPositions( CategoryLabelPositions.STANDARD ); // OPTIONAL CUSTOMISATION COMPLETED. return chart;
}

}


3. Next is to setup a servlet or a screen class that would generate the image . Remember the servlet the image itself as bytes .

import org.jfree.chart.ChartUtilities;
....

public class generatechart extends ... {

screenmethod (....)
{
ChartUtilities.writeChartAsJPEG( os, 100, Treepercent.createChart("Aggregate",dPer,"",sFrac).getChart(), 300, 75 );
// this create a chart based on the numbers sFranc
}
}


4. Setup a template a JSP or Velocity template , It will be a empty file .

5. Test if the image is generated

Wednesday, October 10, 2007

SNMP Call from Java

SNMP code for clearning a port using SNMPJ , I have implemented this in Turbine/Velocity framework as an ajax call .

package org.mymodule;

import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;
import org.mymodule.modules.util.LMLab;
import org.netsnmp.* ;
import org.netsnmp.ASN.INTEGER;
import org.netsnmp.ASN.OCTET_STR ;

public class Snmp extends SecureScreen {

public void doBuildTemplate(RunData data, Context context) throws Exception
{
data.setContentType("text/xml");
LMLab lab = (LMLab)data.getSession().getAttribute("sellab");
String community = lab.getCommunitystr();
if ((community == null)||(community.equals("")))
throw new Exception("ERROR-NO COMMUNITY STRING");

NetSNMPSession session ;
MyListener listener ;
PDU pdu ;
OID sysLocationOID ;
INTEGER lineno;
int lnlength;

String host = data.getParameters().getString("ip",null);
//String community = "private";
String newLocation = data.getParameters().getString("port",null);

if (host == null)
throw new Exception("ERROR-NO HOST");

if (newLocation == null)
throw new Exception("ERROR-NO PORT");
lnlength =newLocation.length() ;
if (lnlength >2)
lineno = new INTEGER(Integer.valueOf(newLocation.substring(lnlength-2,lnlength)).intValue());
else
lineno = new INTEGER(Integer.valueOf(newLocation).intValue());
/*;
* Open a session to the remote host
*/
session = new NetSNMPSession(host, community) ;

/*
* Create a PDU that will perform a 'SET' operation
*/
pdu = new PDU(NetSNMP.MSG_SET) ;

/*
* Create an OID for the systemLocation
*/
try {
//sysLocationOID = new DefaultOID("SNMPv2-MIB::sysLocation.0") ;
//sysLocationOID = new DefaultOID("SNMPv2-MIB::tsClrTtyLine.0") ;

sysLocationOID = new DefaultOID(".1.3.6.1.4.1.9.2.9.10.0") ;

/*
* Add an OCTET_STR value to the PDU that will contain the new
* system location.
*/
//pdu.addEntry(sysLocationOID, new OCTET_STR(" integer "+newLocation)) ;
// pdu.append()
PDU.entry pe = new PDU.entry(sysLocationOID,lineno);
PDU.entry[] peArray = {pe};
pdu.setEntries(peArray);

/*
* create a new listener instance and add it to the listeners for the session
*/
listener = new MyListener() ;
session.addListener(listener) ;

synchronized ( listener ) {
session.send(pdu, null) ;
listener.wait() ;

if( listener.success )
context.put("msg","SUCCESS");
else {
//System.out.println("operation failed") ;
context.put("msg","ERROR-TIMEDOUT");
}
}


}
catch( MIBItemNotFound e ) {
/*System.out.println("The sysLocation Object was not found.") ;
System.out.println("Please ensure that the MIBDIRS and MIBS") ;
System.out.println("environmental variables are set properly");*/
context.put("msg","ERROR-SYSLOCATION");
return ; // NOT REACHED
}
catch (NetSNMPSendError e) {
//System.out.println("An error occurred sending the pdu") ;
context.put("msg","ERROR-NETSNMP");
}
catch (InterruptedException e) {
//System.out.println("the wait operation was interrupted") ;
context.put("msg","ERROR-INTERRUPTED");
}
catch(Exception e)
{
context.put("msg",e.getMessage());
}



/*
* The actionPerformed method will be called on a different thread. Synchronize
* this thread with the thread that it will be called upon with a 'synchronized' block.
*/

/*synchronized ( listener ) {
try {*/
/*
* Send the pdu to the remote agent
*/
//session.send(pdu, null) ;


/*
* wait for the listener actionPerformed method to notify that
* operation has been completed
*/
/*listener.wait() ;

if( !listener.success ) {
System.out.println("operation failed") ;

}
} // try
catch (NetSNMPSendError e) {
System.out.println("An error occurred sending the pdu") ;
}
catch (InterruptedException e) {
System.out.println("the wait operation was interrupted") ;
}

} // synchronized
*/
}

/**
* Class that will receive and process the response from the remote agent.
*/
public static class MyListener implements NetSNMPAction {

boolean success = true ;

/**
* @see org.netsnmp.NetSNMPAction#actionPerformed(int, NetSNMPSession, PDU, Object)
*/
public synchronized boolean actionPerformed(int result, NetSNMPSession session, PDU pdu, Object o) throws Throwable {
if( result == NetSNMP.STAT_TIMEOUT ) {
//System.out.println("Operation timed out. Ensure that your remote agent is running and that the community parameter is correct") ;
success = false ;
this.notify() ; // notify that the operation has completed
return true ; // keep calling other registerred listeners, if any
} // if

if( pdu.errStatus != 0 ) {
//System.out.println("Set operation failed. Ensure that the security info you specified provides write access to the sysLocation Object") ;
success = false ;
this.notify() ; // notify that the operation has completed
return true ;
}

this.notify() ; // notify that the operation has completed
return true ;
}

}

}

Dynamic SQL from Java use any number of parameters


Following is the Code that uses Java and Oracle . Its an utility to do a dynamic search without defining the sql . SQL is generated on the fly ( dynamically ) at runtime . You may have to tweak the sql generated for your purpose , but you can resue most of the Code

Params can be changed to include a variety of search options
1.Quotes for Exact Search
2. % for wider search
- abc% means starts with "abc"
- %xyz means ends with "xyz"
3.Use () to specify OR condition e.g.,(abc , efg)
4.Search is Non-Case Sensitive

One limitation is that all the parameters are created by AND condition .However you can extend the utility class to include
that feature too .

Sql Utlity class

import java.util.StringTokenizer;

public class Sql {
private String sOn ; // column name to search
private String sParam; // exact search parameter

public Sql(String sOn , String sParam)
{
this.sOn = sOn;
this.sParam = sParam;
}
// Generate the sql
public String getSQL()
{
StringBuffer sSql = new StringBuffer();
String sToken = new String();
String sTemp = new String();

if(sParam.startsWith("\"")&& sParam.endsWith("\""))
{
sSql.append("AND UPPER(").append(sOn).append(") =").append("'").append((sParam.substring(sParam.indexOf("\"")+1,sParam.lastIndexOf("\""))).toUpperCase()).append("'");
}else if(sParam.startsWith("(")&& sParam.endsWith(")"))
{
sTemp = sParam.substring(sParam.indexOf("(")+1,sParam.indexOf(")")) ;
sSql.append("AND UPPER(").append(sOn).append(") IN (");
StringTokenizer st1 = new StringTokenizer(sTemp,",");
while ( st1.hasMoreTokens() ) {
sToken = st1.nextToken();
if(sToken !=null)
{
sToken = sToken.trim().toUpperCase();
sSql.append("'").append(sToken).append("',");
}
}
sSql = new StringBuffer(sSql.substring(0,sSql.length()-1)) ;
sSql.append(")");
}
else if(sParam.startsWith("%") || sParam.endsWith("%"))
{
sSql.append("AND UPPER(").append(sOn).append(") LIKE '").append(sParam.toUpperCase()).append("'");

}else if(sParam!=null&& !sParam.equals(""))
{
sSql.append("AND UPPER(").append(sOn).append(") LIKE '%").append(sParam.toUpperCase()).append("%'");

}
return sSql.toString();
}
}

Utlity method


public String getSearchSQL(Vector v)
{
StringBuffer sql = new StringBuffer();
for(Enumeration e=v.elements();e.hasMoreElements();)
{
sql.append(((Sql)e.nextElement()).getSQL() );

}
return sql.toString();
}


Application Logic


Vector v = new Vector();
v.add(new Sql("<name of table column name>", <value to search on use empty string if null> ));

.....repeat for all the parameters to be searched on

<sql string> = getSearchSQL(v);

Bingo !