Archive for the ‘java’ Category

Creating an iText pdf with embedded JFreeChart

Monday, March 17th, 2008

Charts are simple to make with JFreeChart and there are tons of examples on the web about how to generate them and save them as .jpg or .gif files. I ran into an issue however, where I needed to embed a chart into a pdf file. My first thoughts were to generate the charts as a .jpg file and embed them, but the pdfs looked a little choppy and didn’t print well.

To solve the problem you need to have the chart rendered as vector graphics and inserted into the pdf. The code required to do this ended up being simple, but I wasn’t able to find any good complete examples on the web. This is a simple working example I made for anyone else who finds themselves in this position.

Downloads:

To do an ant build, all you need to do is set j2ee.lib.dir in the build.properties file to a directory that contains the j2ee.jar (in your jdk or app server) and you are good to go. The war file should easily deploy on any app server.

Here is the meat of the code required:

docWriter = PdfWriter.getInstance(doc, baosPDF);
 
doc.addProducer();
doc.addCreator(this.getClass().getName());
doc.addTitle("jfreechart pdf");
doc.setPageSize(PageSize.LETTER);
 
doc.open();
 
// add some text to the document
doc.add(new Phrase("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."));
 
// build up the dataset for the char
XYSeriesCollection dataset = new XYSeriesCollection();
 
XYSeries series = new XYSeries("XYGraph");
series.add(1, 1);
series.add(2, 3);
series.add(3, 9);
series.add(4, 11);
 
dataset.addSeries(series);
 
// set up the chart
JFreeChart chart = ChartFactory.createXYLineChart("XY Chart Sample, non default font", // chart title
        "x-axis",   // domain axis label
        "y-axis",   // range axis label
        dataset,    // data
        PlotOrientation.VERTICAL,   // orientation
        true,   // include legend
        true,   // tooltips
        false   // urls
    );
 
// trick to change the default font of the chart
chart.setTitle(new TextTitle("XY Chart Sample, non default font", new java.awt.Font("Serif", Font.BOLD, 12)));
chart.setBackgroundPaint(Color.white);
chart.setBorderPaint(Color.black);
chart.setBorderStroke(new BasicStroke(1));
chart.setBorderVisible(true);
 
int width = 260;
int height = 250;
 
// get the direct pdf content
PdfContentByte dc = docWriter.getDirectContent();
 
// get a pdf template from the direct content
PdfTemplate tp = dc.createTemplate(width, height);
 
// create an AWT renderer from the pdf template
Graphics2D g2 = tp.createGraphics(width, height, new DefaultFontMapper() );
Rectangle2D r2D = new Rectangle2D.Double(0,0, width,height);
chart.draw(g2,r2D,null);
g2.dispose();
 
// add the rendered pdf template to the direct content
// you will have to play around with this because the chart is absolutely positioned.
// 38 is just a typical left margin
// docWriter.getVerticalPosition(true) will approximate the position that the content above the chart ended
dc.addTemplate(tp, 38, docWriter.getVerticalPosition(true)-height);

Sun Spots are now Open Source

Wednesday, January 30th, 2008

sunspot.jpgSun has announced that the Sun Spots are now fully open source. This means that the API as well as the Squawk VM are now fully open. The Squak VM itself is an interesting project. I will be curious to see how it compares against google’s Dalvik VM on small devices (that is whenever google releases or tells us more about Dalvik).

The press release seems to imply that the Sun Spot hardware will also be open source:

The open source release of the versatile Java technology-based Sun SPOT platform will include hardware, software and the Squawk Virtual Machine.

but this is the only mention I see of hardware in the press release and on the several sites dedicated to Sun Spot. I really hope they expand on this and show the world everything that is included in the OSS releases.

If the hardware is Open Source that could make way for some third parties to make their own implementations, similar to the different implementaitons of Arduino. This would be especially welcome given the crazy high cost of a Sun Spot device ($250 or so per device compared with $20-150 depending on configuration for Arduino). Yea, Yea, I know Sun Spot is way awesomer than Arduino, but if I am going to make a little device to attach to the top of a rocket or the under carriage of my skateboard, you better believe I am going to be looking for the cheapest hardware I can find.

Building Chandler Server

Thursday, December 13th, 2007

I’ve been using Chandler for a few weeks now to try to organize my life.

I tried building Chandler Server from source today. Following the instructions on their site give’s me a build error because it can’t find a copy of Apache Abdera

Some of the error:

/mnt/drive2/chandler/cosmo/cosmo/src/main/java/org/osaf/cosmo/atom/provider/UserTarget.java:[20,46] cannot find symbol
symbol  : class AbstractTarget
location: package org.apache.abdera.protocol.server.impl
 
/mnt/drive2/chandler/cosmo/cosmo/src/main/java/org/osaf/cosmo/atom/provider/UserTarget.java:[29,32] cannot find symbol
symbol: class AbstractTarget
public class UserTarget extends AbstractTarget {
 
/mnt/drive2/chandler/cosmo/cosmo/src/main/java/org/osaf/cosmo/atom/provider/BaseItemTarget.java:[22,46] cannot find symbol
symbol  : class AbstractTarget
location: package org.apache.abdera.protocol.server.impl
 
/mnt/drive2/chandler/cosmo/cosmo/src/main/java/org/osaf/cosmo/atom/provider/BaseItemTarget.java:[25,45] cannot find symbol
symbol: class AbstractTarget
public abstract class BaseItemTarget extends AbstractTarget

After much fiddeling around, and even trying to install Abdera from source, I was able to get it to build by checking out everything related to cosmo and building that.

  • svn co http://svn.osafoundation.org/server/cosmo/trunk
  • cd trunk/cosmo
  • mvn package

ta-da.

I still get some errors with the unit tests, but I don’t know if those are serious or not yet.

Now let’s see if it run’s with Tomcat 6.0

Postfix + Javamail = disagreement

Sunday, December 9th, 2007

I had a server die on me last week and I needed to reinstall it as quickly as possible. It was running Fedora Core 4. I only had install media for Fedora core 6. I knew it would be a bit of a pain to update all of the config files for everything running on the server, but I figured now is as good a time as any. I would have updated to 7 or 8, but I didn’t have time to download those on CDs (I have 8 on dvd but the server doesn’t have a dvd drive).

Anyway. I updated everything and it all seemed to run swimmingly. I didn’t even have to configure anything too drastically different. I switched from Courier IMAP to Dovecot, but that is another story.

The issue that got me pulling my hair out last night was that my tomcat log kept showing odd smtp related error messages in the stack trace:

javax.mail.SendFailedException: Sending failed;
  nested exception is:
        class javax.mail.MessagingException: 501 5.5.4 Bad RET parameter syntax
        at javax.mail.Transport.send0(Transport.java:218)
        at javax.mail.Transport.send(Transport.java:80)
        at com.approachingpi.store.order.Notification.sendMail(Notification.java:116)
        at com.approachingpi.store.order.Notification.run(Notification.java:56)
        at java.lang.Thread.run(Thread.java:595)

After a lot of digging, it seems that javamail sends the RET parameter as described in RFC-1891, even if it is not set up in the config file. Since this is an optional parameter, you would think that leaving it out of your properties file would make javamail not send it to the mail server. It seems it sends “RET=” rather than leaving it out.

It also seems that postfix v2.2.2 ignores “RET=”, but v2.3.3 is a little more strict and expects your parameter to have a value.

I don’t know what application is behaving improperly here. My guess is that postfix is doing the right thing, and that javamail should probably not send the RET parameter, but I guess they could argue that I just need to always configure it in my settings to make sure I’m compliant. (I am using javamail 1.3.0 btw, so it may have changed in newer versions)

to fix the problem, all I had to do was add these two lines to my javamail config properties file:
mail.smtp.dsn.ret=HDRS
mail.smtp.dsn.notify=NEVER

I found I also had to set the mail.smtp.dns.notify value too, because if I don’t I get this error:

javax.mail.SendFailedException: Sending failed;
  nested exception is:
        class javax.mail.SendFailedException: Invalid Addresses;
  nested exception is:
        class javax.mail.SendFailedException: 501 5.5.4 Error: Bad NOTIFY parameter syntax;
  nested exception is:
        class javax.mail.SendFailedException: 501 5.5.4 Error: Bad NOTIFY parameter syntax
        at javax.mail.Transport.send0(Transport.java:218)
        at javax.mail.Transport.send(Transport.java:80)
        at com.approachingpi.store.order.Notification.sendMail(Notification.java:116)
        at com.approachingpi.store.order.Notification.run(Notification.java:56)
        at java.lang.Thread.run(Thread.java:595)

It looks like javamail sends that along as blank as well. weird.