nomike Posted October 12, 2006 Share Posted October 12, 2006 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 More sharing options...
lucianc Posted October 12, 2006 Share Posted October 12, 2006 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 propertyCode: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 More sharing options...
nomike Posted October 12, 2006 Author Share Posted October 12, 2006 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 doCode: 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 PostmannPost edited by: nomike, at: 2006/10/12 13:42 Link to comment Share on other sites More sharing options...
lucianc Posted October 12, 2006 Share Posted October 12, 2006 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 More sharing options...
nomike Posted October 12, 2006 Author Share Posted October 12, 2006 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 theJVM; or change the input, output, and error streams.These functions are reserved for the EJB container. Allowing the enterprise bean to use these functionscould 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 More sharing options...
lucianc Posted October 12, 2006 Share Posted October 12, 2006 If your reports change at run time, a simple solution would be to have a report repository in a database. You can save JRXMLs (and serialized compiled reports) as CLOBs/BLOBs and access the data in your EJBs. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now