srividya_sharma

Fusion Charts intergration with JSF

Recommended Posts

Hi,

 

 

 

Could you guys share your ideas on integrating the charts with JSF?

 

I got the script for chart via backing bean on my jsf page.. But it is not executing the script.

 

Is there any established way of integrating with JSF?

Share this post


Link to post
Share on other sites

Hi,

I have tried it out in my application. To use FusionCharts with JSF, you would need to create a Component. I created a component ChartTag. Let me describe how you have to do it. ( I am assuming that you have a JSF application atleast an empty one)

1. Create a charts.tld file in WEB-INF folder with the following contents:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 
<taglib> 
<tlib-version>1.0</tlib-version> 
<jsp-version>1.2</jsp-version> 
<short-name>fc</short-name> 
<uri>http://localhost/</uri> 
<tag> 
<name>fusioncharts</name> 
<tag-class>charts.ChartTag</tag-class> 
<body-content>JSP</body-content> 
<attribute>
<name>filename</name>
</attribute>
<attribute>
<name>url</name>
</attribute>
<attribute>
<name>xml</name>
</attribute> 
<attribute>
<name>chartId</name>
</attribute>
<attribute>
<name>width</name>
</attribute>
<attribute>
<name>height</name>
</attribute>
<attribute>
<name>debugMode</name>
</attribute>
<attribute>
<name>registerWithJS</name>
</attribute>
</tag> 
</taglib> 

2. Modify faces-config.xml present in WEB-INF folder to have the following text:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
<component>
<component-type>chart</component-type>
<component-class>charts.UIChart</component-class>
</component>
<lifecycle/>
<application>
<locale-config/>
</application>
<factory/>
</faces-config>

3. Now we need to write the java classes for charts.ChartTag and charts.UIChart. Create a folder called charts and write the following java classes:

ChartTag.java

package charts;
import javax.faces.component.UIComponent; 
import javax.faces.webapp.UIComponentTag; 
public class ChartTag extends UIComponentTag{ 
String chartId;
String filename;
String xml;
String url;
String width;
String height;
String debugMode;
String registerWithJS;
 
 public String getChartId() { 
 return chartId;
 }
 public void setChartId(String id) {
 this.chartId= id;
 }
public String getFilename() { 
 return filename;
 }
 public void setFilename(String filename){
 this.filename= filename;
 }
public String getXml() { 
 return xml;
 }
 public void setXml(String xml){
 this.xml= xml;
 }
public String getUrl() { 
 return url;
 }
 public void setUrl(String url) {
 this.url= url;
 }
public String getWidth() { 
 return width;
 }
 public void setWidth(String width) {
 this.width= width;
 }
public String getHeight() { 
 return height;
 }
 public void setHeight(String height) {
 this.height= height;
 }
public String getDebugMode() { 
 return debugMode;
 }
 public void setDebugMode(String debugMode) {
 this.debugMode= debugMode;
 }
public String getRegisterWithJS() { 
 return registerWithJS;
 }
 public void setRegisterWithJS(String registerWithJS) {
 this.registerWithJS= registerWithJS;
 }
public void release() { 
// the super class method should be called 
super.release(); 
chartId=null;
filename=null;
xml=null;
url=null;
width=null;
height=null;
debugMode=null;
registerWithJS=null;
} 
protected void setProperties(UIComponent component) {
 // the super class method should be called 
super.setProperties(component); 
if(chartId != null)
 component.getAttributes().put("id", chartId);
if(filename != null)
 component.getAttributes().put("filename", filename);
if(xml!=null)
 component.getAttributes().put("xml", xml);
if(url!=null)
 component.getAttributes().put("url", url);
if(width!=null)
 component.getAttributes().put("width", width);
if(height!=null)
 component.getAttributes().put("height", height);
if(debugMode!=null)
 component.getAttributes().put("debugMode", debugMode);
if(registerWithJS!=null)
 component.getAttributes().put("registerWithJS", registerWithJS);
} 
public String getComponentType() { 
return "chart"; 
} 
public String getRendererType() {
 // null means the component renders itself 
return null; 
} 
} 

UIChart.java

package charts;
import java.io.IOException;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
public class UIChart extends UIOutput {
 public void encodeBegin(FacesContext context) throws IOException {
 ResponseWriter writer = context.getResponseWriter();
 String chartId = (String)getAttributes().get("id");
  writer.startElement("div", this);
  writer.writeAttribute("id", chartId+"Div" , null);
  writer.writeAttribute("align","center",null); 
  writer.writeText("Chart.",null); 
  writer.endElement("div");

 String chartSWF= (String)getAttributes().get("filename");
 String url= (String)getAttributes().get("filename");
 String xml= (String)getAttributes().get("xml");
 String chartWidth= (String)getAttributes().get("width");
 String chartHeight= (String)getAttributes().get("height");
 String debugMode= (String)getAttributes().get("debugMode");
 int debugModeInt = boolToNum(new Boolean(debugMode));
 String registerWithJS= (String)getAttributes().get("registerWithJS");
 int regWithJSInt = boolToNum(new Boolean(registerWithJS));
writer.startElement("script",this);
writer.writeAttribute("type","text/javascript",null);  
writer.writeText("var chart_"+chartId+" = new FusionCharts('"+chartSWF+"', '"+chartId+"', '"+chartWidth +"', '"+chartHeight+"', '"+ debugModeInt+"', '"+regWithJSInt+"');",null);

if (xml==null || xml.equals(""))
 writer.writeText("chart_"+chartId+".setDataURL(""+url+"");",null);
else 
 writer.writeText("chart_"+chartId+".setDataXML(""+xml+"");",null);
// Finally render the chart
writer.writeText("chart_"+chartId+".render('"+chartId+"Div');",null);
}
 public void encodeEnd(FacesContext context) throws IOException {
 ResponseWriter writer = context.getResponseWriter();
 writer.endElement("script");
 }
   /**
 * Converts a Boolean value to int value<br>
 * 
 * @param bool Boolean value which needs to be converted to int value 
 * @return int value correspoding to the boolean : 1 for true and 0 for false
 */
  public int boolToNum(Boolean bool) {
 int num = 0;
 if (bool.booleanValue()) {
 num = 1;
 }
 return num;
   }
}

4. After writing the java classes, we now have to use the new component in our JSF. Here is how we do that:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> 
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> 
<%@ taglib uri="http://localhost/" prefix="fc" %> 
<html> 
<head> 
<title>Show Custom Component</title> 
<script type="text/javascript" src="FusionCharts/FusionCharts.js">
</script>
</head> 
<body> 
<f:view> 
<f:verbatim>This is JSF example</f:verbatim> 
<fc:fusioncharts chartId="MyChart" filename="FusionCharts/Column3D.swf" width="700" height="300" xml="<chart caption='Monthly Unit Sales' xAxisName='Month' yAxisName='Units' showValues='0' formatNumberScale='0' showBorder='1'><set label='Jan' value='462' /><set label='Feb' value='857' /><set label='Mar' value='671' /><set label='Apr' value='494' /><set label='May' value='761' /><set label='Jun' value='960' /><set label='Jul' value='629' /><set label='Aug' value='622' /><set label='Sep' value='376' /><set label='Oct' value='494' /><set label='Nov' value='761' /><set label='Dec' value='960' /></chart>" debugMode="false" registerWithJS="false"> 
</fc:fusioncharts> 
</f:view> 
</body> 
</html> 

Do not forget to include FusionCharts.js present in the FusionCharts folder. This folder will also contain the swf files required to generate the chart. I have used the xml directly here. you could give the url to the xml also.

Here I have hard-coded the xml, you could get the xml from the backing bean also.

In case you have problems with the above code, please feel free to ask questions.

Srividya

Edited by Guest

Share this post


Link to post
Share on other sites

Hi

Here is a sample project which contains all the files described in the previous post.

The jar files required for JSF are not present. Please put those files in WebContent/WEB-INF/lib folder.

Also, FusionCharts swf and js files are not present. Please put those files in WebContent/FusionCharts folder.

Run ant, to create the war which can be directly deployed in your web server.

Hope this works for you.

SkeletonJSF-FCProject.zip

Share this post


Link to post
Share on other sites

hi all

 

 

 

i saw code its working fine but i got one problem that i want to do this code dynamic using database, but i am not able to add value using bean,can you help me.........plz

Share this post


Link to post
Share on other sites

OK.. As I see we can't add data dynamically without writing additional code to Tag library.

 

Alright that's fine, but here is another question/problem.

 

 

 

I have following code:

 

 

 

... debugMode="true" chartId="MyChart" filename="../FusionCharts/Column3D.swf" width="700" height="300" xml="#{ReportController.xmlString}"...

 

 

 

So, my backin bean can't generate. Here is what this code generates:

 

 

 

 

 

... dataXML=#{ReportController.xmlString} ...

 

 

 

 

 

Why ?

Edited by Guest

Share this post


Link to post
Share on other sites

OK.. I got the solution. The problem was that I had to bind value from Backing bean to that tag (lazy taking out parts of the code :hehe: ).

 

Here is my whole code for ChartTag.java

 

 

 

-------------------- START --------------------------------

 

package charts;

 

 

 

import javax.faces.application.Application;

 

import javax.faces.component.UIComponent;

 

import javax.faces.context.FacesContext;

 

import javax.faces.el.ValueBinding;

 

import javax.faces.webapp.UIComponentTag;

 

 

 

public class ChartTag extends UIComponentTag {

 

 

 

String chartId;

 

String filename;

 

String xml;

 

String url;

 

String width;

 

String height;

 

String debugMode;

 

String registerWithJS;

 

 

 

 

 

public String getChartId() {

 

return chartId;

 

}

 

 

 

public void setChartId(String id) {

 

this.chartId = id;

 

}

 

 

 

public String getFilename() {

 

return filename;

 

}

 

 

 

public void setFilename(String filename) {

 

this.filename = filename;

 

}

 

 

 

public String getXml() {

 

return xml;

 

}

 

 

 

public void setXml(String xml) {

 

this.xml = xml;

 

}

 

 

 

public String getUrl() {

 

return url;

 

}

 

 

 

public void setUrl(String url) {

 

this.url = url;

 

}

 

 

 

public String getWidth() {

 

return width;

 

}

 

 

 

public void setWidth(String width) {

 

this.width = width;

 

}

 

 

 

public String getHeight() {

 

return height;

 

}

 

 

 

public void setHeight(String height) {

 

this.height = height;

 

}

 

 

 

public String getDebugMode() {

 

return debugMode;

 

}

 

 

 

public void setDebugMode(String debugMode) {

 

this.debugMode = debugMode;

 

}

 

 

 

public String getRegisterWithJS() {

 

return registerWithJS;

 

}

 

 

 

public void setRegisterWithJS(String registerWithJS) {

 

this.registerWithJS = registerWithJS;

 

}

 

 

 

@Override

 

public void release() {

 

// the super class method should be called

 

super.release();

 

chartId = null;

 

filename = null;

 

xml = null;

 

url = null;

 

width = null;

 

height = null;

 

debugMode = null;

 

registerWithJS = null;

 

}

 

 

 

@Override

 

protected void setProperties(UIComponent component) {

 

// the super class method should be called

 

super.setProperties(component);

 

 

 

FacesContext context = FacesContext.getCurrentInstance();

 

Application application = context.getApplication();

 

ValueBinding binding = application.createValueBinding(xml);

 

 

 

 

 

 

 

if (chartId != null) {

 

component.getAttributes().put("id", chartId);

 

}

 

if (filename != null) {

 

component.getAttributes().put("filename", filename);

 

}

 

if (xml != null) {

 

component.setValueBinding("xml", binding);

 

}

 

if (url != null) {

 

component.getAttributes().put("url", url);

 

}

 

if (width != null) {

 

component.getAttributes().put("width", width);

 

}

 

if (height != null) {

 

component.getAttributes().put("height", height);

 

}

 

if (debugMode != null) {

 

component.getAttributes().put("debugMode", debugMode);

 

}

 

if (registerWithJS != null) {

 

component.getAttributes().put("registerWithJS", registerWithJS);

 

}

 

}

 

 

 

public String getComponentType() {

 

return "chart";

 

}

 

 

 

public String getRendererType() {

 

// null means the component renders itself

 

return null;

 

}

 

}

 

 

 

------------------------------ END -------------------------------------

Edited by Guest

Share this post


Link to post
Share on other sites

Thanks for the tip and solution. I have now added support for ValueBinding from Backing bean in the tag library.

Changes made:

1. xml now is no longer an attribute. You can provide the xml as part of the body of the tag.

2. fc:render and fc:renderHTML are the tags to be used.

3. Binding value can be used for any attribute or the body value.

Attached you can find: fusionchartstaglib.zip containing the fusionchartstaglib.jar

Srividya

fusionchartstaglib.zip

Share this post


Link to post
Share on other sites

I have also created a few examples for using the taglibrary.

You can find the sample application attached.

Please place the neccessary jar files in the WEB-INF/lib folder of this application. I had used the following jars:

  1. commons-beanutils.jar
  2. commons-collections.jar
  3. commons-digester.jar
  4. commons-logging.jar
  5. jsf-api.jar
  6. jsf-impl.jar
  7. jstl.jar
  8. standard.jar

Also, place the FusionCharts folder with the swf files and js.

Srividya

FusionChartsFree_JSF.zip

Edited by Guest

Share this post


Link to post
Share on other sites

The usage of this taglib in Seam application would be similar. Use the same tags in your jsp where you want the chart to be rendered. The actual xml content can be obtained from an action and stored in a bean. Supply the xml from the bean to the fc:render or fc:renderHTML tag.

I haven't tried it in Seam, just trying to provide guidelines to you.

Share this post


Link to post
Share on other sites

this taglib works very well in a seam app. Thanks very much to srividya_sharma:P

 

I used it in a portlet container+seam+jsf+facelets+richfaces environment.

 

just add that fusioncharts.taglib.xml under META-INF folder in that jar file to make it works well with facelets.

 

sorry for my english...

Share this post


Link to post
Share on other sites

ok, this message is now going to be more terse and cranky than I intended, since I just spent a lot of time typing it in and the forum barfed :-(

 

 

 

Is the source code for the fusionchartstaglib.jar attached to the forum above available? There is an error related to the "backing bean" method. I have got to the point of successfully embedding charts in JSF pages generated by the Netbeans 6.5 Visual Web JSF editor, with pages something like this:

 

 

 


code in attachment...

 

 

 

The backing bean Page1 is trivial, with chartData just returning the Data.XML shown in the example. The problem is that the JSF tag is being emitted onto the generated page, as follows:

 

 

 


code in attachment

 

 

 

which means that the generated Script is invalid and the chart does not render to the page. Using has a similar problem - the chart renders but the "#{Page1.chartData}" string is also painted into the page.

 

 

 

It appears to me like some debug code got left in...

 

 

 

Addendum: SON OF A )(*&@#$! the code would not display in this forum. Code is in attachment

problem.txt

Edited by Guest

Share this post


Link to post
Share on other sites

*bump*

 

 

 

I have downloaded the tag library from http://www.fusioncharts.com/forum/FindPost10442.aspx, but there is an issue with it. The source code in the same forum thread, posted earlier, is not for that tag library JAR - is the source code for the posted JAR available, or do i need to reinvent it...

 

 

 

RobertHook (2/3/2009)
srividya_sharma (2/3/2009)
Please verify that you are using the tag library from this post: http://www.fusioncharts.com/forum/FindPost10442.aspx

 

 

 

Yes, it's definitely the library from this post, or to be precise, the library zip that's linked further down in the post, after the author made changes.

Share this post


Link to post
Share on other sites
srividya_sharma (2/9/2009)
Here isthe source code of the tag library. It might have some more modifications to it, since the jar that you had downloaded. So, if you are using the source, please create the corresponding jar.

 

 

 

Thank you for that, I will download and build and test, and advise how it's gone.

Share this post


Link to post
Share on other sites
RobertHook (2/10/2009)Thank you for that, I will download and build and test, and advise how it's gone.

 

 

 

Not much luck I'm afraid. I'm using Netbeans 6.5, and so created a new project, told it to use the JSF1.2 libraries (the only option available), but two problems then arise.

 

 

 

First, javax.servlet.jsp.JspException and javax.servlet.jsp.tagext.BodyContent aren't found in the JSF1.2 libraries - can you suggest where these come from, or rather where you are getting them from.

 

 

 

Secondly, in the 1.2 libraries, javax.faces.webapp.UIComponentBodyTag and javax.faces.el.ValueBinding are deprecated, and at compile time the compiler is saying that it cannot find appropriate symbols to resolve them. All of which suggests that maybe I need a 1.0 or 1.1 JSF library, which makes me a bit worried about deploying in a JSF1.2 environment.

 

 

 

Your advice, suggestion and thoughts are (rather urgently) desired.

Share this post


Link to post
Share on other sites

javax.servlet.jsp.tagext.BodyContent  should be available in jsp-api.jar. Usually present in the webserver. Please include it for compilation in Netbeans.

Yes, the tag lib (1.0) uses those two deprecated classes.

I can try to come up with a 1.2 version of the taglib, if required.

Share this post


Link to post
Share on other sites
srividya_sharma (2/11/2009)
javax.servlet.jsp.tagext.BodyContent should be available in jsp-api.jar. Usually present in the webserver. Please include it for compilation in Netbeans.

 

 

 

Yes, the tag lib (1.0) uses those two deprecated classes.

 

 

 

I can try to come up with a 1.2 version of the taglib, if required.

 

 

 

Ok, I'll grab that jar out of the relevant application server and see how we go. In *theory* I should be able to get a 1.2 version going myself, based on the code you've supplied, and I'll report in a couple of days how I have gone. I hope that the final result of my tinkering is a complete NB6.5 project that I can put back to this forum.

Share this post


Link to post
Share on other sites

Any success on a version which doesnt insert the extra data to the page:

 

 

 

#{backingBean}.xml

 

 

 

???

 

 

 

I'd rather not go through the pain of debugging and generating my own jar file.

Share this post


Link to post
Share on other sites

I am having the same issue as in the post here:

http://www.fusioncharts.com/forum/FindPost11480.aspx

Extra text insterted into the page. From the follow ups it appears to be due to the fact we are using JSF 1.2.

I have started porting the code to JSF 1.2, but have not done a JSF component before and its taking some time. If you have a JSF 1.2 jar that would help.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now