Jump to content
We've recently updated our Privacy Statement, available here ×

Generating Reports in a EJB 2.1 Session Bean


nomike

Recommended Posts

Hi!

 

I'm re-developing our existing business application using J2EE. We use JasperReport to generate reports with 4000+ Pages constructed using 100.000+ DB Records including Dependencies. So they are quite Huge. We are currently using a distributed Client Application with a small-footprint-server where every client has direct DB-Access.

 

Now as I need to reimplement the Application to make it use J2EE (EJB 2.1) I wanted to move the report-generation to the ApplicationServer (JBoss in our case) and created a Session Bean. It creates a Report and returns a JasperPrint object which is then displayed and printed on the swing-client.

 

However, jasper utilizes java.io a lot and does threading too, which are both permitted by the J2EE-Spec.

 

So how could I generate jasperreports in a performant-way without violating EJB Specs and without doing it on the client?

 

thx in Advance

 

nomike aka Michael Postmann

 

PS: It seems to work as an EJB-Bean, but I don't know if I should expect to run into problems...

Post edited by: nomike, at: 2006/10/12 10:17

Link to comment
Share on other sites

  • Replies 5
  • Created
  • Last Reply

Top Posters In This Topic

Popular Days

Top Posters In This Topic

JR uses threads for subreports by default. If this is an issue in your environment, you can switch to Javaflow continuations by setting the following JR property

Code:
net.sf.jasperreports.subreport.runner.factory=net.sf.jasperreports.engine.fill.JRContinuationSubreportRunnerFactory

 

You'll also need a Javaflow-enabled JR jar, so if you use JR >= 1.2.6 make sure you put jasperreports-x.y.z-javaflow.jar in your classpath.

 

Not sure what you meant when you said that JR uses java.io. Can you clarify that?

 

Are you using a file based report virtualizer? If so, you need to think what other external storage places you could use inside an EJB. I think that you can write a JDBC-based virtualizer, and if you finely tune your DB you can achieve decent performance..

 

Regards,

Lucian

Link to comment
Share on other sites

Thx for your support!

 

The thread thingy sounds good to me.

 

But I don't know what you mean/what is a "report virtualizer"?!?

 

I have a directory on Disk which contains our .jrxml and .jasper files. I then do

Code:
  public JasperPrint printCoupon(CouponVO coupon, String mapping, Integer userID) throws FinderException {
JRDataSource dataSource = new JRMapArrayDataSource(new Object[1]);

HashMap<String, Object> map = new HashMap<String, Object>();

CustomerVO cvo = getCustomerFromSomewhere();
KassaArticleVO kavo = getArticleFromSomewhere();
CouponTypeVO tcvo = getCouponTypeFromSomewhere();

map.put("amout", coupon.getAmount());
map.put("bookingCode", tcvo.getBookingCode());
map.put("buyerCity", cvo.getCity());
map.put("buyerFirstName", cvo.getFirstName());
/*...*/
map.put("TXT_copy", "Copy"«»);
map.put("coupon", null);
map.put("user", null);

try {
String reportName = getReportFileName(); // "C:\Reports\sampleReport.jasper"

return JasperFillManager.fillReport(reportName, map, dataSource);
}
catch (JRException ex) {
logger.fatal(ex);
return null;
}
}

 

This makes JasperReport load the .jasper file using java.io.File and others.

And Java.io.* must not be used in EJB according to EJB specs...

 

nomike aka Michael Postmann

Post edited by: nomike, at: 2006/10/12 13:42

Link to comment
Share on other sites

A virtualizer can be used to avoid keeping an entire JasperPrint report in memory, by virtualizing parts of the report data to an external storage (e.g. file system). People use a virtualizer to reduce the heap memory used when filling large reports.

 

I see that you are not using a virtualizer, but loading compiled report from the file system. You approach is wrong from the start: if you keep the compiled reports on the file system, how could you load them without using file I/O?

 

If you have static report templates, you could for example pack all your compiled reports into a jar file at build time, include this in the EJB classpath and load the compiled reports as resources through the classloader:

Code:

JasperReport jasperReport = JRLoader.loadObject(getClass().getResourceAsStream("/reports/sampleReport.jasper"«»));
JasperFillManager.fillReport(jasperReport, map, dataSource);

 

HTH,

Lucian

Link to comment
Share on other sites

Well, basically your solution sounds good, but it has two problems which make it unuseable for us:

 

First of all, the reports frequently change. So if we use a jar file and a classloader to load the reports we need to restart the application if a report changes which is inacceptable.

 

And secondly the all nice and good EJB Spec (*grmmmml* :angry: ) says:

 

The enterprise bean must not attempt to create a class loader; obtain the current class loader;
set the context class loader; set security manager; create a new security manager; stop the
JVM; or change the input, output, and error streams.
These functions are reserved for the EJB container. Allowing the enterprise bean to use these functions
could compromise security and decrease the container’s ability to properly manage the runtime environment.

 

thx, but I think I have to find another solution... :(

 

nomike aka Michael Postmann

Link to comment
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

×
×
  • Create New...